Merge "media: add undocumented exceptions to MediaCodec api."
diff --git a/Android.mk b/Android.mk
index 1df2af3..f9ac712 100644
--- a/Android.mk
+++ b/Android.mk
@@ -45,6 +45,7 @@
        core/java/android/content/EventLogTags.logtags \
        core/java/android/speech/tts/EventLogTags.logtags \
        core/java/android/webkit/EventLogTags.logtags \
+       core/java/com/android/internal/logging/EventLogTags.logtags \
 
 ## READ ME: ########################################################
 ##
@@ -151,6 +152,8 @@
 	core/java/android/hardware/display/IDisplayManager.aidl \
 	core/java/android/hardware/display/IDisplayManagerCallback.aidl \
 	core/java/android/hardware/display/IVirtualDisplayCallback.aidl \
+	core/java/android/hardware/fingerprint/IFingerprintService.aidl \
+	core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl \
 	core/java/android/hardware/hdmi/IHdmiControlCallback.aidl \
 	core/java/android/hardware/hdmi/IHdmiControlService.aidl \
 	core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl \
@@ -226,8 +229,6 @@
 	core/java/android/service/dreams/IDreamManager.aidl \
 	core/java/android/service/dreams/IDreamService.aidl \
 	core/java/android/service/persistentdata/IPersistentDataBlockService.aidl \
-	core/java/android/service/fingerprint/IFingerprintService.aidl \
-	core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl \
 	core/java/android/service/trust/ITrustAgentService.aidl \
 	core/java/android/service/trust/ITrustAgentServiceCallback.aidl \
 	core/java/android/service/voice/IVoiceInteractionService.aidl \
@@ -244,6 +245,7 @@
 	core/java/android/view/accessibility/IAccessibilityManagerClient.aidl \
 	core/java/android/view/IApplicationToken.aidl \
 	core/java/android/view/IAssetAtlas.aidl \
+	core/java/android/view/IGraphicsStats.aidl \
 	core/java/android/view/IInputFilter.aidl \
 	core/java/android/view/IInputFilterHost.aidl \
 	core/java/android/view/IOnKeyguardExitResult.aidl \
@@ -265,6 +267,7 @@
 	core/java/com/android/internal/app/IBatteryStats.aidl \
 	core/java/com/android/internal/app/IProcessStats.aidl \
 	core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl \
+	core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl \
 	core/java/com/android/internal/app/IVoiceInteractor.aidl \
 	core/java/com/android/internal/app/IVoiceInteractorCallback.aidl \
 	core/java/com/android/internal/app/IVoiceInteractorRequest.aidl \
diff --git a/api/current.txt b/api/current.txt
index d8d8998..26e977b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -92,6 +92,7 @@
     field public static final java.lang.String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
     field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
     field public static final java.lang.String NFC = "android.permission.NFC";
+    field public static final java.lang.String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
     field public static final deprecated java.lang.String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
     field public static final java.lang.String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
     field public static final java.lang.String READ_CALENDAR = "android.permission.READ_CALENDAR";
@@ -303,8 +304,8 @@
     field public static final int alphabeticShortcut = 16843235; // 0x10101e3
     field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
     field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
-    field public static final int amPmBackgroundColor = 16843941; // 0x10104a5
-    field public static final int amPmTextColor = 16843940; // 0x10104a4
+    field public static final deprecated int amPmBackgroundColor = 16843941; // 0x10104a5
+    field public static final deprecated int amPmTextColor = 16843940; // 0x10104a4
     field public static final int ambientShadowAlpha = 16843966; // 0x10104be
     field public static final int angle = 16843168; // 0x10101a0
     field public static final int animateFirstView = 16843477; // 0x10102d5
@@ -329,6 +330,7 @@
     field public static final int autoStart = 16843445; // 0x10102b5
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
+    field public static final int autoVerify = 16844010; // 0x10104ea
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -352,6 +354,7 @@
     field public static final int bottomRightRadius = 16843180; // 0x10101ac
     field public static final int breadCrumbShortTitle = 16843524; // 0x1010304
     field public static final int breadCrumbTitle = 16843523; // 0x1010303
+    field public static final int breakStrategy = 16844011; // 0x10104eb
     field public static final int bufferType = 16843086; // 0x101014e
     field public static final int button = 16843015; // 0x1010107
     field public static final int buttonBarButtonStyle = 16843567; // 0x101032f
@@ -650,13 +653,13 @@
     field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
     field public static final int hardwareAccelerated = 16843475; // 0x10102d3
     field public static final int hasCode = 16842764; // 0x101000c
-    field public static final int headerAmPmTextAppearance = 16843936; // 0x10104a0
+    field public static final deprecated int headerAmPmTextAppearance = 16843936; // 0x10104a0
     field public static final int headerBackground = 16843055; // 0x101012f
     field public static final deprecated int headerDayOfMonthTextAppearance = 16843927; // 0x1010497
     field public static final int headerDividersEnabled = 16843310; // 0x101022e
     field public static final deprecated int headerMonthTextAppearance = 16843926; // 0x1010496
-    field public static final int headerTimeTextAppearance = 16843935; // 0x101049f
-    field public static final int headerYearTextAppearance = 16843928; // 0x1010498
+    field public static final deprecated int headerTimeTextAppearance = 16843935; // 0x101049f
+    field public static final deprecated int headerYearTextAppearance = 16843928; // 0x1010498
     field public static final int height = 16843093; // 0x1010155
     field public static final int hideOnContentScroll = 16843843; // 0x1010443
     field public static final int hint = 16843088; // 0x1010150
@@ -1197,6 +1200,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
+    field public static final int supportsAssistGesture = 16844012; // 0x10104ec
     field public static final int supportsRtl = 16843695; // 0x10103af
     field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
     field public static final int supportsUploading = 16843419; // 0x101029b
@@ -1360,6 +1364,7 @@
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
+    field public static final int usesCleartextTraffic = 16844009; // 0x10104e9
     field public static final int value = 16842788; // 0x1010024
     field public static final int valueFrom = 16843486; // 0x10102de
     field public static final int valueTo = 16843487; // 0x10102df
@@ -1454,7 +1459,7 @@
     field public static final int x = 16842924; // 0x10100ac
     field public static final int xlargeScreens = 16843455; // 0x10102bf
     field public static final int y = 16842925; // 0x10100ad
-    field public static final int yearListItemTextAppearance = 16843929; // 0x1010499
+    field public static final deprecated int yearListItemTextAppearance = 16843929; // 0x1010499
     field public static final deprecated int yearListSelectorColor = 16843930; // 0x101049a
     field public static final int yesNoPreferenceStyle = 16842896; // 0x1010090
     field public static final int zAdjustment = 16843201; // 0x10101c1
@@ -1691,6 +1696,8 @@
 
   public static final class R.id {
     ctor public R.id();
+    field public static final int accessibilityActionScrollToPosition = 16908342; // 0x1020036
+    field public static final int accessibilityActionShowOnScreen = 16908341; // 0x1020035
     field public static final int addToDictionary = 16908330; // 0x102002a
     field public static final int background = 16908288; // 0x1020000
     field public static final int button1 = 16908313; // 0x1020019
@@ -2733,6 +2740,7 @@
   }
 
   public class AccountManager {
+    method public boolean accountAuthenticated(android.accounts.Account);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
     method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
@@ -2793,6 +2801,7 @@
     field public static final java.lang.String KEY_ERROR_CODE = "errorCode";
     field public static final java.lang.String KEY_ERROR_MESSAGE = "errorMessage";
     field public static final java.lang.String KEY_INTENT = "intent";
+    field public static final java.lang.String KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH = "lastAuthenticatedTimeMillisEpoch";
     field public static final java.lang.String KEY_PASSWORD = "password";
     field public static final java.lang.String KEY_USERDATA = "userdata";
     field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
@@ -3546,6 +3555,7 @@
   public class ActivityManager {
     method public int addAppTask(android.app.Activity, android.content.Intent, android.app.ActivityManager.TaskDescription, android.graphics.Bitmap);
     method public boolean clearApplicationUserData();
+    method public void clearWatchHeapLimit();
     method public void dumpPackageState(java.io.FileDescriptor, java.lang.String);
     method public android.util.Size getAppTaskThumbnailSize();
     method public java.util.List<android.app.ActivityManager.AppTask> getAppTasks();
@@ -3572,6 +3582,8 @@
     method public void moveTaskToFront(int, int);
     method public void moveTaskToFront(int, int, android.os.Bundle);
     method public deprecated void restartPackage(java.lang.String);
+    method public void setWatchHeapLimit(long);
+    field public static final java.lang.String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT";
     field public static final int LOCK_TASK_MODE_LOCKED = 1; // 0x1
     field public static final int LOCK_TASK_MODE_NONE = 0; // 0x0
     field public static final int LOCK_TASK_MODE_PINNED = 2; // 0x2
@@ -4701,6 +4713,7 @@
     field public static final java.lang.String CATEGORY_PROGRESS = "progress";
     field public static final java.lang.String CATEGORY_PROMO = "promo";
     field public static final java.lang.String CATEGORY_RECOMMENDATION = "recommendation";
+    field public static final java.lang.String CATEGORY_REMINDER = "reminder";
     field public static final java.lang.String CATEGORY_SERVICE = "service";
     field public static final java.lang.String CATEGORY_SOCIAL = "social";
     field public static final java.lang.String CATEGORY_STATUS = "status";
@@ -5426,10 +5439,12 @@
 
   public static final class VoiceInteractor.PickOptionRequest.Option implements android.os.Parcelable {
     ctor public VoiceInteractor.PickOptionRequest.Option(java.lang.CharSequence);
+    ctor public VoiceInteractor.PickOptionRequest.Option(java.lang.CharSequence, int);
     method public android.app.VoiceInteractor.PickOptionRequest.Option addSynonym(java.lang.CharSequence);
     method public int countSynonyms();
     method public int describeContents();
     method public android.os.Bundle getExtras();
+    method public int getIndex();
     method public java.lang.CharSequence getLabel();
     method public java.lang.CharSequence getSynonymAt(int);
     method public void setExtras(android.os.Bundle);
@@ -5699,6 +5714,7 @@
     field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
+    field public static final java.lang.String EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS = "android.app.extra.PROVISIONING_RESET_PROTECTION_PARAMETERS";
     field public static final java.lang.String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
     field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
@@ -5720,6 +5736,7 @@
     field public static final int KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS = 8; // 0x8
     field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1; // 0x1
     field public static final java.lang.String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning";
+    field public static final java.lang.String MIME_TYPE_PROVISIONING_NFC_V2 = "application/com.android.managedprovisioning.v2";
     field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000
     field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000
     field public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 32768; // 0x8000
@@ -5905,6 +5922,37 @@
     field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
   }
 
+  public class NetworkStatsManager {
+    method public android.app.usage.NetworkUsageStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkUsageStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkUsageStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkUsageStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkUsageStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+  }
+
+  public final class NetworkUsageStats implements java.lang.AutoCloseable {
+    method public void close();
+    method public boolean getNextBucket(android.app.usage.NetworkUsageStats.Bucket);
+    method public boolean hasNextBucket();
+  }
+
+  public static class NetworkUsageStats.Bucket {
+    ctor public NetworkUsageStats.Bucket();
+    method public long getEndTimeStamp();
+    method public long getRxBytes();
+    method public long getRxPackets();
+    method public long getStartTimeStamp();
+    method public int getState();
+    method public long getTxBytes();
+    method public long getTxPackets();
+    method public int getUid();
+    field public static final int STATE_ALL = -1; // 0xffffffff
+    field public static final int STATE_DEFAULT = 1; // 0x1
+    field public static final int STATE_FOREGROUND = 2; // 0x2
+    field public static final int UID_REMOVED = -4; // 0xfffffffc
+    field public static final int UID_TETHERING = -5; // 0xfffffffb
+  }
+
   public final class UsageEvents implements android.os.Parcelable {
     method public int describeContents();
     method public boolean getNextEvent(android.app.usage.UsageEvents.Event);
@@ -6954,6 +7002,7 @@
     field public static final int SCAN_MODE_BALANCED = 1; // 0x1
     field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
     field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
+    field public static final int SCAN_MODE_OPPORTUNISTIC = -1; // 0xffffffff
   }
 
   public static final class ScanSettings.Builder {
@@ -7562,6 +7611,7 @@
     field public static final int MODE_PRIVATE = 0; // 0x0
     field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
     field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
+    field public static final java.lang.String NETWORK_STATS_SERVICE = "netstats";
     field public static final java.lang.String NFC_SERVICE = "nfc";
     field public static final java.lang.String NOTIFICATION_SERVICE = "notification";
     field public static final java.lang.String NSD_SERVICE = "servicediscovery";
@@ -7967,6 +8017,7 @@
     field public static final java.lang.String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED";
     field public static final java.lang.String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";
     field public static final java.lang.String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY";
+    field public static final java.lang.String ACTION_PROCESS_TEXT = "android.intent.action.PROCESS_TEXT";
     field public static final java.lang.String ACTION_PROVIDER_CHANGED = "android.intent.action.PROVIDER_CHANGED";
     field public static final java.lang.String ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK";
     field public static final java.lang.String ACTION_REBOOT = "android.intent.action.REBOOT";
@@ -8067,6 +8118,8 @@
     field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
     field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
     field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
+    field public static final java.lang.String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
+    field public static final java.lang.String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
     field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
     field public static final java.lang.String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
     field public static final java.lang.String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
@@ -8217,6 +8270,8 @@
     field public static final int NO_MATCH_CATEGORY = -4; // 0xfffffffc
     field public static final int NO_MATCH_DATA = -2; // 0xfffffffe
     field public static final int NO_MATCH_TYPE = -1; // 0xffffffff
+    field public static final java.lang.String SCHEME_HTTP = "http";
+    field public static final java.lang.String SCHEME_HTTPS = "https";
     field public static final int SYSTEM_HIGH_PRIORITY = 1000; // 0x3e8
     field public static final int SYSTEM_LOW_PRIORITY = -1000; // 0xfffffc18
   }
@@ -8338,6 +8393,7 @@
     ctor public RestrictionEntry(java.lang.String, boolean);
     ctor public RestrictionEntry(java.lang.String, java.lang.String[]);
     ctor public RestrictionEntry(java.lang.String, int);
+    ctor public RestrictionEntry(java.lang.String, android.content.RestrictionEntry[], boolean);
     ctor public RestrictionEntry(android.os.Parcel);
     method public int describeContents();
     method public java.lang.String[] getAllSelectedStrings();
@@ -8346,6 +8402,7 @@
     method public java.lang.String getDescription();
     method public int getIntValue();
     method public java.lang.String getKey();
+    method public android.content.RestrictionEntry[] getRestrictions();
     method public boolean getSelectedState();
     method public java.lang.String getSelectedString();
     method public java.lang.String getTitle();
@@ -8357,6 +8414,7 @@
     method public void setChoiceValues(android.content.Context, int);
     method public void setDescription(java.lang.String);
     method public void setIntValue(int);
+    method public void setRestrictions(android.content.RestrictionEntry[]);
     method public void setSelectedState(boolean);
     method public void setSelectedString(java.lang.String);
     method public void setTitle(java.lang.String);
@@ -8364,6 +8422,8 @@
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.RestrictionEntry> CREATOR;
     field public static final int TYPE_BOOLEAN = 1; // 0x1
+    field public static final int TYPE_BUNDLE = 7; // 0x7
+    field public static final int TYPE_BUNDLE_ARRAY = 8; // 0x8
     field public static final int TYPE_CHOICE = 2; // 0x2
     field public static final int TYPE_INTEGER = 5; // 0x5
     field public static final int TYPE_MULTI_SELECT = 4; // 0x4
@@ -8372,6 +8432,7 @@
   }
 
   public class RestrictionsManager {
+    method public static android.os.Bundle convertRestrictionsToBundle(java.util.List<android.content.RestrictionEntry>);
     method public android.content.Intent createLocalApprovalIntent();
     method public android.os.Bundle getApplicationRestrictions();
     method public java.util.List<android.content.RestrictionEntry> getManifestRestrictions(java.lang.String);
@@ -8693,6 +8754,7 @@
     field public static final int FLAG_SYSTEM = 1; // 0x1
     field public static final int FLAG_TEST_ONLY = 256; // 0x100
     field public static final int FLAG_UPDATED_SYSTEM_APP = 128; // 0x80
+    field public static final int FLAG_USES_CLEARTEXT_TRAFFIC = 134217728; // 0x8000000
     field public static final int FLAG_VM_SAFE_MODE = 16384; // 0x4000
     field public java.lang.String backupAgentName;
     field public java.lang.String className;
@@ -8795,6 +8857,25 @@
     field public java.lang.String targetPackage;
   }
 
+  public final class IntentFilterVerificationInfo implements android.os.Parcelable {
+    ctor public IntentFilterVerificationInfo();
+    ctor public IntentFilterVerificationInfo(java.lang.String, java.lang.String[]);
+    ctor public IntentFilterVerificationInfo(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    ctor public IntentFilterVerificationInfo(android.os.Parcel);
+    method public int describeContents();
+    method public java.lang.String[] getDomains();
+    method public java.lang.String getDomainsString();
+    method public java.lang.String getPackageName();
+    method public int getStatus();
+    method public java.lang.String getStatusString();
+    method public static java.lang.String getStatusStringFromValue(int);
+    method public void readFromXml(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void setStatus(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    method public void writeToXml(org.xmlpull.v1.XmlSerializer) throws java.io.IOException;
+    field public static final android.os.Parcelable.Creator<android.content.pm.IntentFilterVerificationInfo> CREATOR;
+  }
+
   public class LabeledIntent extends android.content.Intent {
     ctor public LabeledIntent(android.content.Intent, java.lang.String, int, int);
     ctor public LabeledIntent(android.content.Intent, java.lang.String, java.lang.CharSequence, int);
@@ -9023,6 +9104,7 @@
     method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
     method public abstract java.lang.String getInstallerPackageName(java.lang.String);
     method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(java.lang.String);
     method public abstract android.content.Intent getLaunchIntentForPackage(java.lang.String);
     method public abstract android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
     method public abstract java.lang.String getNameForUid(int);
@@ -9109,6 +9191,7 @@
     field public static final java.lang.String FEATURE_LOCATION_NETWORK = "android.hardware.location.network";
     field public static final java.lang.String FEATURE_MANAGED_USERS = "android.software.managed_users";
     field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone";
+    field public static final java.lang.String FEATURE_MIDI = "android.software.midi";
     field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc";
     field public static final java.lang.String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce";
     field public static final java.lang.String FEATURE_OPENGLES_EXTENSION_PACK = "android.hardware.opengles.aep";
@@ -9378,11 +9461,10 @@
 
   public class ColorStateList implements android.os.Parcelable {
     ctor public ColorStateList(int[][], int[]);
-    method public void applyTheme(android.content.res.Resources.Theme);
-    method public boolean canApplyTheme();
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
+    method public int getChangingConfigurations();
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
@@ -11100,7 +11182,9 @@
     field public static final int JPEG = 256; // 0x100
     field public static final int NV16 = 16; // 0x10
     field public static final int NV21 = 17; // 0x11
+    field public static final int PRIVATE = 34; // 0x22
     field public static final int RAW10 = 37; // 0x25
+    field public static final int RAW12 = 38; // 0x26
     field public static final int RAW_SENSOR = 32; // 0x20
     field public static final int RGB_565 = 4; // 0x4
     field public static final int UNKNOWN = 0; // 0x0
@@ -11316,6 +11400,7 @@
     method public int getTextWidths(java.lang.String, float[]);
     method public android.graphics.Typeface getTypeface();
     method public android.graphics.Xfermode getXfermode();
+    method public boolean hasGlyph(java.lang.String);
     method public final boolean isAntiAlias();
     method public final boolean isDither();
     method public boolean isElegantTextHeight();
@@ -11896,9 +11981,12 @@
 
   public class AnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
     ctor public AnimatedVectorDrawable();
+    method public void addListener(android.animation.Animator.AnimatorListener);
     method public void draw(android.graphics.Canvas);
+    method public java.util.List<android.animation.Animator.AnimatorListener> getListeners();
     method public int getOpacity();
     method public boolean isRunning();
+    method public void removeListener(android.animation.Animator.AnimatorListener);
     method public void setAlpha(int);
     method public void setColorFilter(android.graphics.ColorFilter);
     method public void start();
@@ -14379,6 +14467,8 @@
     field public static final int CHANNEL_OUT_SURROUND = 1052; // 0x41c
     field public static final int ENCODING_AC3 = 5; // 0x5
     field public static final int ENCODING_DEFAULT = 1; // 0x1
+    field public static final int ENCODING_DTS = 7; // 0x7
+    field public static final int ENCODING_DTS_HD = 8; // 0x8
     field public static final int ENCODING_E_AC3 = 6; // 0x6
     field public static final int ENCODING_INVALID = 0; // 0x0
     field public static final int ENCODING_PCM_16BIT = 2; // 0x2
@@ -14572,6 +14662,14 @@
     field public static final int SUCCESS = 0; // 0x0
   }
 
+  public static class AudioRecord.Builder {
+    ctor public AudioRecord.Builder();
+    method public android.media.AudioRecord build() throws java.lang.UnsupportedOperationException;
+    method public android.media.AudioRecord.Builder setAudioFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioRecord.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioRecord.Builder setCapturePreset(int) throws java.lang.IllegalArgumentException;
+  }
+
   public static abstract interface AudioRecord.OnRecordPositionUpdateListener {
     method public abstract void onMarkerReached(android.media.AudioRecord);
     method public abstract void onPeriodicNotification(android.media.AudioRecord);
@@ -14643,6 +14741,16 @@
     field public static final int WRITE_NON_BLOCKING = 1; // 0x1
   }
 
+  public static class AudioTrack.Builder {
+    ctor public AudioTrack.Builder();
+    method public android.media.AudioTrack build() throws java.lang.UnsupportedOperationException;
+    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 setSessionId(int) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
+  }
+
   public static abstract interface AudioTrack.OnPlaybackPositionUpdateListener {
     method public abstract void onMarkerReached(android.media.AudioTrack);
     method public abstract void onPeriodicNotification(android.media.AudioTrack);
@@ -15193,6 +15301,7 @@
     method public android.graphics.Bitmap getIconBitmap();
     method public android.net.Uri getIconUri();
     method public java.lang.String getMediaId();
+    method public android.net.Uri getMediaUri();
     method public java.lang.CharSequence getSubtitle();
     method public java.lang.CharSequence getTitle();
     method public void writeToParcel(android.os.Parcel, int);
@@ -15207,6 +15316,7 @@
     method public android.media.MediaDescription.Builder setIconBitmap(android.graphics.Bitmap);
     method public android.media.MediaDescription.Builder setIconUri(android.net.Uri);
     method public android.media.MediaDescription.Builder setMediaId(java.lang.String);
+    method public android.media.MediaDescription.Builder setMediaUri(android.net.Uri);
     method public android.media.MediaDescription.Builder setSubtitle(java.lang.CharSequence);
     method public android.media.MediaDescription.Builder setTitle(java.lang.CharSequence);
   }
@@ -15880,6 +15990,23 @@
     method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
   }
 
+  public final class MediaSync {
+    ctor public MediaSync();
+    method public void configureAudioTrack(android.media.AudioTrack, int);
+    method public void configureSurface(android.view.Surface);
+    method public final android.view.Surface createInputSurface();
+    method public void queueAudio(java.nio.ByteBuffer, int, int, long);
+    method public final void release();
+    method public void setCallback(android.media.MediaSync.Callback, android.os.Handler);
+    method public void setPlaybackRate(float, int);
+    field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0; // 0x0
+  }
+
+  public static abstract class MediaSync.Callback {
+    ctor public MediaSync.Callback();
+    method public abstract void onReturnAudioBuffer(android.media.MediaSync, java.nio.ByteBuffer, int);
+  }
+
   public class MediaSyncEvent {
     method public static android.media.MediaSyncEvent createEvent(int) throws java.lang.IllegalArgumentException;
     method public int getAudioSessionId();
@@ -16634,6 +16761,18 @@
 
 package android.media.midi {
 
+  public final class MidiDevice implements java.io.Closeable {
+    method public void close() throws java.io.IOException;
+    method public android.media.midi.MidiDevice.MidiConnection connectPorts(android.media.midi.MidiInputPort, int);
+    method public android.media.midi.MidiDeviceInfo getInfo();
+    method public android.media.midi.MidiInputPort openInputPort(int);
+    method public android.media.midi.MidiOutputPort openOutputPort(int);
+  }
+
+  public class MidiDevice.MidiConnection implements java.io.Closeable {
+    method public void close() throws java.io.IOException;
+  }
+
   public final class MidiDeviceInfo implements android.os.Parcelable {
     method public int describeContents();
     method public int getId();
@@ -16690,6 +16829,25 @@
     method public void onReceive(byte[], int, int, long) throws java.io.IOException;
   }
 
+  public final class MidiManager {
+    method public android.media.midi.MidiDeviceInfo[] getDeviceList();
+    method public void openDevice(android.media.midi.MidiDeviceInfo, android.media.midi.MidiManager.DeviceOpenCallback, android.os.Handler);
+    method public void registerDeviceCallback(android.media.midi.MidiManager.DeviceCallback, android.os.Handler);
+    method public void unregisterDeviceCallback(android.media.midi.MidiManager.DeviceCallback);
+  }
+
+  public static class MidiManager.DeviceCallback {
+    ctor public MidiManager.DeviceCallback();
+    method public void onDeviceAdded(android.media.midi.MidiDeviceInfo);
+    method public void onDeviceRemoved(android.media.midi.MidiDeviceInfo);
+    method public void onDeviceStatusChanged(android.media.midi.MidiDeviceStatus);
+  }
+
+  public static abstract class MidiManager.DeviceOpenCallback {
+    ctor public MidiManager.DeviceOpenCallback();
+    method public abstract void onDeviceOpened(android.media.midi.MidiDeviceInfo, android.media.midi.MidiDevice);
+  }
+
   public final class MidiOutputPort extends android.media.midi.MidiSender implements java.io.Closeable {
     method public void close() throws java.io.IOException;
     method public void connect(android.media.midi.MidiReceiver);
@@ -17024,6 +17182,7 @@
     method public void play();
     method public void playFromMediaId(java.lang.String, android.os.Bundle);
     method public void playFromSearch(java.lang.String, android.os.Bundle);
+    method public void playFromUri(android.net.Uri, android.os.Bundle);
     method public void rewind();
     method public void seekTo(long);
     method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
@@ -17071,6 +17230,7 @@
     method public void onPlay();
     method public void onPlayFromMediaId(java.lang.String, android.os.Bundle);
     method public void onPlayFromSearch(java.lang.String, android.os.Bundle);
+    method public void onPlayFromUri(android.net.Uri, android.os.Bundle);
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.media.Rating);
@@ -17125,6 +17285,7 @@
     field public static final long ACTION_PLAY = 4L; // 0x4L
     field public static final long ACTION_PLAY_FROM_MEDIA_ID = 1024L; // 0x400L
     field public static final long ACTION_PLAY_FROM_SEARCH = 2048L; // 0x800L
+    field public static final long ACTION_PLAY_FROM_URI = 8192L; // 0x2000L
     field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
@@ -17377,6 +17538,10 @@
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
     field public static final java.lang.String META_DATA_CONTENT_RATING_SYSTEMS = "android.media.tv.metadata.CONTENT_RATING_SYSTEMS";
+    field public static final long TIME_SHIFT_INVALID_TIME = -9223372036854775808L; // 0x8000000000000000L
+    field public static final int TIME_SHIFT_STATUS_AVAILABLE = 0; // 0x0
+    field public static final int TIME_SHIFT_STATUS_ERROR = 2; // 0x2
+    field public static final int TIME_SHIFT_STATUS_UNAVAILABLE = 1; // 0x1
     field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3
     field public static final int VIDEO_UNAVAILABLE_REASON_TUNING = 1; // 0x1
     field public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0; // 0x0
@@ -17411,6 +17576,8 @@
     method public void notifyChannelRetuned(android.net.Uri);
     method public void notifyContentAllowed();
     method public void notifyContentBlocked(android.media.tv.TvContentRating);
+    method public void notifyTimeShiftStartPositionChanged(long);
+    method public void notifyTimeShiftStatusChanged(int);
     method public void notifyTrackSelected(int, java.lang.String);
     method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>);
     method public void notifyVideoAvailable();
@@ -17427,6 +17594,11 @@
     method public abstract void onSetStreamVolume(float);
     method public abstract boolean onSetSurface(android.view.Surface);
     method public void onSurfaceChanged(int, int, int);
+    method public long onTimeShiftGetCurrentPosition();
+    method public void onTimeShiftPause();
+    method public void onTimeShiftResume();
+    method public void onTimeShiftSeekTo(long);
+    method public void onTimeShiftSetPlaybackRate(float, int);
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
     method public abstract boolean onTune(android.net.Uri);
@@ -17475,19 +17647,31 @@
     method public java.util.List<android.media.tv.TvTrackInfo> getTracks(int);
     method protected void onLayout(boolean, int, int, int, int);
     method public boolean onUnhandledInputEvent(android.view.InputEvent);
+    method public void registerTimeShiftPositionCallback(android.media.tv.TvView.TimeShiftPositionCallback);
     method public void reset();
     method public void selectTrack(int, java.lang.String);
     method public void setCallback(android.media.tv.TvView.TvInputCallback);
     method public void setCaptionEnabled(boolean);
     method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
     method public void setStreamVolume(float);
+    method public void timeShiftPause();
+    method public void timeShiftResume();
+    method public void timeShiftSeekTo(long);
+    method public void timeShiftSetPlaybackRate(float, int);
     method public void tune(java.lang.String, android.net.Uri);
+    method public void unregisterTimeShiftPositionCallback(android.media.tv.TvView.TimeShiftPositionCallback);
   }
 
   public static abstract interface TvView.OnUnhandledInputEventListener {
     method public abstract boolean onUnhandledInputEvent(android.view.InputEvent);
   }
 
+  public static abstract class TvView.TimeShiftPositionCallback {
+    ctor public TvView.TimeShiftPositionCallback();
+    method public void onTimeShiftCurrentPositionChanged(java.lang.String, long);
+    method public void onTimeShiftStartPositionChanged(java.lang.String, long);
+  }
+
   public static abstract class TvView.TvInputCallback {
     ctor public TvView.TvInputCallback();
     method public void onChannelRetuned(java.lang.String, android.net.Uri);
@@ -17495,6 +17679,7 @@
     method public void onContentAllowed(java.lang.String);
     method public void onContentBlocked(java.lang.String, android.media.tv.TvContentRating);
     method public void onDisconnected(java.lang.String);
+    method public void onTimeShiftStatusChanged(java.lang.String, int);
     method public void onTrackSelected(java.lang.String, int, java.lang.String);
     method public void onTracksChanged(java.lang.String, java.util.List<android.media.tv.TvTrackInfo>);
     method public void onVideoAvailable(java.lang.String);
@@ -18580,7 +18765,10 @@
     field public int frequency;
     field public boolean is80211McRTTResponder;
     field public int level;
+    field public java.lang.String operatorFriendlyName;
+    field public boolean passpointNetwork;
     field public long timestamp;
+    field public java.lang.String venueName;
   }
 
   public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
@@ -18607,6 +18795,7 @@
   public class WifiConfiguration implements android.os.Parcelable {
     ctor public WifiConfiguration();
     method public int describeContents();
+    method public boolean isPasspoint();
     method public void writeToParcel(android.os.Parcel, int);
     field public java.lang.String BSSID;
     field public java.lang.String FQDN;
@@ -18710,6 +18899,7 @@
 
   public static final class WifiEnterpriseConfig.Eap {
     field public static final int AKA = 5; // 0x5
+    field public static final int AKA_PRIME = 6; // 0x6
     field public static final int NONE = -1; // 0xffffffff
     field public static final int PEAP = 0; // 0x0
     field public static final int PWD = 3; // 0x3
@@ -22453,6 +22643,7 @@
     field public static java.lang.String DIRECTORY_RINGTONES;
     field public static final java.lang.String MEDIA_BAD_REMOVAL = "bad_removal";
     field public static final java.lang.String MEDIA_CHECKING = "checking";
+    field public static final java.lang.String MEDIA_EJECTING = "ejecting";
     field public static final java.lang.String MEDIA_MOUNTED = "mounted";
     field public static final java.lang.String MEDIA_MOUNTED_READ_ONLY = "mounted_ro";
     field public static final java.lang.String MEDIA_NOFS = "nofs";
@@ -22884,6 +23075,7 @@
   }
 
   public final class PowerManager {
+    method public boolean isDeviceIdleMode();
     method public boolean isInteractive();
     method public boolean isPowerSaveMode();
     method public deprecated boolean isScreenOn();
@@ -22891,6 +23083,7 @@
     method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
     method public void reboot(java.lang.String);
     field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
+    field public static final java.lang.String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
     field public static final java.lang.String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
     field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a
     field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
@@ -23961,8 +24154,16 @@
     field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
     field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
     field public static final java.lang.String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
+    field public static final java.lang.String ACTION_VOICE_CANCEL_ALARM = "android.intent.action.VOICE_CANCEL_ALARM";
+    field public static final java.lang.String ACTION_VOICE_DELETE_ALARM = "android.intent.action.VOICE_DELETE_ALARM";
+    field public static final java.lang.String ALARM_SEARCH_MODE_ALL = "all";
+    field public static final java.lang.String ALARM_SEARCH_MODE_NEXT = "next";
+    field public static final java.lang.String ALARM_SEARCH_MODE_NONE = "none";
+    field public static final java.lang.String ALARM_SEARCH_MODE_TIME = "time";
+    field public static final java.lang.String EXTRA_ALARM_SEARCH_MODE = "android.intent.extra.alarm.ALARM_SEARCH_MODE";
     field public static final java.lang.String EXTRA_DAYS = "android.intent.extra.alarm.DAYS";
     field public static final java.lang.String EXTRA_HOUR = "android.intent.extra.alarm.HOUR";
+    field public static final java.lang.String EXTRA_IS_PM = "android.intent.extra.alarm.IS_PM";
     field public static final java.lang.String EXTRA_LENGTH = "android.intent.extra.alarm.LENGTH";
     field public static final java.lang.String EXTRA_MESSAGE = "android.intent.extra.alarm.MESSAGE";
     field public static final java.lang.String EXTRA_MINUTES = "android.intent.extra.alarm.MINUTES";
@@ -25641,6 +25842,7 @@
     method public static java.lang.String getVersion(android.content.Context);
     field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
     field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
+    field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM";
     field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
     field public static final java.lang.String AUTHORITY = "media";
     field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
@@ -26012,6 +26214,8 @@
     field public static final java.lang.String ACTION_USAGE_ACCESS_SETTINGS = "android.settings.USAGE_ACCESS_SETTINGS";
     field public static final java.lang.String ACTION_USER_DICTIONARY_SETTINGS = "android.settings.USER_DICTIONARY_SETTINGS";
     field public static final java.lang.String ACTION_VOICE_CONTROL_AIRPLANE_MODE = "android.settings.VOICE_CONTROL_AIRPLANE_MODE";
+    field public static final java.lang.String ACTION_VOICE_CONTROL_BATTERY_SAVER_MODE = "android.settings.VOICE_CONTROL_BATTERY_SAVER_MODE";
+    field public static final java.lang.String ACTION_VOICE_CONTROL_DO_NOT_DISTURB_MODE = "android.settings.VOICE_CONTROL_DO_NOT_DISTURB_MODE";
     field public static final java.lang.String ACTION_VOICE_INPUT_SETTINGS = "android.settings.VOICE_INPUT_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
@@ -26020,6 +26224,9 @@
     field public static final java.lang.String EXTRA_ACCOUNT_TYPES = "account_types";
     field public static final java.lang.String EXTRA_AIRPLANE_MODE_ENABLED = "airplane_mode_enabled";
     field public static final java.lang.String EXTRA_AUTHORITIES = "authorities";
+    field public static final java.lang.String EXTRA_BATTERY_SAVER_MODE_ENABLED = "android.settings.extra.battery_saver_mode_enabled";
+    field public static final java.lang.String EXTRA_DO_NOT_DISTURB_MODE_ENABLED = "android.settings.extra.do_not_disturb_mode_enabled";
+    field public static final java.lang.String EXTRA_DO_NOT_DISTURB_MODE_MINUTES = "android.settings.extra.do_not_disturb_mode_minutes";
     field public static final java.lang.String EXTRA_INPUT_METHOD_ID = "input_method_id";
   }
 
@@ -26697,6 +26904,16 @@
     method public void copy1DRangeFromUnchecked(int, int, short[]);
     method public void copy1DRangeFromUnchecked(int, int, byte[]);
     method public void copy1DRangeFromUnchecked(int, int, float[]);
+    method public void copy1DRangeTo(int, int, java.lang.Object);
+    method public void copy1DRangeTo(int, int, int[]);
+    method public void copy1DRangeTo(int, int, short[]);
+    method public void copy1DRangeTo(int, int, byte[]);
+    method public void copy1DRangeTo(int, int, float[]);
+    method public void copy1DRangeToUnchecked(int, int, java.lang.Object);
+    method public void copy1DRangeToUnchecked(int, int, int[]);
+    method public void copy1DRangeToUnchecked(int, int, short[]);
+    method public void copy1DRangeToUnchecked(int, int, byte[]);
+    method public void copy1DRangeToUnchecked(int, int, float[]);
     method public void copy2DRangeFrom(int, int, int, int, java.lang.Object);
     method public void copy2DRangeFrom(int, int, int, int, byte[]);
     method public void copy2DRangeFrom(int, int, int, int, short[]);
@@ -26704,6 +26921,14 @@
     method public void copy2DRangeFrom(int, int, int, int, float[]);
     method public void copy2DRangeFrom(int, int, int, int, android.renderscript.Allocation, int, int);
     method public void copy2DRangeFrom(int, int, android.graphics.Bitmap);
+    method public void copy2DRangeTo(int, int, int, int, java.lang.Object);
+    method public void copy2DRangeTo(int, int, int, int, byte[]);
+    method public void copy2DRangeTo(int, int, int, int, short[]);
+    method public void copy2DRangeTo(int, int, int, int, int[]);
+    method public void copy2DRangeTo(int, int, int, int, float[]);
+    method public void copy3DRangeFrom(int, int, int, int, int, int, java.lang.Object);
+    method public void copy3DRangeFrom(int, int, int, int, int, int, android.renderscript.Allocation, int, int, int);
+    method public void copy3DRangeTo(int, int, int, int, int, int, java.lang.Object);
     method public void copyFrom(android.renderscript.BaseObj[]);
     method public void copyFrom(java.lang.Object);
     method public void copyFrom(int[]);
@@ -26723,6 +26948,7 @@
     method public void copyTo(short[]);
     method public void copyTo(int[]);
     method public void copyTo(float[]);
+    method public void copyToFieldPacker(int, int, int, int, android.renderscript.FieldPacker);
     method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
     method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap);
     method public static android.renderscript.Allocation createCubemapFromCubeFaces(android.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
@@ -26746,8 +26972,10 @@
     method public void ioReceive();
     method public void ioSend();
     method public deprecated synchronized void resize(int);
+    method public void setAutoPadding(boolean);
     method public void setFromFieldPacker(int, android.renderscript.FieldPacker);
     method public void setFromFieldPacker(int, int, android.renderscript.FieldPacker);
+    method public void setFromFieldPacker(int, int, int, int, android.renderscript.FieldPacker);
     method public void setOnBufferAvailableListener(android.renderscript.Allocation.OnBufferAvailableListener);
     method public void setSurface(android.view.Surface);
     method public void syncAll(int);
@@ -26844,6 +27072,10 @@
     method public static android.renderscript.Element A_8(android.renderscript.RenderScript);
     method public static android.renderscript.Element BOOLEAN(android.renderscript.RenderScript);
     method public static android.renderscript.Element ELEMENT(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F16(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F16_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F16_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F16_4(android.renderscript.RenderScript);
     method public static android.renderscript.Element F32(android.renderscript.RenderScript);
     method public static android.renderscript.Element F32_2(android.renderscript.RenderScript);
     method public static android.renderscript.Element F32_3(android.renderscript.RenderScript);
@@ -26942,6 +27174,7 @@
     method public static android.renderscript.Element.DataType valueOf(java.lang.String);
     method public static final android.renderscript.Element.DataType[] values();
     enum_constant public static final android.renderscript.Element.DataType BOOLEAN;
+    enum_constant public static final android.renderscript.Element.DataType FLOAT_16;
     enum_constant public static final android.renderscript.Element.DataType FLOAT_32;
     enum_constant public static final android.renderscript.Element.DataType FLOAT_64;
     enum_constant public static final android.renderscript.Element.DataType MATRIX_2X2;
@@ -27215,11 +27448,14 @@
     method public static android.renderscript.RenderScript create(android.content.Context);
     method public static android.renderscript.RenderScript create(android.content.Context, android.renderscript.RenderScript.ContextType);
     method public static android.renderscript.RenderScript create(android.content.Context, android.renderscript.RenderScript.ContextType, int);
+    method public static android.renderscript.RenderScript createMultiContext(android.content.Context, android.renderscript.RenderScript.ContextType, int, int);
     method public void destroy();
     method public void finish();
     method public final android.content.Context getApplicationContext();
     method public android.renderscript.RenderScript.RSErrorHandler getErrorHandler();
     method public android.renderscript.RenderScript.RSMessageHandler getMessageHandler();
+    method public static long getMinorID();
+    method public static void releaseAllContexts();
     method public void sendMessage(int, int[]);
     method public void setErrorHandler(android.renderscript.RenderScript.RSErrorHandler);
     method public void setMessageHandler(android.renderscript.RenderScript.RSMessageHandler);
@@ -27301,9 +27537,12 @@
   public class Script extends android.renderscript.BaseObj {
     method public void bindAllocation(android.renderscript.Allocation, int);
     method protected android.renderscript.Script.FieldID createFieldID(int, android.renderscript.Element);
+    method protected android.renderscript.Script.InvokeID createInvokeID(int);
     method protected android.renderscript.Script.KernelID createKernelID(int, int, android.renderscript.Element, android.renderscript.Element);
     method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker);
     method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker, android.renderscript.Script.LaunchOptions);
+    method protected void forEach(int, android.renderscript.Allocation[], android.renderscript.Allocation, android.renderscript.FieldPacker);
+    method protected void forEach(int, android.renderscript.Allocation[], android.renderscript.Allocation, android.renderscript.FieldPacker, android.renderscript.Script.LaunchOptions);
     method public boolean getVarB(int);
     method public double getVarD(int);
     method public float getVarF(int);
@@ -27341,6 +27580,9 @@
   public static final class Script.FieldID extends android.renderscript.BaseObj {
   }
 
+  public static final class Script.InvokeID extends android.renderscript.BaseObj {
+  }
+
   public static final class Script.KernelID extends android.renderscript.BaseObj {
   }
 
@@ -27378,6 +27620,41 @@
     method public android.renderscript.ScriptGroup create();
   }
 
+  public class ScriptGroup2 extends android.renderscript.BaseObj {
+    ctor public ScriptGroup2(long, android.renderscript.RenderScript);
+    method public java.lang.Object[] execute(java.lang.Object...);
+  }
+
+  public static final class ScriptGroup2.Binding {
+    ctor public ScriptGroup2.Binding(android.renderscript.Script.FieldID, java.lang.Object);
+    method public android.renderscript.Script.FieldID getField();
+    method public java.lang.Object getValue();
+  }
+
+  public static final class ScriptGroup2.Builder {
+    ctor public ScriptGroup2.Builder(android.renderscript.RenderScript);
+    method public android.renderscript.ScriptGroup2.UnboundValue addInput();
+    method public android.renderscript.ScriptGroup2.Closure addInvoke(android.renderscript.Script.InvokeID, java.lang.Object[], java.util.Map<android.renderscript.Script.FieldID, java.lang.Object>);
+    method public android.renderscript.ScriptGroup2.Closure addInvoke(android.renderscript.Script.InvokeID, java.lang.Object...);
+    method public android.renderscript.ScriptGroup2.Closure addKernel(android.renderscript.Script.KernelID, android.renderscript.Type, java.lang.Object[], java.util.Map<android.renderscript.Script.FieldID, java.lang.Object>);
+    method public android.renderscript.ScriptGroup2.Closure addKernel(android.renderscript.Script.KernelID, android.renderscript.Type, java.lang.Object...);
+    method public android.renderscript.ScriptGroup2 create(android.renderscript.ScriptGroup2.Future...);
+  }
+
+  public static class ScriptGroup2.Closure extends android.renderscript.BaseObj {
+    ctor public ScriptGroup2.Closure(long, android.renderscript.RenderScript);
+    ctor public ScriptGroup2.Closure(android.renderscript.RenderScript, android.renderscript.Script.KernelID, android.renderscript.Type, java.lang.Object[], java.util.Map<android.renderscript.Script.FieldID, java.lang.Object>);
+    ctor public ScriptGroup2.Closure(android.renderscript.RenderScript, android.renderscript.Script.InvokeID, java.lang.Object[], java.util.Map<android.renderscript.Script.FieldID, java.lang.Object>);
+    method public android.renderscript.ScriptGroup2.Future getGlobal(android.renderscript.Script.FieldID);
+    method public android.renderscript.ScriptGroup2.Future getReturn();
+  }
+
+  public static class ScriptGroup2.Future {
+  }
+
+  public static class ScriptGroup2.UnboundValue {
+  }
+
   public abstract class ScriptIntrinsic extends android.renderscript.Script {
   }
 
@@ -27551,6 +27828,8 @@
     method public static android.renderscript.Type createX(android.renderscript.RenderScript, android.renderscript.Element, int);
     method public static android.renderscript.Type createXY(android.renderscript.RenderScript, android.renderscript.Element, int, int);
     method public static android.renderscript.Type createXYZ(android.renderscript.RenderScript, android.renderscript.Element, int, int, int);
+    method public int getArray(int);
+    method public int getArrayCount();
     method public int getCount();
     method public android.renderscript.Element getElement();
     method public int getX();
@@ -27564,6 +27843,7 @@
   public static class Type.Builder {
     ctor public Type.Builder(android.renderscript.RenderScript, android.renderscript.Element);
     method public android.renderscript.Type create();
+    method public android.renderscript.Type.Builder setArray(int, int);
     method public android.renderscript.Type.Builder setFaces(boolean);
     method public android.renderscript.Type.Builder setMipmaps(boolean);
     method public android.renderscript.Type.Builder setX(int);
@@ -27693,6 +27973,11 @@
     method public android.security.KeyStoreParameter.Builder setEncryptionRequired(boolean);
   }
 
+  public class NetworkSecurityPolicy {
+    method public static android.security.NetworkSecurityPolicy getInstance();
+    method public boolean isCleartextTrafficPermitted();
+  }
+
 }
 
 package android.service.carrier {
@@ -27875,6 +28160,7 @@
     method public final void requestInterruptionFilter(int);
     method public final void requestListenerHints(int);
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
+    field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
     field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
     field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
     field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
@@ -27996,6 +28282,7 @@
     method public void showSession(android.os.Bundle, int);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
     field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
+    field public static final int START_SOURCE_ASSIST_GESTURE = 4; // 0x4
     field public static final int START_WITH_ASSIST = 1; // 0x1
     field public static final int START_WITH_SCREENSHOT = 2; // 0x2
   }
@@ -28004,6 +28291,7 @@
     ctor public VoiceInteractionSession(android.content.Context);
     ctor public VoiceInteractionSession(android.content.Context, android.os.Handler);
     method public void finish();
+    method public android.content.Context getContext();
     method public android.view.LayoutInflater getLayoutInflater();
     method public android.app.Dialog getWindow();
     method public void hide();
@@ -29711,6 +29999,7 @@
     method public boolean setOperatorBrandOverride(java.lang.String);
     method public boolean setPreferredNetworkTypeToGlobal();
     method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
+    field public static final java.lang.String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
     field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
     field public static final int CALL_STATE_IDLE = 0; // 0x0
@@ -30382,6 +30671,7 @@
     method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
     method public java.lang.String getInstallerPackageName(java.lang.String);
     method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(java.lang.String);
     method public android.content.Intent getLaunchIntentForPackage(java.lang.String);
     method public android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
     method public java.lang.String getNameForUid(int);
@@ -30746,6 +31036,9 @@
     method public final void increaseWidthTo(int);
     method public boolean isRtlCharAt(int);
     method protected final boolean isSpanned();
+    field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2
+    field public static final int BREAK_STRATEGY_HIGH_QUALITY = 1; // 0x1
+    field public static final int BREAK_STRATEGY_SIMPLE = 0; // 0x0
     field public static final int DIR_LEFT_TO_RIGHT = 1; // 0x1
     field public static final int DIR_RIGHT_TO_LEFT = -1; // 0xffffffff
   }
@@ -34160,8 +34453,10 @@
     method public long getTimeDelta();
     method public boolean isInProgress();
     method public boolean isQuickScaleEnabled();
+    method public boolean isSecondaryButtonScaleEnabled();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public void setQuickScaleEnabled(boolean);
+    method public void setSecondaryButtonScaleEnabled(boolean);
   }
 
   public static abstract interface ScaleGestureDetector.OnScaleGestureListener {
@@ -34382,6 +34677,7 @@
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public void dispatchProvideAssistStructure(android.view.ViewAssistStructure);
     method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSetActivated(boolean);
@@ -34442,6 +34738,10 @@
     method public boolean getFitsSystemWindows();
     method public java.util.ArrayList<android.view.View> getFocusables(int);
     method public void getFocusedRect(android.graphics.Rect);
+    method public android.graphics.drawable.Drawable getForeground();
+    method public int getForegroundGravity();
+    method public android.content.res.ColorStateList getForegroundTintList();
+    method public android.graphics.PorterDuff.Mode getForegroundTintMode();
     method public boolean getGlobalVisibleRect(android.graphics.Rect, android.graphics.Point);
     method public final boolean getGlobalVisibleRect(android.graphics.Rect);
     method public android.os.Handler getHandler();
@@ -34613,6 +34913,7 @@
     method protected void onDisplayHint(int);
     method public boolean onDragEvent(android.view.DragEvent);
     method protected void onDraw(android.graphics.Canvas);
+    method public void onDrawForeground(android.graphics.Canvas);
     method protected final void onDrawScrollBars(android.graphics.Canvas);
     method public boolean onFilterTouchEventForSecurity(android.view.MotionEvent);
     method protected void onFinishInflate();
@@ -34633,7 +34934,8 @@
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public void onProvideAssistStructure(android.view.ViewAssistStructure, android.os.Bundle);
+    method public void onProvideAssistStructure(android.view.ViewAssistStructure);
+    method public void onProvideVirtualAssistStructure(android.view.ViewAssistStructure);
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method public void onRtlPropertiesChanged(int);
     method protected android.os.Parcelable onSaveInstanceState();
@@ -34718,6 +35020,10 @@
     method public void setFitsSystemWindows(boolean);
     method public void setFocusable(boolean);
     method public void setFocusableInTouchMode(boolean);
+    method public void setForeground(android.graphics.drawable.Drawable);
+    method public void setForegroundGravity(int);
+    method public void setForegroundTintList(android.content.res.ColorStateList);
+    method public void setForegroundTintMode(android.graphics.PorterDuff.Mode);
     method public void setHapticFeedbackEnabled(boolean);
     method public void setHasTransientState(boolean);
     method public void setHorizontalFadingEdgeEnabled(boolean);
@@ -35039,14 +35345,36 @@
 
   public abstract class ViewAssistStructure {
     ctor public ViewAssistStructure();
+    method public abstract void asyncCommit();
+    method public abstract android.view.ViewAssistStructure asyncNewChild(int);
+    method public abstract void clearExtras();
+    method public abstract android.os.Bundle editExtras();
+    method public abstract int getChildCount();
     method public abstract java.lang.CharSequence getHint();
     method public abstract java.lang.CharSequence getText();
     method public abstract int getTextSelectionEnd();
     method public abstract int getTextSelectionStart();
+    method public abstract android.view.ViewAssistStructure newChild(int);
+    method public abstract void setAccessibilityFocused(boolean);
+    method public abstract void setActivated(boolean);
+    method public abstract void setCheckable(boolean);
+    method public abstract void setChecked(boolean);
+    method public abstract void setChildCount(int);
+    method public abstract void setClassName(java.lang.String);
+    method public abstract void setClickable(boolean);
+    method public abstract void setContentDescription(java.lang.CharSequence);
+    method public abstract void setDimens(int, int, int, int, int, int);
+    method public abstract void setEnabled(boolean);
+    method public abstract void setFocusable(boolean);
+    method public abstract void setFocused(boolean);
     method public abstract void setHint(java.lang.CharSequence);
+    method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
+    method public abstract void setLongClickable(boolean);
+    method public abstract void setSelected(boolean);
     method public abstract void setText(java.lang.CharSequence);
     method public abstract void setText(java.lang.CharSequence, int, int);
     method public abstract void setTextPaint(android.text.TextPaint);
+    method public abstract void setVisibility(int);
   }
 
   public class ViewConfiguration {
@@ -36076,9 +36404,11 @@
     method public void setVisibleToUser(boolean);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
+    field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
     field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
     field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
     field public static final java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
+    field public static final java.lang.String ACTION_ARGUMENT_ROW_INT = "android.view.accessibility.action.ARGUMENT_ROW_INT";
     field public static final java.lang.String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
     field public static final java.lang.String ACTION_ARGUMENT_SELECTION_START_INT = "ACTION_ARGUMENT_SELECTION_START_INT";
     field public static final java.lang.String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
@@ -36136,9 +36466,11 @@
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_BACKWARD;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_FORWARD;
+    field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_TO_POSITION;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SELECT;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_SELECTION;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_TEXT;
+    field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SHOW_ON_SCREEN;
   }
 
   public static final class AccessibilityNodeInfo.CollectionInfo {
@@ -37680,7 +38012,6 @@
     method public boolean shouldOverrideUrlLoading(android.webkit.WebView, java.lang.String);
     field public static final int ERROR_AUTHENTICATION = -4; // 0xfffffffc
     field public static final int ERROR_BAD_URL = -12; // 0xfffffff4
-    field public static final int ERROR_BLOCKED = -16; // 0xfffffff0
     field public static final int ERROR_CONNECT = -6; // 0xfffffffa
     field public static final int ERROR_FAILED_SSL_HANDSHAKE = -11; // 0xfffffff5
     field public static final int ERROR_FILE = -13; // 0xfffffff3
@@ -38043,7 +38374,7 @@
     field protected android.database.Cursor mDataCursor;
   }
 
-  public class AnalogClock extends android.view.View {
+  public deprecated class AnalogClock extends android.view.View {
     ctor public AnalogClock(android.content.Context);
     ctor public AnalogClock(android.content.Context, android.util.AttributeSet);
     ctor public AnalogClock(android.content.Context, android.util.AttributeSet, int);
@@ -38546,16 +38877,8 @@
     ctor public FrameLayout(android.content.Context, android.util.AttributeSet, int);
     ctor public FrameLayout(android.content.Context, android.util.AttributeSet, int, int);
     method public deprecated boolean getConsiderGoneChildrenWhenMeasuring();
-    method public android.graphics.drawable.Drawable getForeground();
-    method public int getForegroundGravity();
-    method public android.content.res.ColorStateList getForegroundTintList();
-    method public android.graphics.PorterDuff.Mode getForegroundTintMode();
     method public boolean getMeasureAllChildren();
     method protected void onLayout(boolean, int, int, int, int);
-    method public void setForeground(android.graphics.drawable.Drawable);
-    method public void setForegroundGravity(int);
-    method public void setForegroundTintList(android.content.res.ColorStateList);
-    method public void setForegroundTintMode(android.graphics.PorterDuff.Mode);
     method public void setMeasureAllChildren(boolean);
   }
 
@@ -39905,6 +40228,7 @@
     method public void endBatchEdit();
     method public boolean extractText(android.view.inputmethod.ExtractedTextRequest, android.view.inputmethod.ExtractedText);
     method public final int getAutoLinkMask();
+    method public int getBreakStrategy();
     method public int getCompoundDrawablePadding();
     method public android.content.res.ColorStateList getCompoundDrawableTintList();
     method public android.graphics.PorterDuff.Mode getCompoundDrawableTintMode();
@@ -40006,6 +40330,7 @@
     method public void removeTextChangedListener(android.text.TextWatcher);
     method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
+    method public void setBreakStrategy(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawableTintList(android.content.res.ColorStateList);
     method public void setCompoundDrawableTintMode(android.graphics.PorterDuff.Mode);
@@ -40112,12 +40437,16 @@
     ctor public TimePicker(android.content.Context, android.util.AttributeSet);
     ctor public TimePicker(android.content.Context, android.util.AttributeSet, int);
     ctor public TimePicker(android.content.Context, android.util.AttributeSet, int, int);
-    method public java.lang.Integer getCurrentHour();
-    method public java.lang.Integer getCurrentMinute();
+    method public deprecated java.lang.Integer getCurrentHour();
+    method public deprecated java.lang.Integer getCurrentMinute();
+    method public int getHour();
+    method public int getMinute();
     method public boolean is24HourView();
-    method public void setCurrentHour(java.lang.Integer);
-    method public void setCurrentMinute(java.lang.Integer);
+    method public deprecated void setCurrentHour(java.lang.Integer);
+    method public deprecated void setCurrentMinute(java.lang.Integer);
+    method public void setHour(int);
     method public void setIs24HourView(java.lang.Boolean);
+    method public void setMinute(int);
     method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index 71474a3..2c3199d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -103,6 +103,7 @@
     field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
     field public static final java.lang.String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES";
     field public static final java.lang.String INSTALL_SHORTCUT = "com.android.launcher.permission.INSTALL_SHORTCUT";
+    field public static final java.lang.String INTENT_FILTER_VERIFICATION_AGENT = "android.permission.INTENT_FILTER_VERIFICATION_AGENT";
     field public static final java.lang.String INTERACT_ACROSS_USERS = "android.permission.INTERACT_ACROSS_USERS";
     field public static final java.lang.String INTERNAL_SYSTEM_WINDOW = "android.permission.INTERNAL_SYSTEM_WINDOW";
     field public static final java.lang.String INTERNET = "android.permission.INTERNET";
@@ -134,6 +135,7 @@
     field public static final java.lang.String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
     field public static final java.lang.String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
     field public static final java.lang.String PERFORM_CDMA_PROVISIONING = "android.permission.PERFORM_CDMA_PROVISIONING";
+    field public static final java.lang.String PERFORM_SIM_ACTIVATION = "android.permission.PERFORM_SIM_ACTIVATION";
     field public static final deprecated java.lang.String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
     field public static final java.lang.String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
     field public static final java.lang.String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT";
@@ -375,8 +377,8 @@
     field public static final int alphabeticShortcut = 16843235; // 0x10101e3
     field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
     field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
-    field public static final int amPmBackgroundColor = 16843941; // 0x10104a5
-    field public static final int amPmTextColor = 16843940; // 0x10104a4
+    field public static final deprecated int amPmBackgroundColor = 16843941; // 0x10104a5
+    field public static final deprecated int amPmTextColor = 16843940; // 0x10104a4
     field public static final int ambientShadowAlpha = 16843966; // 0x10104be
     field public static final int angle = 16843168; // 0x10101a0
     field public static final int animateFirstView = 16843477; // 0x10102d5
@@ -401,6 +403,7 @@
     field public static final int autoStart = 16843445; // 0x10102b5
     field public static final deprecated int autoText = 16843114; // 0x101016a
     field public static final int autoUrlDetect = 16843404; // 0x101028c
+    field public static final int autoVerify = 16844010; // 0x10104ea
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -424,6 +427,7 @@
     field public static final int bottomRightRadius = 16843180; // 0x10101ac
     field public static final int breadCrumbShortTitle = 16843524; // 0x1010304
     field public static final int breadCrumbTitle = 16843523; // 0x1010303
+    field public static final int breakStrategy = 16844011; // 0x10104eb
     field public static final int bufferType = 16843086; // 0x101014e
     field public static final int button = 16843015; // 0x1010107
     field public static final int buttonBarButtonStyle = 16843567; // 0x101032f
@@ -722,13 +726,13 @@
     field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
     field public static final int hardwareAccelerated = 16843475; // 0x10102d3
     field public static final int hasCode = 16842764; // 0x101000c
-    field public static final int headerAmPmTextAppearance = 16843936; // 0x10104a0
+    field public static final deprecated int headerAmPmTextAppearance = 16843936; // 0x10104a0
     field public static final int headerBackground = 16843055; // 0x101012f
     field public static final deprecated int headerDayOfMonthTextAppearance = 16843927; // 0x1010497
     field public static final int headerDividersEnabled = 16843310; // 0x101022e
     field public static final deprecated int headerMonthTextAppearance = 16843926; // 0x1010496
-    field public static final int headerTimeTextAppearance = 16843935; // 0x101049f
-    field public static final int headerYearTextAppearance = 16843928; // 0x1010498
+    field public static final deprecated int headerTimeTextAppearance = 16843935; // 0x101049f
+    field public static final deprecated int headerYearTextAppearance = 16843928; // 0x1010498
     field public static final int height = 16843093; // 0x1010155
     field public static final int hideOnContentScroll = 16843843; // 0x1010443
     field public static final int hint = 16843088; // 0x1010150
@@ -1273,6 +1277,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
+    field public static final int supportsAssistGesture = 16844012; // 0x10104ec
     field public static final int supportsRtl = 16843695; // 0x10103af
     field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
     field public static final int supportsUploading = 16843419; // 0x101029b
@@ -1436,6 +1441,7 @@
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
+    field public static final int usesCleartextTraffic = 16844009; // 0x10104e9
     field public static final int value = 16842788; // 0x1010024
     field public static final int valueFrom = 16843486; // 0x10102de
     field public static final int valueTo = 16843487; // 0x10102df
@@ -1530,7 +1536,7 @@
     field public static final int x = 16842924; // 0x10100ac
     field public static final int xlargeScreens = 16843455; // 0x10102bf
     field public static final int y = 16842925; // 0x10100ad
-    field public static final int yearListItemTextAppearance = 16843929; // 0x1010499
+    field public static final deprecated int yearListItemTextAppearance = 16843929; // 0x1010499
     field public static final deprecated int yearListSelectorColor = 16843930; // 0x101049a
     field public static final int yesNoPreferenceStyle = 16842896; // 0x1010090
     field public static final int zAdjustment = 16843201; // 0x10101c1
@@ -1767,6 +1773,8 @@
 
   public static final class R.id {
     ctor public R.id();
+    field public static final int accessibilityActionScrollToPosition = 16908342; // 0x1020036
+    field public static final int accessibilityActionShowOnScreen = 16908341; // 0x1020035
     field public static final int addToDictionary = 16908330; // 0x102002a
     field public static final int background = 16908288; // 0x1020000
     field public static final int button1 = 16908313; // 0x1020019
@@ -2812,6 +2820,7 @@
   }
 
   public class AccountManager {
+    method public boolean accountAuthenticated(android.accounts.Account);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
     method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
@@ -2872,6 +2881,7 @@
     field public static final java.lang.String KEY_ERROR_CODE = "errorCode";
     field public static final java.lang.String KEY_ERROR_MESSAGE = "errorMessage";
     field public static final java.lang.String KEY_INTENT = "intent";
+    field public static final java.lang.String KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH = "lastAuthenticatedTimeMillisEpoch";
     field public static final java.lang.String KEY_PASSWORD = "password";
     field public static final java.lang.String KEY_USERDATA = "userdata";
     field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
@@ -3633,6 +3643,7 @@
   public class ActivityManager {
     method public int addAppTask(android.app.Activity, android.content.Intent, android.app.ActivityManager.TaskDescription, android.graphics.Bitmap);
     method public boolean clearApplicationUserData();
+    method public void clearWatchHeapLimit();
     method public void dumpPackageState(java.io.FileDescriptor, java.lang.String);
     method public android.util.Size getAppTaskThumbnailSize();
     method public java.util.List<android.app.ActivityManager.AppTask> getAppTasks();
@@ -3660,6 +3671,8 @@
     method public void moveTaskToFront(int, int);
     method public void moveTaskToFront(int, int, android.os.Bundle);
     method public deprecated void restartPackage(java.lang.String);
+    method public void setWatchHeapLimit(long);
+    field public static final java.lang.String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT";
     field public static final int LOCK_TASK_MODE_LOCKED = 1; // 0x1
     field public static final int LOCK_TASK_MODE_NONE = 0; // 0x0
     field public static final int LOCK_TASK_MODE_PINNED = 2; // 0x2
@@ -4791,6 +4804,7 @@
     field public static final java.lang.String CATEGORY_PROGRESS = "progress";
     field public static final java.lang.String CATEGORY_PROMO = "promo";
     field public static final java.lang.String CATEGORY_RECOMMENDATION = "recommendation";
+    field public static final java.lang.String CATEGORY_REMINDER = "reminder";
     field public static final java.lang.String CATEGORY_SERVICE = "service";
     field public static final java.lang.String CATEGORY_SOCIAL = "social";
     field public static final java.lang.String CATEGORY_STATUS = "status";
@@ -5516,10 +5530,12 @@
 
   public static final class VoiceInteractor.PickOptionRequest.Option implements android.os.Parcelable {
     ctor public VoiceInteractor.PickOptionRequest.Option(java.lang.CharSequence);
+    ctor public VoiceInteractor.PickOptionRequest.Option(java.lang.CharSequence, int);
     method public android.app.VoiceInteractor.PickOptionRequest.Option addSynonym(java.lang.CharSequence);
     method public int countSynonyms();
     method public int describeContents();
     method public android.os.Bundle getExtras();
+    method public int getIndex();
     method public java.lang.CharSequence getLabel();
     method public java.lang.CharSequence getSynonymAt(int);
     method public void setExtras(android.os.Bundle);
@@ -5681,6 +5697,7 @@
     method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
     method public java.lang.String getDeviceInitializerApp();
+    method public android.content.ComponentName getDeviceInitializerComponent();
     method public java.lang.String getDeviceOwner();
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
@@ -5803,6 +5820,7 @@
     field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
+    field public static final java.lang.String EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS = "android.app.extra.PROVISIONING_RESET_PROTECTION_PARAMETERS";
     field public static final java.lang.String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
     field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
@@ -5824,6 +5842,7 @@
     field public static final int KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS = 8; // 0x8
     field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1; // 0x1
     field public static final java.lang.String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning";
+    field public static final java.lang.String MIME_TYPE_PROVISIONING_NFC_V2 = "application/com.android.managedprovisioning.v2";
     field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000
     field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000
     field public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 32768; // 0x8000
@@ -5908,6 +5927,7 @@
     ctor public BackupTransport();
     method public int abortFullRestore();
     method public void cancelFullBackup();
+    method public int checkFullBackupSize(long);
     method public int clearBackupData(android.content.pm.PackageInfo);
     method public android.content.Intent configurationIntent();
     method public java.lang.String currentDestinationString();
@@ -6085,6 +6105,37 @@
     field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
   }
 
+  public class NetworkStatsManager {
+    method public android.app.usage.NetworkUsageStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkUsageStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkUsageStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkUsageStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+    method public android.app.usage.NetworkUsageStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+  }
+
+  public final class NetworkUsageStats implements java.lang.AutoCloseable {
+    method public void close();
+    method public boolean getNextBucket(android.app.usage.NetworkUsageStats.Bucket);
+    method public boolean hasNextBucket();
+  }
+
+  public static class NetworkUsageStats.Bucket {
+    ctor public NetworkUsageStats.Bucket();
+    method public long getEndTimeStamp();
+    method public long getRxBytes();
+    method public long getRxPackets();
+    method public long getStartTimeStamp();
+    method public int getState();
+    method public long getTxBytes();
+    method public long getTxPackets();
+    method public int getUid();
+    field public static final int STATE_ALL = -1; // 0xffffffff
+    field public static final int STATE_DEFAULT = 1; // 0x1
+    field public static final int STATE_FOREGROUND = 2; // 0x2
+    field public static final int UID_REMOVED = -4; // 0xfffffffc
+    field public static final int UID_TETHERING = -5; // 0xfffffffb
+  }
+
   public final class UsageEvents implements android.os.Parcelable {
     method public int describeContents();
     method public boolean getNextEvent(android.app.usage.UsageEvents.Event);
@@ -6293,6 +6344,7 @@
     method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]);
     method public int getScanMode();
     method public int getState();
+    method public boolean isBleScanAlwaysAvailable();
     method public boolean isDiscovering();
     method public boolean isEnabled();
     method public boolean isMultipleAdvertisementSupported();
@@ -6309,6 +6361,7 @@
     field public static final java.lang.String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
     field public static final java.lang.String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
     field public static final java.lang.String ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
+    field public static final java.lang.String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
     field public static final java.lang.String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
     field public static final java.lang.String ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
     field public static final java.lang.String ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
@@ -7149,6 +7202,7 @@
     field public static final int SCAN_MODE_BALANCED = 1; // 0x1
     field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
     field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
+    field public static final int SCAN_MODE_OPPORTUNISTIC = -1; // 0xffffffff
     field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1
     field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0
   }
@@ -7771,6 +7825,7 @@
     field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
     field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
     field public static final java.lang.String NETWORK_SCORE_SERVICE = "network_score";
+    field public static final java.lang.String NETWORK_STATS_SERVICE = "netstats";
     field public static final java.lang.String NFC_SERVICE = "nfc";
     field public static final java.lang.String NOTIFICATION_SERVICE = "notification";
     field public static final java.lang.String NSD_SERVICE = "servicediscovery";
@@ -8139,12 +8194,15 @@
     field public static final java.lang.String ACTION_INSERT = "android.intent.action.INSERT";
     field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
     field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
+    field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
     field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
     field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
+    field public static final java.lang.String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
     field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
     field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
+    field public static final java.lang.String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
     field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
     field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
     field public static final java.lang.String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
@@ -8179,6 +8237,7 @@
     field public static final java.lang.String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED";
     field public static final java.lang.String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";
     field public static final java.lang.String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY";
+    field public static final java.lang.String ACTION_PROCESS_TEXT = "android.intent.action.PROCESS_TEXT";
     field public static final java.lang.String ACTION_PROVIDER_CHANGED = "android.intent.action.PROVIDER_CHANGED";
     field public static final java.lang.String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
     field public static final java.lang.String ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK";
@@ -8281,7 +8340,11 @@
     field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
     field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
     field public static final java.lang.String EXTRA_PACKAGES = "android.intent.extra.PACKAGES";
+    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
+    field public static final java.lang.String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME";
     field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
+    field public static final java.lang.String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
+    field public static final java.lang.String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
     field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
     field public static final java.lang.String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
     field public static final java.lang.String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
@@ -8432,6 +8495,8 @@
     field public static final int NO_MATCH_CATEGORY = -4; // 0xfffffffc
     field public static final int NO_MATCH_DATA = -2; // 0xfffffffe
     field public static final int NO_MATCH_TYPE = -1; // 0xffffffff
+    field public static final java.lang.String SCHEME_HTTP = "http";
+    field public static final java.lang.String SCHEME_HTTPS = "https";
     field public static final int SYSTEM_HIGH_PRIORITY = 1000; // 0x3e8
     field public static final int SYSTEM_LOW_PRIORITY = -1000; // 0xfffffc18
   }
@@ -8553,6 +8618,7 @@
     ctor public RestrictionEntry(java.lang.String, boolean);
     ctor public RestrictionEntry(java.lang.String, java.lang.String[]);
     ctor public RestrictionEntry(java.lang.String, int);
+    ctor public RestrictionEntry(java.lang.String, android.content.RestrictionEntry[], boolean);
     ctor public RestrictionEntry(android.os.Parcel);
     method public int describeContents();
     method public java.lang.String[] getAllSelectedStrings();
@@ -8561,6 +8627,7 @@
     method public java.lang.String getDescription();
     method public int getIntValue();
     method public java.lang.String getKey();
+    method public android.content.RestrictionEntry[] getRestrictions();
     method public boolean getSelectedState();
     method public java.lang.String getSelectedString();
     method public java.lang.String getTitle();
@@ -8572,6 +8639,7 @@
     method public void setChoiceValues(android.content.Context, int);
     method public void setDescription(java.lang.String);
     method public void setIntValue(int);
+    method public void setRestrictions(android.content.RestrictionEntry[]);
     method public void setSelectedState(boolean);
     method public void setSelectedString(java.lang.String);
     method public void setTitle(java.lang.String);
@@ -8579,6 +8647,8 @@
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.RestrictionEntry> CREATOR;
     field public static final int TYPE_BOOLEAN = 1; // 0x1
+    field public static final int TYPE_BUNDLE = 7; // 0x7
+    field public static final int TYPE_BUNDLE_ARRAY = 8; // 0x8
     field public static final int TYPE_CHOICE = 2; // 0x2
     field public static final int TYPE_INTEGER = 5; // 0x5
     field public static final int TYPE_MULTI_SELECT = 4; // 0x4
@@ -8587,6 +8657,7 @@
   }
 
   public class RestrictionsManager {
+    method public static android.os.Bundle convertRestrictionsToBundle(java.util.List<android.content.RestrictionEntry>);
     method public android.content.Intent createLocalApprovalIntent();
     method public android.os.Bundle getApplicationRestrictions();
     method public java.util.List<android.content.RestrictionEntry> getManifestRestrictions(java.lang.String);
@@ -8908,6 +8979,7 @@
     field public static final int FLAG_SYSTEM = 1; // 0x1
     field public static final int FLAG_TEST_ONLY = 256; // 0x100
     field public static final int FLAG_UPDATED_SYSTEM_APP = 128; // 0x80
+    field public static final int FLAG_USES_CLEARTEXT_TRAFFIC = 134217728; // 0x8000000
     field public static final int FLAG_VM_SAFE_MODE = 16384; // 0x4000
     field public java.lang.String backupAgentName;
     field public java.lang.String className;
@@ -9029,6 +9101,25 @@
     field public java.lang.String targetPackage;
   }
 
+  public final class IntentFilterVerificationInfo implements android.os.Parcelable {
+    ctor public IntentFilterVerificationInfo();
+    ctor public IntentFilterVerificationInfo(java.lang.String, java.lang.String[]);
+    ctor public IntentFilterVerificationInfo(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    ctor public IntentFilterVerificationInfo(android.os.Parcel);
+    method public int describeContents();
+    method public java.lang.String[] getDomains();
+    method public java.lang.String getDomainsString();
+    method public java.lang.String getPackageName();
+    method public int getStatus();
+    method public java.lang.String getStatusString();
+    method public static java.lang.String getStatusStringFromValue(int);
+    method public void readFromXml(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public void setStatus(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    method public void writeToXml(org.xmlpull.v1.XmlSerializer) throws java.io.IOException;
+    field public static final android.os.Parcelable.Creator<android.content.pm.IntentFilterVerificationInfo> CREATOR;
+  }
+
   public class LabeledIntent extends android.content.Intent {
     ctor public LabeledIntent(android.content.Intent, java.lang.String, int, int);
     ctor public LabeledIntent(android.content.Intent, java.lang.String, java.lang.CharSequence, int);
@@ -9263,6 +9354,7 @@
     method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
     method public abstract java.lang.String getInstallerPackageName(java.lang.String);
     method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(java.lang.String);
     method public abstract android.content.Intent getLaunchIntentForPackage(java.lang.String);
     method public abstract android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
     method public abstract java.lang.String getNameForUid(int);
@@ -9354,6 +9446,7 @@
     field public static final java.lang.String FEATURE_LOCATION_NETWORK = "android.hardware.location.network";
     field public static final java.lang.String FEATURE_MANAGED_USERS = "android.software.managed_users";
     field public static final java.lang.String FEATURE_MICROPHONE = "android.hardware.microphone";
+    field public static final java.lang.String FEATURE_MIDI = "android.software.midi";
     field public static final java.lang.String FEATURE_NFC = "android.hardware.nfc";
     field public static final java.lang.String FEATURE_NFC_HOST_CARD_EMULATION = "android.hardware.nfc.hce";
     field public static final java.lang.String FEATURE_OPENGLES_EXTENSION_PACK = "android.hardware.opengles.aep";
@@ -9658,11 +9751,10 @@
 
   public class ColorStateList implements android.os.Parcelable {
     ctor public ColorStateList(int[][], int[]);
-    method public void applyTheme(android.content.res.Resources.Theme);
-    method public boolean canApplyTheme();
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
+    method public int getChangingConfigurations();
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
@@ -11380,7 +11472,9 @@
     field public static final int JPEG = 256; // 0x100
     field public static final int NV16 = 16; // 0x10
     field public static final int NV21 = 17; // 0x11
+    field public static final int PRIVATE = 34; // 0x22
     field public static final int RAW10 = 37; // 0x25
+    field public static final int RAW12 = 38; // 0x26
     field public static final int RAW_SENSOR = 32; // 0x20
     field public static final int RGB_565 = 4; // 0x4
     field public static final int UNKNOWN = 0; // 0x0
@@ -11596,6 +11690,7 @@
     method public int getTextWidths(java.lang.String, float[]);
     method public android.graphics.Typeface getTypeface();
     method public android.graphics.Xfermode getXfermode();
+    method public boolean hasGlyph(java.lang.String);
     method public final boolean isAntiAlias();
     method public final boolean isDither();
     method public boolean isElegantTextHeight();
@@ -12176,9 +12271,12 @@
 
   public class AnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
     ctor public AnimatedVectorDrawable();
+    method public void addListener(android.animation.Animator.AnimatorListener);
     method public void draw(android.graphics.Canvas);
+    method public java.util.List<android.animation.Animator.AnimatorListener> getListeners();
     method public int getOpacity();
     method public boolean isRunning();
+    method public void removeListener(android.animation.Animator.AnimatorListener);
     method public void setAlpha(int);
     method public void setColorFilter(android.graphics.ColorFilter);
     method public void start();
@@ -14127,6 +14225,7 @@
     method public void setHdmiMhlVendorCommandListener(android.hardware.hdmi.HdmiTvClient.HdmiMhlVendorCommandListener);
     method public void setInputChangeListener(android.hardware.hdmi.HdmiTvClient.InputChangeListener);
     method public void setRecordListener(android.hardware.hdmi.HdmiRecordListener);
+    method public void setSystemAudioMode(boolean, android.hardware.hdmi.HdmiTvClient.SelectCallback);
     method public void setSystemAudioMute(boolean);
     method public void setSystemAudioVolume(int, int, int);
     method public void startOneTouchRecord(int, android.hardware.hdmi.HdmiRecordSources.RecordSource);
@@ -15564,6 +15663,8 @@
     field public static final int CHANNEL_OUT_SURROUND = 1052; // 0x41c
     field public static final int ENCODING_AC3 = 5; // 0x5
     field public static final int ENCODING_DEFAULT = 1; // 0x1
+    field public static final int ENCODING_DTS = 7; // 0x7
+    field public static final int ENCODING_DTS_HD = 8; // 0x8
     field public static final int ENCODING_E_AC3 = 6; // 0x6
     field public static final int ENCODING_INVALID = 0; // 0x0
     field public static final int ENCODING_PCM_16BIT = 2; // 0x2
@@ -15767,6 +15868,16 @@
     field public static final int SUCCESS = 0; // 0x0
   }
 
+  public static class AudioRecord.Builder {
+    ctor public AudioRecord.Builder();
+    method public android.media.AudioRecord build() throws java.lang.UnsupportedOperationException;
+    method public android.media.AudioRecord.Builder setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioRecord.Builder setAudioFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioRecord.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioRecord.Builder setCapturePreset(int) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioRecord.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
+  }
+
   public static abstract interface AudioRecord.OnRecordPositionUpdateListener {
     method public abstract void onMarkerReached(android.media.AudioRecord);
     method public abstract void onPeriodicNotification(android.media.AudioRecord);
@@ -15838,6 +15949,16 @@
     field public static final int WRITE_NON_BLOCKING = 1; // 0x1
   }
 
+  public static class AudioTrack.Builder {
+    ctor public AudioTrack.Builder();
+    method public android.media.AudioTrack build() throws java.lang.UnsupportedOperationException;
+    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 setSessionId(int) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
+  }
+
   public static abstract interface AudioTrack.OnPlaybackPositionUpdateListener {
     method public abstract void onMarkerReached(android.media.AudioTrack);
     method public abstract void onPeriodicNotification(android.media.AudioTrack);
@@ -16388,6 +16509,7 @@
     method public android.graphics.Bitmap getIconBitmap();
     method public android.net.Uri getIconUri();
     method public java.lang.String getMediaId();
+    method public android.net.Uri getMediaUri();
     method public java.lang.CharSequence getSubtitle();
     method public java.lang.CharSequence getTitle();
     method public void writeToParcel(android.os.Parcel, int);
@@ -16402,6 +16524,7 @@
     method public android.media.MediaDescription.Builder setIconBitmap(android.graphics.Bitmap);
     method public android.media.MediaDescription.Builder setIconUri(android.net.Uri);
     method public android.media.MediaDescription.Builder setMediaId(java.lang.String);
+    method public android.media.MediaDescription.Builder setMediaUri(android.net.Uri);
     method public android.media.MediaDescription.Builder setSubtitle(java.lang.CharSequence);
     method public android.media.MediaDescription.Builder setTitle(java.lang.CharSequence);
   }
@@ -17078,6 +17201,23 @@
     method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
   }
 
+  public final class MediaSync {
+    ctor public MediaSync();
+    method public void configureAudioTrack(android.media.AudioTrack, int);
+    method public void configureSurface(android.view.Surface);
+    method public final android.view.Surface createInputSurface();
+    method public void queueAudio(java.nio.ByteBuffer, int, int, long);
+    method public final void release();
+    method public void setCallback(android.media.MediaSync.Callback, android.os.Handler);
+    method public void setPlaybackRate(float, int);
+    field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0; // 0x0
+  }
+
+  public static abstract class MediaSync.Callback {
+    ctor public MediaSync.Callback();
+    method public abstract void onReturnAudioBuffer(android.media.MediaSync, java.nio.ByteBuffer, int);
+  }
+
   public class MediaSyncEvent {
     method public static android.media.MediaSyncEvent createEvent(int) throws java.lang.IllegalArgumentException;
     method public int getAudioSessionId();
@@ -17896,6 +18036,18 @@
 
 package android.media.midi {
 
+  public final class MidiDevice implements java.io.Closeable {
+    method public void close() throws java.io.IOException;
+    method public android.media.midi.MidiDevice.MidiConnection connectPorts(android.media.midi.MidiInputPort, int);
+    method public android.media.midi.MidiDeviceInfo getInfo();
+    method public android.media.midi.MidiInputPort openInputPort(int);
+    method public android.media.midi.MidiOutputPort openOutputPort(int);
+  }
+
+  public class MidiDevice.MidiConnection implements java.io.Closeable {
+    method public void close() throws java.io.IOException;
+  }
+
   public final class MidiDeviceInfo implements android.os.Parcelable {
     method public int describeContents();
     method public int getId();
@@ -17952,6 +18104,25 @@
     method public void onReceive(byte[], int, int, long) throws java.io.IOException;
   }
 
+  public final class MidiManager {
+    method public android.media.midi.MidiDeviceInfo[] getDeviceList();
+    method public void openDevice(android.media.midi.MidiDeviceInfo, android.media.midi.MidiManager.DeviceOpenCallback, android.os.Handler);
+    method public void registerDeviceCallback(android.media.midi.MidiManager.DeviceCallback, android.os.Handler);
+    method public void unregisterDeviceCallback(android.media.midi.MidiManager.DeviceCallback);
+  }
+
+  public static class MidiManager.DeviceCallback {
+    ctor public MidiManager.DeviceCallback();
+    method public void onDeviceAdded(android.media.midi.MidiDeviceInfo);
+    method public void onDeviceRemoved(android.media.midi.MidiDeviceInfo);
+    method public void onDeviceStatusChanged(android.media.midi.MidiDeviceStatus);
+  }
+
+  public static abstract class MidiManager.DeviceOpenCallback {
+    ctor public MidiManager.DeviceOpenCallback();
+    method public abstract void onDeviceOpened(android.media.midi.MidiDeviceInfo, android.media.midi.MidiDevice);
+  }
+
   public final class MidiOutputPort extends android.media.midi.MidiSender implements java.io.Closeable {
     method public void close() throws java.io.IOException;
     method public void connect(android.media.midi.MidiReceiver);
@@ -18286,6 +18457,7 @@
     method public void play();
     method public void playFromMediaId(java.lang.String, android.os.Bundle);
     method public void playFromSearch(java.lang.String, android.os.Bundle);
+    method public void playFromUri(android.net.Uri, android.os.Bundle);
     method public void rewind();
     method public void seekTo(long);
     method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
@@ -18333,6 +18505,7 @@
     method public void onPlay();
     method public void onPlayFromMediaId(java.lang.String, android.os.Bundle);
     method public void onPlayFromSearch(java.lang.String, android.os.Bundle);
+    method public void onPlayFromUri(android.net.Uri, android.os.Bundle);
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.media.Rating);
@@ -18387,6 +18560,7 @@
     field public static final long ACTION_PLAY = 4L; // 0x4L
     field public static final long ACTION_PLAY_FROM_MEDIA_ID = 1024L; // 0x400L
     field public static final long ACTION_PLAY_FROM_SEARCH = 2048L; // 0x800L
+    field public static final long ACTION_PLAY_FROM_URI = 8192L; // 0x2000L
     field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
@@ -18727,6 +18901,10 @@
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
     field public static final java.lang.String META_DATA_CONTENT_RATING_SYSTEMS = "android.media.tv.metadata.CONTENT_RATING_SYSTEMS";
+    field public static final long TIME_SHIFT_INVALID_TIME = -9223372036854775808L; // 0x8000000000000000L
+    field public static final int TIME_SHIFT_STATUS_AVAILABLE = 0; // 0x0
+    field public static final int TIME_SHIFT_STATUS_ERROR = 2; // 0x2
+    field public static final int TIME_SHIFT_STATUS_UNAVAILABLE = 1; // 0x1
     field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3
     field public static final int VIDEO_UNAVAILABLE_REASON_TUNING = 1; // 0x1
     field public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0; // 0x0
@@ -18769,6 +18947,9 @@
     method public void onSessionCreated(android.media.tv.TvInputManager.Session);
     method public void onSessionEvent(android.media.tv.TvInputManager.Session, java.lang.String, android.os.Bundle);
     method public void onSessionReleased(android.media.tv.TvInputManager.Session);
+    method public void onTimeShiftCurrentPositionChanged(android.media.tv.TvInputManager.Session, long);
+    method public void onTimeShiftStartPositionChanged(android.media.tv.TvInputManager.Session, long);
+    method public void onTimeShiftStatusChanged(android.media.tv.TvInputManager.Session, int);
     method public void onTrackSelected(android.media.tv.TvInputManager.Session, int, java.lang.String);
     method public void onTracksChanged(android.media.tv.TvInputManager.Session, java.util.List<android.media.tv.TvTrackInfo>);
     method public void onVideoAvailable(android.media.tv.TvInputManager.Session);
@@ -18811,6 +18992,8 @@
     method public void notifyContentAllowed();
     method public void notifyContentBlocked(android.media.tv.TvContentRating);
     method public void notifySessionEvent(java.lang.String, android.os.Bundle);
+    method public void notifyTimeShiftStartPositionChanged(long);
+    method public void notifyTimeShiftStatusChanged(int);
     method public void notifyTrackSelected(int, java.lang.String);
     method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>);
     method public void notifyVideoAvailable();
@@ -18830,6 +19013,11 @@
     method public abstract void onSetStreamVolume(float);
     method public abstract boolean onSetSurface(android.view.Surface);
     method public void onSurfaceChanged(int, int, int);
+    method public long onTimeShiftGetCurrentPosition();
+    method public void onTimeShiftPause();
+    method public void onTimeShiftResume();
+    method public void onTimeShiftSeekTo(long);
+    method public void onTimeShiftSetPlaybackRate(float, int);
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
     method public abstract boolean onTune(android.net.Uri);
@@ -18902,6 +19090,7 @@
     method public java.util.List<android.media.tv.TvTrackInfo> getTracks(int);
     method protected void onLayout(boolean, int, int, int, int);
     method public boolean onUnhandledInputEvent(android.view.InputEvent);
+    method public void registerTimeShiftPositionCallback(android.media.tv.TvView.TimeShiftPositionCallback);
     method public void requestUnblockContent(android.media.tv.TvContentRating);
     method public void reset();
     method public void selectTrack(int, java.lang.String);
@@ -18913,14 +19102,25 @@
     method public void setStreamVolume(float);
     method public void setZOrderMediaOverlay(boolean);
     method public void setZOrderOnTop(boolean);
+    method public void timeShiftPause();
+    method public void timeShiftResume();
+    method public void timeShiftSeekTo(long);
+    method public void timeShiftSetPlaybackRate(float, int);
     method public void tune(java.lang.String, android.net.Uri);
     method public void tune(java.lang.String, android.net.Uri, android.os.Bundle);
+    method public void unregisterTimeShiftPositionCallback(android.media.tv.TvView.TimeShiftPositionCallback);
   }
 
   public static abstract interface TvView.OnUnhandledInputEventListener {
     method public abstract boolean onUnhandledInputEvent(android.view.InputEvent);
   }
 
+  public static abstract class TvView.TimeShiftPositionCallback {
+    ctor public TvView.TimeShiftPositionCallback();
+    method public void onTimeShiftCurrentPositionChanged(java.lang.String, long);
+    method public void onTimeShiftStartPositionChanged(java.lang.String, long);
+  }
+
   public static abstract class TvView.TvInputCallback {
     ctor public TvView.TvInputCallback();
     method public void onChannelRetuned(java.lang.String, android.net.Uri);
@@ -18929,6 +19129,7 @@
     method public void onContentBlocked(java.lang.String, android.media.tv.TvContentRating);
     method public void onDisconnected(java.lang.String);
     method public void onEvent(java.lang.String, java.lang.String, android.os.Bundle);
+    method public void onTimeShiftStatusChanged(java.lang.String, int);
     method public void onTrackSelected(java.lang.String, int, java.lang.String);
     method public void onTracksChanged(java.lang.String, java.util.List<android.media.tv.TvTrackInfo>);
     method public void onVideoAvailable(java.lang.String);
@@ -20072,7 +20273,8 @@
   }
 
   public class RttManager {
-    method public android.net.wifi.RttManager.Capabilities getCapabilities();
+    method public deprecated android.net.wifi.RttManager.Capabilities getCapabilities();
+    method public android.net.wifi.RttManager.RttCapabilities getRttCapabilities();
     method public void startRanging(android.net.wifi.RttManager.RttParams[], android.net.wifi.RttManager.RttListener);
     method public void stopRanging(android.net.wifi.RttManager.RttListener);
     field public static final int BASE = 160256; // 0x27200
@@ -20082,10 +20284,19 @@
     field public static final int CMD_OP_STOP_RANGING = 160257; // 0x27201
     field public static final int CMD_OP_SUCCEEDED = 160259; // 0x27203
     field public static final java.lang.String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description";
+    field public static final int PREAMBLE_HT = 2; // 0x2
+    field public static final int PREAMBLE_LEGACY = 1; // 0x1
+    field public static final int PREAMBLE_VHT = 4; // 0x4
     field public static final int REASON_INVALID_LISTENER = -3; // 0xfffffffd
     field public static final int REASON_INVALID_REQUEST = -4; // 0xfffffffc
     field public static final int REASON_NOT_AVAILABLE = -2; // 0xfffffffe
     field public static final int REASON_UNSPECIFIED = -1; // 0xffffffff
+    field public static final int RTT_BW_10_SUPPORT = 2; // 0x2
+    field public static final int RTT_BW_160_SUPPORT = 32; // 0x20
+    field public static final int RTT_BW_20_SUPPORT = 4; // 0x4
+    field public static final int RTT_BW_40_SUPPORT = 8; // 0x8
+    field public static final int RTT_BW_5_SUPPORT = 1; // 0x1
+    field public static final int RTT_BW_80_SUPPORT = 16; // 0x10
     field public static final int RTT_CHANNEL_WIDTH_10 = 6; // 0x6
     field public static final int RTT_CHANNEL_WIDTH_160 = 3; // 0x3
     field public static final int RTT_CHANNEL_WIDTH_20 = 0; // 0x0
@@ -20093,26 +20304,31 @@
     field public static final int RTT_CHANNEL_WIDTH_5 = 5; // 0x5
     field public static final int RTT_CHANNEL_WIDTH_80 = 2; // 0x2
     field public static final int RTT_CHANNEL_WIDTH_80P80 = 4; // 0x4
-    field public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; // 0xffffffff
+    field public static final deprecated int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; // 0xffffffff
     field public static final int RTT_PEER_TYPE_AP = 1; // 0x1
     field public static final int RTT_PEER_TYPE_STA = 2; // 0x2
     field public static final int RTT_PEER_TYPE_UNSPECIFIED = 0; // 0x0
     field public static final int RTT_STATUS_ABORTED = 8; // 0x8
     field public static final int RTT_STATUS_FAILURE = 1; // 0x1
     field public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; // 0x6
+    field public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; // 0xc
+    field public static final int RTT_STATUS_FAIL_INVALID_TS = 9; // 0x9
     field public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; // 0x4
     field public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7; // 0x7
     field public static final int RTT_STATUS_FAIL_NO_RSP = 2; // 0x2
+    field public static final int RTT_STATUS_FAIL_PROTOCOL = 10; // 0xa
     field public static final int RTT_STATUS_FAIL_REJECTED = 3; // 0x3
+    field public static final int RTT_STATUS_FAIL_SCHEDULE = 11; // 0xb
     field public static final int RTT_STATUS_FAIL_TM_TIMEOUT = 5; // 0x5
     field public static final int RTT_STATUS_SUCCESS = 0; // 0x0
-    field public static final int RTT_TYPE_11_MC = 4; // 0x4
-    field public static final int RTT_TYPE_11_V = 2; // 0x2
+    field public static final deprecated int RTT_TYPE_11_MC = 4; // 0x4
+    field public static final deprecated int RTT_TYPE_11_V = 2; // 0x2
     field public static final int RTT_TYPE_ONE_SIDED = 1; // 0x1
-    field public static final int RTT_TYPE_UNSPECIFIED = 0; // 0x0
+    field public static final int RTT_TYPE_TWO_SIDED = 4; // 0x4
+    field public static final deprecated int RTT_TYPE_UNSPECIFIED = 0; // 0x0
   }
 
-  public class RttManager.Capabilities {
+  public deprecated class RttManager.Capabilities {
     ctor public RttManager.Capabilities();
     field public int supportedPeerType;
     field public int supportedType;
@@ -20131,6 +20347,20 @@
     field public android.net.wifi.RttManager.RttResult[] mResults;
   }
 
+  public static class RttManager.RttCapabilities implements android.os.Parcelable {
+    ctor public RttManager.RttCapabilities();
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public int bwSupported;
+    field public boolean lciSupported;
+    field public boolean lcrSupported;
+    field public boolean oneSidedRttSupported;
+    field public int preambleSupported;
+    field public deprecated boolean supportedPeerType;
+    field public deprecated boolean supportedType;
+    field public boolean twoSided11McRttSupported;
+  }
+
   public static abstract interface RttManager.RttListener {
     method public abstract void onAborted();
     method public abstract void onFailure(int, java.lang.String);
@@ -20139,30 +20369,64 @@
 
   public static class RttManager.RttParams {
     ctor public RttManager.RttParams();
+    field public boolean LCIRequest;
+    field public boolean LCRRequest;
+    field public int bandwidth;
     field public java.lang.String bssid;
+    field public int burstTimeout;
+    field public int centerFreq0;
+    field public int centerFreq1;
     field public int channelWidth;
     field public int deviceType;
     field public int frequency;
-    field public int num_retries;
-    field public int num_samples;
+    field public int interval;
+    field public int numRetriesPerFTMR;
+    field public int numRetriesPerMeasurementFrame;
+    field public int numSamplesPerBurst;
+    field public deprecated int num_retries;
+    field public deprecated int num_samples;
+    field public int numberBurst;
+    field public int preamble;
     field public int requestType;
   }
 
   public static class RttManager.RttResult {
     ctor public RttManager.RttResult();
     field public java.lang.String bssid;
-    field public int distance_cm;
-    field public int distance_sd_cm;
-    field public int distance_spread_cm;
-    field public int requestType;
+    field public int burstDuration;
+    field public int burstNumber;
+    field public int distance;
+    field public int distanceSpread;
+    field public int distanceStandardDeviation;
+    field public deprecated int distance_cm;
+    field public deprecated int distance_sd_cm;
+    field public deprecated int distance_spread_cm;
+    field public int frameNumberPerBurstPeer;
+    field public int measurementFrameNumber;
+    field public int measurementType;
+    field public deprecated int requestType;
+    field public int retryAfterDuration;
     field public int rssi;
-    field public int rssi_spread;
-    field public long rtt_ns;
-    field public long rtt_sd_ns;
-    field public long rtt_spread_ns;
+    field public int rssiSpread;
+    field public deprecated int rssi_spread;
+    field public long rtt;
+    field public long rttSpread;
+    field public long rttStandardDeviation;
+    field public deprecated long rtt_ns;
+    field public deprecated long rtt_sd_ns;
+    field public deprecated long rtt_spread_ns;
+    field public int rxRate;
     field public int status;
+    field public int successMeasurementFrameNumber;
     field public long ts;
-    field public int tx_rate;
+    field public int txRate;
+    field public deprecated int tx_rate;
+  }
+
+  public class RttManager.wifiInformationElement {
+    ctor public RttManager.wifiInformationElement();
+    field public java.lang.String data;
+    field public int id;
   }
 
   public class ScanResult implements android.os.Parcelable {
@@ -20182,7 +20446,10 @@
     field public int frequency;
     field public boolean is80211McRTTResponder;
     field public int level;
+    field public java.lang.String operatorFriendlyName;
+    field public boolean passpointNetwork;
     field public long timestamp;
+    field public java.lang.String venueName;
   }
 
   public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
@@ -20209,6 +20476,7 @@
   public class WifiConfiguration implements android.os.Parcelable {
     ctor public WifiConfiguration();
     method public int describeContents();
+    method public boolean isPasspoint();
     method public void writeToParcel(android.os.Parcel, int);
     field public java.lang.String BSSID;
     field public java.lang.String FQDN;
@@ -20334,6 +20602,7 @@
 
   public static final class WifiEnterpriseConfig.Eap {
     field public static final int AKA = 5; // 0x5
+    field public static final int AKA_PRIME = 6; // 0x6
     field public static final int NONE = -1; // 0xffffffff
     field public static final int PEAP = 0; // 0x0
     field public static final int PWD = 3; // 0x3
@@ -24245,6 +24514,7 @@
     field public static java.lang.String DIRECTORY_RINGTONES;
     field public static final java.lang.String MEDIA_BAD_REMOVAL = "bad_removal";
     field public static final java.lang.String MEDIA_CHECKING = "checking";
+    field public static final java.lang.String MEDIA_EJECTING = "ejecting";
     field public static final java.lang.String MEDIA_MOUNTED = "mounted";
     field public static final java.lang.String MEDIA_MOUNTED_READ_ONLY = "mounted_ro";
     field public static final java.lang.String MEDIA_NOFS = "nofs";
@@ -24676,15 +24946,19 @@
   }
 
   public final class PowerManager {
+    method public boolean isDeviceIdleMode();
     method public boolean isInteractive();
     method public boolean isPowerSaveMode();
+    method public boolean isScreenBrightnessBoosted();
     method public deprecated boolean isScreenOn();
     method public boolean isWakeLockLevelSupported(int);
     method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
     method public void reboot(java.lang.String);
     method public void userActivity(long, int, int);
     field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
+    field public static final java.lang.String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
     field public static final java.lang.String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
+    field public static final java.lang.String ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED = "android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED";
     field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a
     field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
     field public static final int PARTIAL_WAKE_LOCK = 1; // 0x1
@@ -25763,8 +26037,16 @@
     field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
     field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
     field public static final java.lang.String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
+    field public static final java.lang.String ACTION_VOICE_CANCEL_ALARM = "android.intent.action.VOICE_CANCEL_ALARM";
+    field public static final java.lang.String ACTION_VOICE_DELETE_ALARM = "android.intent.action.VOICE_DELETE_ALARM";
+    field public static final java.lang.String ALARM_SEARCH_MODE_ALL = "all";
+    field public static final java.lang.String ALARM_SEARCH_MODE_NEXT = "next";
+    field public static final java.lang.String ALARM_SEARCH_MODE_NONE = "none";
+    field public static final java.lang.String ALARM_SEARCH_MODE_TIME = "time";
+    field public static final java.lang.String EXTRA_ALARM_SEARCH_MODE = "android.intent.extra.alarm.ALARM_SEARCH_MODE";
     field public static final java.lang.String EXTRA_DAYS = "android.intent.extra.alarm.DAYS";
     field public static final java.lang.String EXTRA_HOUR = "android.intent.extra.alarm.HOUR";
+    field public static final java.lang.String EXTRA_IS_PM = "android.intent.extra.alarm.IS_PM";
     field public static final java.lang.String EXTRA_LENGTH = "android.intent.extra.alarm.LENGTH";
     field public static final java.lang.String EXTRA_MESSAGE = "android.intent.extra.alarm.MESSAGE";
     field public static final java.lang.String EXTRA_MINUTES = "android.intent.extra.alarm.MINUTES";
@@ -27443,6 +27725,7 @@
     method public static java.lang.String getVersion(android.content.Context);
     field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
     field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
+    field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM";
     field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
     field public static final java.lang.String AUTHORITY = "media";
     field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
@@ -27757,6 +28040,108 @@
     field public static final java.lang.String SIZE = "_size";
   }
 
+  public abstract class SearchIndexableData {
+    ctor public SearchIndexableData();
+    ctor public SearchIndexableData(android.content.Context);
+    field public java.lang.String className;
+    field public android.content.Context context;
+    field public boolean enabled;
+    field public int iconResId;
+    field public java.lang.String intentAction;
+    field public java.lang.String intentTargetClass;
+    field public java.lang.String intentTargetPackage;
+    field public java.lang.String key;
+    field public java.util.Locale locale;
+    field public java.lang.String packageName;
+    field public int rank;
+    field public int userId;
+  }
+
+  public class SearchIndexableResource extends android.provider.SearchIndexableData {
+    ctor public SearchIndexableResource(int, int, java.lang.String, int);
+    ctor public SearchIndexableResource(android.content.Context);
+    field public int xmlResId;
+  }
+
+  public class SearchIndexablesContract {
+    ctor public SearchIndexablesContract();
+    field public static final int COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE = 0; // 0x0
+    field public static final int COLUMN_INDEX_RAW_CLASS_NAME = 7; // 0x7
+    field public static final int COLUMN_INDEX_RAW_ENTRIES = 4; // 0x4
+    field public static final int COLUMN_INDEX_RAW_ICON_RESID = 8; // 0x8
+    field public static final int COLUMN_INDEX_RAW_INTENT_ACTION = 9; // 0x9
+    field public static final int COLUMN_INDEX_RAW_INTENT_TARGET_CLASS = 11; // 0xb
+    field public static final int COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE = 10; // 0xa
+    field public static final int COLUMN_INDEX_RAW_KEY = 12; // 0xc
+    field public static final int COLUMN_INDEX_RAW_KEYWORDS = 5; // 0x5
+    field public static final int COLUMN_INDEX_RAW_RANK = 0; // 0x0
+    field public static final int COLUMN_INDEX_RAW_SCREEN_TITLE = 6; // 0x6
+    field public static final int COLUMN_INDEX_RAW_SUMMARY_OFF = 3; // 0x3
+    field public static final int COLUMN_INDEX_RAW_SUMMARY_ON = 2; // 0x2
+    field public static final int COLUMN_INDEX_RAW_TITLE = 1; // 0x1
+    field public static final int COLUMN_INDEX_RAW_USER_ID = 13; // 0xd
+    field public static final int COLUMN_INDEX_XML_RES_CLASS_NAME = 2; // 0x2
+    field public static final int COLUMN_INDEX_XML_RES_ICON_RESID = 3; // 0x3
+    field public static final int COLUMN_INDEX_XML_RES_INTENT_ACTION = 4; // 0x4
+    field public static final int COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS = 6; // 0x6
+    field public static final int COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE = 5; // 0x5
+    field public static final int COLUMN_INDEX_XML_RES_RANK = 0; // 0x0
+    field public static final int COLUMN_INDEX_XML_RES_RESID = 1; // 0x1
+    field public static final java.lang.String INDEXABLES_RAW = "indexables_raw";
+    field public static final java.lang.String[] INDEXABLES_RAW_COLUMNS;
+    field public static final java.lang.String INDEXABLES_RAW_PATH = "settings/indexables_raw";
+    field public static final java.lang.String INDEXABLES_XML_RES = "indexables_xml_res";
+    field public static final java.lang.String[] INDEXABLES_XML_RES_COLUMNS;
+    field public static final java.lang.String INDEXABLES_XML_RES_PATH = "settings/indexables_xml_res";
+    field public static final java.lang.String NON_INDEXABLES_KEYS = "non_indexables_key";
+    field public static final java.lang.String[] NON_INDEXABLES_KEYS_COLUMNS;
+    field public static final java.lang.String NON_INDEXABLES_KEYS_PATH = "settings/non_indexables_key";
+    field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.SEARCH_INDEXABLES_PROVIDER";
+  }
+
+  public static class SearchIndexablesContract.BaseColumns {
+    field public static final java.lang.String COLUMN_CLASS_NAME = "className";
+    field public static final java.lang.String COLUMN_ICON_RESID = "iconResId";
+    field public static final java.lang.String COLUMN_INTENT_ACTION = "intentAction";
+    field public static final java.lang.String COLUMN_INTENT_TARGET_CLASS = "intentTargetClass";
+    field public static final java.lang.String COLUMN_INTENT_TARGET_PACKAGE = "intentTargetPackage";
+    field public static final java.lang.String COLUMN_RANK = "rank";
+  }
+
+  public static final class SearchIndexablesContract.NonIndexableKey extends android.provider.SearchIndexablesContract.BaseColumns {
+    field public static final java.lang.String COLUMN_KEY_VALUE = "key";
+    field public static final java.lang.String MIME_TYPE = "vnd.android.cursor.dir/non_indexables_key";
+  }
+
+  public static final class SearchIndexablesContract.RawData extends android.provider.SearchIndexablesContract.BaseColumns {
+    field public static final java.lang.String COLUMN_ENTRIES = "entries";
+    field public static final java.lang.String COLUMN_KEY = "key";
+    field public static final java.lang.String COLUMN_KEYWORDS = "keywords";
+    field public static final java.lang.String COLUMN_SCREEN_TITLE = "screenTitle";
+    field public static final java.lang.String COLUMN_SUMMARY_OFF = "summaryOff";
+    field public static final java.lang.String COLUMN_SUMMARY_ON = "summaryOn";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_USER_ID = "user_id";
+    field public static final java.lang.String MIME_TYPE = "vnd.android.cursor.dir/indexables_raw";
+  }
+
+  public static final class SearchIndexablesContract.XmlResource extends android.provider.SearchIndexablesContract.BaseColumns {
+    field public static final java.lang.String COLUMN_XML_RESID = "xmlResId";
+    field public static final java.lang.String MIME_TYPE = "vnd.android.cursor.dir/indexables_xml_res";
+  }
+
+  public abstract class SearchIndexablesProvider extends android.content.ContentProvider {
+    ctor public SearchIndexablesProvider();
+    method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+    method public java.lang.String getType(android.net.Uri);
+    method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
+    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
+    method public abstract android.database.Cursor queryNonIndexableKeys(java.lang.String[]);
+    method public abstract android.database.Cursor queryRawData(java.lang.String[]);
+    method public abstract android.database.Cursor queryXmlResources(java.lang.String[]);
+    method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
+  }
+
   public class SearchRecentSuggestions {
     ctor public SearchRecentSuggestions(android.content.Context, java.lang.String, int);
     method public void clearHistory();
@@ -27814,6 +28199,8 @@
     field public static final java.lang.String ACTION_USAGE_ACCESS_SETTINGS = "android.settings.USAGE_ACCESS_SETTINGS";
     field public static final java.lang.String ACTION_USER_DICTIONARY_SETTINGS = "android.settings.USER_DICTIONARY_SETTINGS";
     field public static final java.lang.String ACTION_VOICE_CONTROL_AIRPLANE_MODE = "android.settings.VOICE_CONTROL_AIRPLANE_MODE";
+    field public static final java.lang.String ACTION_VOICE_CONTROL_BATTERY_SAVER_MODE = "android.settings.VOICE_CONTROL_BATTERY_SAVER_MODE";
+    field public static final java.lang.String ACTION_VOICE_CONTROL_DO_NOT_DISTURB_MODE = "android.settings.VOICE_CONTROL_DO_NOT_DISTURB_MODE";
     field public static final java.lang.String ACTION_VOICE_INPUT_SETTINGS = "android.settings.VOICE_INPUT_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
@@ -27822,6 +28209,9 @@
     field public static final java.lang.String EXTRA_ACCOUNT_TYPES = "account_types";
     field public static final java.lang.String EXTRA_AIRPLANE_MODE_ENABLED = "airplane_mode_enabled";
     field public static final java.lang.String EXTRA_AUTHORITIES = "authorities";
+    field public static final java.lang.String EXTRA_BATTERY_SAVER_MODE_ENABLED = "android.settings.extra.battery_saver_mode_enabled";
+    field public static final java.lang.String EXTRA_DO_NOT_DISTURB_MODE_ENABLED = "android.settings.extra.do_not_disturb_mode_enabled";
+    field public static final java.lang.String EXTRA_DO_NOT_DISTURB_MODE_MINUTES = "android.settings.extra.do_not_disturb_mode_minutes";
     field public static final java.lang.String EXTRA_INPUT_METHOD_ID = "input_method_id";
   }
 
@@ -28500,6 +28890,16 @@
     method public void copy1DRangeFromUnchecked(int, int, short[]);
     method public void copy1DRangeFromUnchecked(int, int, byte[]);
     method public void copy1DRangeFromUnchecked(int, int, float[]);
+    method public void copy1DRangeTo(int, int, java.lang.Object);
+    method public void copy1DRangeTo(int, int, int[]);
+    method public void copy1DRangeTo(int, int, short[]);
+    method public void copy1DRangeTo(int, int, byte[]);
+    method public void copy1DRangeTo(int, int, float[]);
+    method public void copy1DRangeToUnchecked(int, int, java.lang.Object);
+    method public void copy1DRangeToUnchecked(int, int, int[]);
+    method public void copy1DRangeToUnchecked(int, int, short[]);
+    method public void copy1DRangeToUnchecked(int, int, byte[]);
+    method public void copy1DRangeToUnchecked(int, int, float[]);
     method public void copy2DRangeFrom(int, int, int, int, java.lang.Object);
     method public void copy2DRangeFrom(int, int, int, int, byte[]);
     method public void copy2DRangeFrom(int, int, int, int, short[]);
@@ -28507,6 +28907,14 @@
     method public void copy2DRangeFrom(int, int, int, int, float[]);
     method public void copy2DRangeFrom(int, int, int, int, android.renderscript.Allocation, int, int);
     method public void copy2DRangeFrom(int, int, android.graphics.Bitmap);
+    method public void copy2DRangeTo(int, int, int, int, java.lang.Object);
+    method public void copy2DRangeTo(int, int, int, int, byte[]);
+    method public void copy2DRangeTo(int, int, int, int, short[]);
+    method public void copy2DRangeTo(int, int, int, int, int[]);
+    method public void copy2DRangeTo(int, int, int, int, float[]);
+    method public void copy3DRangeFrom(int, int, int, int, int, int, java.lang.Object);
+    method public void copy3DRangeFrom(int, int, int, int, int, int, android.renderscript.Allocation, int, int, int);
+    method public void copy3DRangeTo(int, int, int, int, int, int, java.lang.Object);
     method public void copyFrom(android.renderscript.BaseObj[]);
     method public void copyFrom(java.lang.Object);
     method public void copyFrom(int[]);
@@ -28526,6 +28934,7 @@
     method public void copyTo(short[]);
     method public void copyTo(int[]);
     method public void copyTo(float[]);
+    method public void copyToFieldPacker(int, int, int, int, android.renderscript.FieldPacker);
     method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
     method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap);
     method public static android.renderscript.Allocation createCubemapFromCubeFaces(android.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
@@ -28549,8 +28958,10 @@
     method public void ioReceive();
     method public void ioSend();
     method public deprecated synchronized void resize(int);
+    method public void setAutoPadding(boolean);
     method public void setFromFieldPacker(int, android.renderscript.FieldPacker);
     method public void setFromFieldPacker(int, int, android.renderscript.FieldPacker);
+    method public void setFromFieldPacker(int, int, int, int, android.renderscript.FieldPacker);
     method public void setOnBufferAvailableListener(android.renderscript.Allocation.OnBufferAvailableListener);
     method public void setSurface(android.view.Surface);
     method public void syncAll(int);
@@ -28647,6 +29058,10 @@
     method public static android.renderscript.Element A_8(android.renderscript.RenderScript);
     method public static android.renderscript.Element BOOLEAN(android.renderscript.RenderScript);
     method public static android.renderscript.Element ELEMENT(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F16(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F16_2(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F16_3(android.renderscript.RenderScript);
+    method public static android.renderscript.Element F16_4(android.renderscript.RenderScript);
     method public static android.renderscript.Element F32(android.renderscript.RenderScript);
     method public static android.renderscript.Element F32_2(android.renderscript.RenderScript);
     method public static android.renderscript.Element F32_3(android.renderscript.RenderScript);
@@ -28745,6 +29160,7 @@
     method public static android.renderscript.Element.DataType valueOf(java.lang.String);
     method public static final android.renderscript.Element.DataType[] values();
     enum_constant public static final android.renderscript.Element.DataType BOOLEAN;
+    enum_constant public static final android.renderscript.Element.DataType FLOAT_16;
     enum_constant public static final android.renderscript.Element.DataType FLOAT_32;
     enum_constant public static final android.renderscript.Element.DataType FLOAT_64;
     enum_constant public static final android.renderscript.Element.DataType MATRIX_2X2;
@@ -29018,11 +29434,14 @@
     method public static android.renderscript.RenderScript create(android.content.Context);
     method public static android.renderscript.RenderScript create(android.content.Context, android.renderscript.RenderScript.ContextType);
     method public static android.renderscript.RenderScript create(android.content.Context, android.renderscript.RenderScript.ContextType, int);
+    method public static android.renderscript.RenderScript createMultiContext(android.content.Context, android.renderscript.RenderScript.ContextType, int, int);
     method public void destroy();
     method public void finish();
     method public final android.content.Context getApplicationContext();
     method public android.renderscript.RenderScript.RSErrorHandler getErrorHandler();
     method public android.renderscript.RenderScript.RSMessageHandler getMessageHandler();
+    method public static long getMinorID();
+    method public static void releaseAllContexts();
     method public void sendMessage(int, int[]);
     method public void setErrorHandler(android.renderscript.RenderScript.RSErrorHandler);
     method public void setMessageHandler(android.renderscript.RenderScript.RSMessageHandler);
@@ -29104,9 +29523,12 @@
   public class Script extends android.renderscript.BaseObj {
     method public void bindAllocation(android.renderscript.Allocation, int);
     method protected android.renderscript.Script.FieldID createFieldID(int, android.renderscript.Element);
+    method protected android.renderscript.Script.InvokeID createInvokeID(int);
     method protected android.renderscript.Script.KernelID createKernelID(int, int, android.renderscript.Element, android.renderscript.Element);
     method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker);
     method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker, android.renderscript.Script.LaunchOptions);
+    method protected void forEach(int, android.renderscript.Allocation[], android.renderscript.Allocation, android.renderscript.FieldPacker);
+    method protected void forEach(int, android.renderscript.Allocation[], android.renderscript.Allocation, android.renderscript.FieldPacker, android.renderscript.Script.LaunchOptions);
     method public boolean getVarB(int);
     method public double getVarD(int);
     method public float getVarF(int);
@@ -29144,6 +29566,9 @@
   public static final class Script.FieldID extends android.renderscript.BaseObj {
   }
 
+  public static final class Script.InvokeID extends android.renderscript.BaseObj {
+  }
+
   public static final class Script.KernelID extends android.renderscript.BaseObj {
   }
 
@@ -29181,6 +29606,41 @@
     method public android.renderscript.ScriptGroup create();
   }
 
+  public class ScriptGroup2 extends android.renderscript.BaseObj {
+    ctor public ScriptGroup2(long, android.renderscript.RenderScript);
+    method public java.lang.Object[] execute(java.lang.Object...);
+  }
+
+  public static final class ScriptGroup2.Binding {
+    ctor public ScriptGroup2.Binding(android.renderscript.Script.FieldID, java.lang.Object);
+    method public android.renderscript.Script.FieldID getField();
+    method public java.lang.Object getValue();
+  }
+
+  public static final class ScriptGroup2.Builder {
+    ctor public ScriptGroup2.Builder(android.renderscript.RenderScript);
+    method public android.renderscript.ScriptGroup2.UnboundValue addInput();
+    method public android.renderscript.ScriptGroup2.Closure addInvoke(android.renderscript.Script.InvokeID, java.lang.Object[], java.util.Map<android.renderscript.Script.FieldID, java.lang.Object>);
+    method public android.renderscript.ScriptGroup2.Closure addInvoke(android.renderscript.Script.InvokeID, java.lang.Object...);
+    method public android.renderscript.ScriptGroup2.Closure addKernel(android.renderscript.Script.KernelID, android.renderscript.Type, java.lang.Object[], java.util.Map<android.renderscript.Script.FieldID, java.lang.Object>);
+    method public android.renderscript.ScriptGroup2.Closure addKernel(android.renderscript.Script.KernelID, android.renderscript.Type, java.lang.Object...);
+    method public android.renderscript.ScriptGroup2 create(android.renderscript.ScriptGroup2.Future...);
+  }
+
+  public static class ScriptGroup2.Closure extends android.renderscript.BaseObj {
+    ctor public ScriptGroup2.Closure(long, android.renderscript.RenderScript);
+    ctor public ScriptGroup2.Closure(android.renderscript.RenderScript, android.renderscript.Script.KernelID, android.renderscript.Type, java.lang.Object[], java.util.Map<android.renderscript.Script.FieldID, java.lang.Object>);
+    ctor public ScriptGroup2.Closure(android.renderscript.RenderScript, android.renderscript.Script.InvokeID, java.lang.Object[], java.util.Map<android.renderscript.Script.FieldID, java.lang.Object>);
+    method public android.renderscript.ScriptGroup2.Future getGlobal(android.renderscript.Script.FieldID);
+    method public android.renderscript.ScriptGroup2.Future getReturn();
+  }
+
+  public static class ScriptGroup2.Future {
+  }
+
+  public static class ScriptGroup2.UnboundValue {
+  }
+
   public abstract class ScriptIntrinsic extends android.renderscript.Script {
   }
 
@@ -29354,6 +29814,8 @@
     method public static android.renderscript.Type createX(android.renderscript.RenderScript, android.renderscript.Element, int);
     method public static android.renderscript.Type createXY(android.renderscript.RenderScript, android.renderscript.Element, int, int);
     method public static android.renderscript.Type createXYZ(android.renderscript.RenderScript, android.renderscript.Element, int, int, int);
+    method public int getArray(int);
+    method public int getArrayCount();
     method public int getCount();
     method public android.renderscript.Element getElement();
     method public int getX();
@@ -29367,6 +29829,7 @@
   public static class Type.Builder {
     ctor public Type.Builder(android.renderscript.RenderScript, android.renderscript.Element);
     method public android.renderscript.Type create();
+    method public android.renderscript.Type.Builder setArray(int, int);
     method public android.renderscript.Type.Builder setFaces(boolean);
     method public android.renderscript.Type.Builder setMipmaps(boolean);
     method public android.renderscript.Type.Builder setX(int);
@@ -29496,6 +29959,11 @@
     method public android.security.KeyStoreParameter.Builder setEncryptionRequired(boolean);
   }
 
+  public class NetworkSecurityPolicy {
+    method public static android.security.NetworkSecurityPolicy getInstance();
+    method public boolean isCleartextTrafficPermitted();
+  }
+
 }
 
 package android.service.carrier {
@@ -29721,6 +30189,7 @@
     method public final void setOnNotificationPostedTrim(int);
     method public void unregisterAsSystemService() throws android.os.RemoteException;
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
+    field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
     field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
     field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
     field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
@@ -29888,6 +30357,7 @@
     method public void showSession(android.os.Bundle, int);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
     field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
+    field public static final int START_SOURCE_ASSIST_GESTURE = 4; // 0x4
     field public static final int START_WITH_ASSIST = 1; // 0x1
     field public static final int START_WITH_SCREENSHOT = 2; // 0x2
   }
@@ -29896,6 +30366,7 @@
     ctor public VoiceInteractionSession(android.content.Context);
     ctor public VoiceInteractionSession(android.content.Context, android.os.Handler);
     method public void finish();
+    method public android.content.Context getContext();
     method public android.view.LayoutInflater getLayoutInflater();
     method public android.app.Dialog getWindow();
     method public void hide();
@@ -32075,6 +32546,7 @@
     method public int[] supplyPukReportResult(java.lang.String, java.lang.String);
     method public void toggleRadioOnOff();
     method public void updateServiceLocation();
+    field public static final java.lang.String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
     field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
     field public static final int CALL_STATE_IDLE = 0; // 0x0
@@ -32746,6 +33218,7 @@
     method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
     method public java.lang.String getInstallerPackageName(java.lang.String);
     method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(java.lang.String);
     method public android.content.Intent getLaunchIntentForPackage(java.lang.String);
     method public android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
     method public java.lang.String getNameForUid(int);
@@ -32771,6 +33244,7 @@
     method public android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
     method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public void grantPermission(java.lang.String, java.lang.String, android.os.UserHandle);
     method public boolean hasSystemFeature(java.lang.String);
     method public boolean isSafeMode();
     method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -32786,6 +33260,7 @@
     method public android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
     method public android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int);
     method public android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
+    method public void revokePermission(java.lang.String, java.lang.String, android.os.UserHandle);
     method public void setApplicationEnabledSetting(java.lang.String, int, int);
     method public void setComponentEnabledSetting(android.content.ComponentName, int, int);
     method public void setInstallerPackageName(java.lang.String, java.lang.String);
@@ -33110,6 +33585,9 @@
     method public final void increaseWidthTo(int);
     method public boolean isRtlCharAt(int);
     method protected final boolean isSpanned();
+    field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2
+    field public static final int BREAK_STRATEGY_HIGH_QUALITY = 1; // 0x1
+    field public static final int BREAK_STRATEGY_SIMPLE = 0; // 0x0
     field public static final int DIR_LEFT_TO_RIGHT = 1; // 0x1
     field public static final int DIR_RIGHT_TO_LEFT = -1; // 0xffffffff
   }
@@ -36524,8 +37002,10 @@
     method public long getTimeDelta();
     method public boolean isInProgress();
     method public boolean isQuickScaleEnabled();
+    method public boolean isSecondaryButtonScaleEnabled();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public void setQuickScaleEnabled(boolean);
+    method public void setSecondaryButtonScaleEnabled(boolean);
   }
 
   public static abstract interface ScaleGestureDetector.OnScaleGestureListener {
@@ -36746,6 +37226,7 @@
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    method public void dispatchProvideAssistStructure(android.view.ViewAssistStructure);
     method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSetActivated(boolean);
@@ -36806,6 +37287,10 @@
     method public boolean getFitsSystemWindows();
     method public java.util.ArrayList<android.view.View> getFocusables(int);
     method public void getFocusedRect(android.graphics.Rect);
+    method public android.graphics.drawable.Drawable getForeground();
+    method public int getForegroundGravity();
+    method public android.content.res.ColorStateList getForegroundTintList();
+    method public android.graphics.PorterDuff.Mode getForegroundTintMode();
     method public boolean getGlobalVisibleRect(android.graphics.Rect, android.graphics.Point);
     method public final boolean getGlobalVisibleRect(android.graphics.Rect);
     method public android.os.Handler getHandler();
@@ -36977,6 +37462,7 @@
     method protected void onDisplayHint(int);
     method public boolean onDragEvent(android.view.DragEvent);
     method protected void onDraw(android.graphics.Canvas);
+    method public void onDrawForeground(android.graphics.Canvas);
     method protected final void onDrawScrollBars(android.graphics.Canvas);
     method public boolean onFilterTouchEventForSecurity(android.view.MotionEvent);
     method protected void onFinishInflate();
@@ -36997,7 +37483,8 @@
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public void onProvideAssistStructure(android.view.ViewAssistStructure, android.os.Bundle);
+    method public void onProvideAssistStructure(android.view.ViewAssistStructure);
+    method public void onProvideVirtualAssistStructure(android.view.ViewAssistStructure);
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method public void onRtlPropertiesChanged(int);
     method protected android.os.Parcelable onSaveInstanceState();
@@ -37082,6 +37569,10 @@
     method public void setFitsSystemWindows(boolean);
     method public void setFocusable(boolean);
     method public void setFocusableInTouchMode(boolean);
+    method public void setForeground(android.graphics.drawable.Drawable);
+    method public void setForegroundGravity(int);
+    method public void setForegroundTintList(android.content.res.ColorStateList);
+    method public void setForegroundTintMode(android.graphics.PorterDuff.Mode);
     method public void setHapticFeedbackEnabled(boolean);
     method public void setHasTransientState(boolean);
     method public void setHorizontalFadingEdgeEnabled(boolean);
@@ -37403,14 +37894,36 @@
 
   public abstract class ViewAssistStructure {
     ctor public ViewAssistStructure();
+    method public abstract void asyncCommit();
+    method public abstract android.view.ViewAssistStructure asyncNewChild(int);
+    method public abstract void clearExtras();
+    method public abstract android.os.Bundle editExtras();
+    method public abstract int getChildCount();
     method public abstract java.lang.CharSequence getHint();
     method public abstract java.lang.CharSequence getText();
     method public abstract int getTextSelectionEnd();
     method public abstract int getTextSelectionStart();
+    method public abstract android.view.ViewAssistStructure newChild(int);
+    method public abstract void setAccessibilityFocused(boolean);
+    method public abstract void setActivated(boolean);
+    method public abstract void setCheckable(boolean);
+    method public abstract void setChecked(boolean);
+    method public abstract void setChildCount(int);
+    method public abstract void setClassName(java.lang.String);
+    method public abstract void setClickable(boolean);
+    method public abstract void setContentDescription(java.lang.CharSequence);
+    method public abstract void setDimens(int, int, int, int, int, int);
+    method public abstract void setEnabled(boolean);
+    method public abstract void setFocusable(boolean);
+    method public abstract void setFocused(boolean);
     method public abstract void setHint(java.lang.CharSequence);
+    method public abstract void setId(int, java.lang.String, java.lang.String, java.lang.String);
+    method public abstract void setLongClickable(boolean);
+    method public abstract void setSelected(boolean);
     method public abstract void setText(java.lang.CharSequence);
     method public abstract void setText(java.lang.CharSequence, int, int);
     method public abstract void setTextPaint(android.text.TextPaint);
+    method public abstract void setVisibility(int);
   }
 
   public class ViewConfiguration {
@@ -38443,9 +38956,11 @@
     method public void setVisibleToUser(boolean);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
+    field public static final java.lang.String ACTION_ARGUMENT_COLUMN_INT = "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
     field public static final java.lang.String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN = "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
     field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
     field public static final java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
+    field public static final java.lang.String ACTION_ARGUMENT_ROW_INT = "android.view.accessibility.action.ARGUMENT_ROW_INT";
     field public static final java.lang.String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
     field public static final java.lang.String ACTION_ARGUMENT_SELECTION_START_INT = "ACTION_ARGUMENT_SELECTION_START_INT";
     field public static final java.lang.String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
@@ -38503,9 +39018,11 @@
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_BACKWARD;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_FORWARD;
+    field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SCROLL_TO_POSITION;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SELECT;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_SELECTION;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_TEXT;
+    field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SHOW_ON_SCREEN;
   }
 
   public static final class AccessibilityNodeInfo.CollectionInfo {
@@ -40150,7 +40667,6 @@
     method public boolean shouldOverrideUrlLoading(android.webkit.WebView, java.lang.String);
     field public static final int ERROR_AUTHENTICATION = -4; // 0xfffffffc
     field public static final int ERROR_BAD_URL = -12; // 0xfffffff4
-    field public static final int ERROR_BLOCKED = -16; // 0xfffffff0
     field public static final int ERROR_CONNECT = -6; // 0xfffffffa
     field public static final int ERROR_FAILED_SSL_HANDSHAKE = -11; // 0xfffffff5
     field public static final int ERROR_FILE = -13; // 0xfffffff3
@@ -40355,6 +40871,7 @@
     method public abstract boolean onKeyUp(int, android.view.KeyEvent);
     method public abstract void onMeasure(int, int);
     method public abstract void onOverScrolled(int, int, boolean, boolean);
+    method public abstract void onProvideVirtualAssistStructure(android.view.ViewAssistStructure);
     method public abstract void onScrollChanged(int, int, int, int);
     method public abstract void onSizeChanged(int, int, int, int);
     method public abstract void onStartTemporaryDetach();
@@ -40708,7 +41225,7 @@
     field protected android.database.Cursor mDataCursor;
   }
 
-  public class AnalogClock extends android.view.View {
+  public deprecated class AnalogClock extends android.view.View {
     ctor public AnalogClock(android.content.Context);
     ctor public AnalogClock(android.content.Context, android.util.AttributeSet);
     ctor public AnalogClock(android.content.Context, android.util.AttributeSet, int);
@@ -41211,16 +41728,8 @@
     ctor public FrameLayout(android.content.Context, android.util.AttributeSet, int);
     ctor public FrameLayout(android.content.Context, android.util.AttributeSet, int, int);
     method public deprecated boolean getConsiderGoneChildrenWhenMeasuring();
-    method public android.graphics.drawable.Drawable getForeground();
-    method public int getForegroundGravity();
-    method public android.content.res.ColorStateList getForegroundTintList();
-    method public android.graphics.PorterDuff.Mode getForegroundTintMode();
     method public boolean getMeasureAllChildren();
     method protected void onLayout(boolean, int, int, int, int);
-    method public void setForeground(android.graphics.drawable.Drawable);
-    method public void setForegroundGravity(int);
-    method public void setForegroundTintList(android.content.res.ColorStateList);
-    method public void setForegroundTintMode(android.graphics.PorterDuff.Mode);
     method public void setMeasureAllChildren(boolean);
   }
 
@@ -42570,6 +43079,7 @@
     method public void endBatchEdit();
     method public boolean extractText(android.view.inputmethod.ExtractedTextRequest, android.view.inputmethod.ExtractedText);
     method public final int getAutoLinkMask();
+    method public int getBreakStrategy();
     method public int getCompoundDrawablePadding();
     method public android.content.res.ColorStateList getCompoundDrawableTintList();
     method public android.graphics.PorterDuff.Mode getCompoundDrawableTintMode();
@@ -42671,6 +43181,7 @@
     method public void removeTextChangedListener(android.text.TextWatcher);
     method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
+    method public void setBreakStrategy(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawableTintList(android.content.res.ColorStateList);
     method public void setCompoundDrawableTintMode(android.graphics.PorterDuff.Mode);
@@ -42777,12 +43288,16 @@
     ctor public TimePicker(android.content.Context, android.util.AttributeSet);
     ctor public TimePicker(android.content.Context, android.util.AttributeSet, int);
     ctor public TimePicker(android.content.Context, android.util.AttributeSet, int, int);
-    method public java.lang.Integer getCurrentHour();
-    method public java.lang.Integer getCurrentMinute();
+    method public deprecated java.lang.Integer getCurrentHour();
+    method public deprecated java.lang.Integer getCurrentMinute();
+    method public int getHour();
+    method public int getMinute();
     method public boolean is24HourView();
-    method public void setCurrentHour(java.lang.Integer);
-    method public void setCurrentMinute(java.lang.Integer);
+    method public deprecated void setCurrentHour(java.lang.Integer);
+    method public deprecated void setCurrentMinute(java.lang.Integer);
+    method public void setHour(int);
     method public void setIs24HourView(java.lang.Boolean);
+    method public void setMinute(int);
     method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
   }
 
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 29ba1d7..908d46e 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -112,7 +112,7 @@
                 "       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
                 "               [--user <USER_ID> | current]\n" +
                 "               [--no-window-animation] [--abi <ABI>] <COMPONENT>\n" +
-                "       am profile start [--user <USER_ID> current] <PROCESS> <FILE>\n" +
+                "       am profile start [--user <USER_ID> current] [--sampling INTERVAL] <PROCESS> <FILE>\n" +
                 "       am profile stop [--user <USER_ID> current] [<PROCESS>]\n" +
                 "       am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" +
                 "       am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
@@ -1031,6 +1031,7 @@
         boolean wall = false;
         int userId = UserHandle.USER_CURRENT;
         int profileType = 0;
+        mSamplingInterval = 0;
 
         String process = null;
 
@@ -1044,6 +1045,8 @@
                     userId = parseUserArg(nextArgRequired());
                 } else if (opt.equals("--wall")) {
                     wall = true;
+                } else if (opt.equals("--sampling")) {
+                    mSamplingInterval = Integer.parseInt(nextArgRequired());
                 } else {
                     System.err.println("Error: Unknown option: " + opt);
                     return;
@@ -1093,7 +1096,7 @@
                 System.err.println("Consider using a file under /data/local/tmp/");
                 return;
             }
-            profilerInfo = new ProfilerInfo(profileFile, fd, 0, false);
+            profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false);
         }
 
         try {
@@ -1186,12 +1189,12 @@
     private void runSetWatchHeap() throws Exception {
         String proc = nextArgRequired();
         String limit = nextArgRequired();
-        mAm.setDumpHeapDebugLimit(proc, Long.parseLong(limit));
+        mAm.setDumpHeapDebugLimit(proc, 0, Long.parseLong(limit), null);
     }
 
     private void runClearWatchHeap() throws Exception {
         String proc = nextArgRequired();
-        mAm.setDumpHeapDebugLimit(proc, -1);
+        mAm.setDumpHeapDebugLimit(proc, 0, -1, null);
     }
 
     private void runBugReport() throws Exception {
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index c86fd53..c5af992 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -7,6 +7,12 @@
 
 #define LOG_TAG "appproc"
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <utils/Log.h>
@@ -17,11 +23,6 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <private/android_filesystem_config.h>  // for AID_SYSTEM
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/prctl.h>
-
 namespace android {
 
 static void app_usage()
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index 197e36b..84158d3 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -1,3 +1,6 @@
+#include <dirent.h>
+#include <sys/stat.h>
+
 #include "idmap.h"
 
 #include <UniquePtr.h>
@@ -9,8 +12,6 @@
 #include <utils/String16.h>
 #include <utils/String8.h>
 
-#include <dirent.h>
-
 #define NO_OVERLAY_TAG (-1000)
 
 using namespace android;
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 89dd079..b43c462 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -30,6 +30,7 @@
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageInstaller;
 import android.content.pm.IPackageManager;
+import android.content.pm.IPackageMoveObserver;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
@@ -55,12 +56,12 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import libcore.io.IoUtils;
+
 import com.android.internal.content.PackageHelper;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.SizedInputStream;
 
-import libcore.io.IoUtils;
-
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -234,6 +235,10 @@
             return runForceDexOpt();
         }
 
+        if ("move".equals(op)) {
+            return runMove();
+        }
+
         try {
             if (args.length == 1) {
                 if (args[0].equalsIgnoreCase("-l")) {
@@ -1278,6 +1283,51 @@
         }
     }
 
+    class LocalPackageMoveObserver extends IPackageMoveObserver.Stub {
+        boolean finished;
+        int returnCode;
+
+        @Override
+        public void packageMoved(String packageName, int returnCode) throws RemoteException {
+            synchronized (this) {
+                this.finished = true;
+                this.returnCode = returnCode;
+                notifyAll();
+            }
+        }
+    }
+
+    public int runMove() {
+        final String packageName = nextArg();
+        String volumeUuid = nextArg();
+        if ("internal".equals(volumeUuid)) {
+            volumeUuid = null;
+        }
+
+        final LocalPackageMoveObserver obs = new LocalPackageMoveObserver();
+        try {
+            mPm.movePackageAndData(packageName, volumeUuid, obs);
+
+            synchronized (obs) {
+                while (!obs.finished) {
+                    try {
+                        obs.wait();
+                    } catch (InterruptedException e) {
+                    }
+                }
+                if (obs.returnCode == PackageManager.MOVE_SUCCEEDED) {
+                    System.out.println("Success");
+                    return 0;
+                } else {
+                    System.err.println("Failure [" + obs.returnCode + "]");
+                    return 1;
+                }
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
     private int runUninstall() throws RemoteException {
         int flags = 0;
         int userId = UserHandle.USER_ALL;
@@ -1335,7 +1385,8 @@
         }
 
         final LocalIntentReceiver receiver = new LocalIntentReceiver();
-        mInstaller.uninstall(pkg, flags, receiver.getIntentSender(), userId);
+        mInstaller.uninstall(pkg, null /* callerPackageName */, flags,
+                receiver.getIntentSender(), userId);
 
         final Intent result = receiver.getResult();
         final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
@@ -1813,13 +1864,14 @@
         System.err.println("       pm list users");
         System.err.println("       pm path PACKAGE");
         System.err.println("       pm dump PACKAGE");
-        System.err.println("       pm install [-lrtsfd] [-i PACKAGE] [PATH]");
+        System.err.println("       pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]");
         System.err.println("       pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]");
         System.err.println("       pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]");
         System.err.println("       pm install-commit SESSION_ID");
         System.err.println("       pm install-abandon SESSION_ID");
         System.err.println("       pm uninstall [-k] [--user USER_ID] PACKAGE");
         System.err.println("       pm set-installer PACKAGE INSTALLER");
+        System.err.println("       pm move PACKAGE [internal|UUID]");
         System.err.println("       pm clear [--user USER_ID] PACKAGE");
         System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 6957435c..480d171 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -203,6 +203,14 @@
     public static final String KEY_USERDATA = "userdata";
 
     /**
+     * Bundle key used to supply the last time the credentials of the account
+     * were authenticated successfully. Time is specified in milliseconds since
+     * epoch.
+     */
+    public static final String KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH =
+            "lastAuthenticatedTimeMillisEpoch";
+
+    /**
      * Authenticators using 'customTokens' option will also get the UID of the
      * caller
      */
@@ -663,6 +671,31 @@
     }
 
     /**
+     * Informs the system that the account has been authenticated recently. This
+     * recency may be used by other applications to verify the account. This
+     * should be called only when the user has entered correct credentials for
+     * the account.
+     * <p>
+     * It is not safe to call this method from the main thread. As such, call it
+     * from another thread.
+     * <p>
+     * This method requires the caller to hold the permission
+     * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and should be
+     * called from the account's authenticator.
+     *
+     * @param account The {@link Account} to be updated.
+     */
+    public boolean accountAuthenticated(Account account) {
+        if (account == null)
+            throw new IllegalArgumentException("account is null");
+        try {
+            return mService.accountAuthenticated(account);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
      * Rename the specified {@link Account}.  This is equivalent to removing
      * the existing account and adding a new renamed account with the old
      * account's user data.
@@ -1544,15 +1577,20 @@
      *     with these fields if activity or password was supplied and
      *     the account was successfully verified:
      * <ul>
-     * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account created
+     * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account verified
      * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
      * <li> {@link #KEY_BOOLEAN_RESULT} - true to indicate success
      * </ul>
      *
      * If no activity or password was specified, the returned Bundle contains
-     * only {@link #KEY_INTENT} with the {@link Intent} needed to launch the
-     * password prompt.  If an error occurred,
-     * {@link AccountManagerFuture#getResult()} throws:
+     * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
+     * password prompt.
+     * 
+     * <p>Also the returning Bundle may contain {@link
+     * #KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH} indicating the last time the
+     * credential was validated/created.
+     * 
+     * If an error occurred,{@link AccountManagerFuture#getResult()} throws:
      * <ul>
      * <li> {@link AuthenticatorException} if the authenticator failed to respond
      * <li> {@link OperationCanceledException} if the operation was canceled for
@@ -1625,9 +1663,9 @@
      * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
      * </ul>
      *
-     * If no activity was specified, the returned Bundle contains only
+     * If no activity was specified, the returned Bundle contains
      * {@link #KEY_INTENT} with the {@link Intent} needed to launch the
-     * password prompt.  If an error occurred,
+     * password prompt. If an error occurred,
      * {@link AccountManagerFuture#getResult()} throws:
      * <ul>
      * <li> {@link AuthenticatorException} if the authenticator failed to respond
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index aa41161..04b3c88 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -67,6 +67,7 @@
         boolean expectActivityLaunch);
     void confirmCredentialsAsUser(in IAccountManagerResponse response, in Account account,
         in Bundle options, boolean expectActivityLaunch, int userId);
+    boolean accountAuthenticated(in Account account);
     void getAuthTokenLabel(in IAccountManagerResponse response, String accountType,
         String authTokenType);
 
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 021194c..81a01ee 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -947,6 +947,11 @@
                     Keyframe.ofInt(fraction);
         }
 
+        final int resID = a.getResourceId(R.styleable.Keyframe_interpolator, 0);
+        if (resID > 0) {
+            final Interpolator interpolator = AnimationUtils.loadInterpolator(res, theme, resID);
+            keyframe.setInterpolator(interpolator);
+        }
         a.recycle();
 
         return keyframe;
diff --git a/core/java/android/animation/FloatKeyframeSet.java b/core/java/android/animation/FloatKeyframeSet.java
index 56da940..0173079 100644
--- a/core/java/android/animation/FloatKeyframeSet.java
+++ b/core/java/android/animation/FloatKeyframeSet.java
@@ -118,13 +118,14 @@
             FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(i);
             if (fraction < nextKeyframe.getFraction()) {
                 final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
-                if (interpolator != null) {
-                    fraction = interpolator.getInterpolation(fraction);
-                }
                 float intervalFraction = (fraction - prevKeyframe.getFraction()) /
                     (nextKeyframe.getFraction() - prevKeyframe.getFraction());
                 float prevValue = prevKeyframe.getFloatValue();
                 float nextValue = nextKeyframe.getFloatValue();
+                // Apply interpolator on the proportional duration.
+                if (interpolator != null) {
+                    intervalFraction = interpolator.getInterpolation(intervalFraction);
+                }
                 return mEvaluator == null ?
                         prevValue + intervalFraction * (nextValue - prevValue) :
                         ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
diff --git a/core/java/android/animation/IntKeyframeSet.java b/core/java/android/animation/IntKeyframeSet.java
index 12a4bf9..73f9af1 100644
--- a/core/java/android/animation/IntKeyframeSet.java
+++ b/core/java/android/animation/IntKeyframeSet.java
@@ -117,13 +117,14 @@
             IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(i);
             if (fraction < nextKeyframe.getFraction()) {
                 final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
-                if (interpolator != null) {
-                    fraction = interpolator.getInterpolation(fraction);
-                }
                 float intervalFraction = (fraction - prevKeyframe.getFraction()) /
                     (nextKeyframe.getFraction() - prevKeyframe.getFraction());
                 int prevValue = prevKeyframe.getIntValue();
                 int nextValue = nextKeyframe.getIntValue();
+                // Apply interpolator on the proportional duration.
+                if (interpolator != null) {
+                    intervalFraction = interpolator.getInterpolation(intervalFraction);
+                }
                 return mEvaluator == null ?
                         prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
                         ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java
index c80e162..32edd4d 100644
--- a/core/java/android/animation/KeyframeSet.java
+++ b/core/java/android/animation/KeyframeSet.java
@@ -201,7 +201,6 @@
      * @return The animated value.
      */
     public Object getValue(float fraction) {
-
         // Special-case optimization for the common case of only two keyframes
         if (mNumKeyframes == 2) {
             if (mInterpolator != null) {
@@ -238,12 +237,13 @@
             Keyframe nextKeyframe = mKeyframes.get(i);
             if (fraction < nextKeyframe.getFraction()) {
                 final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
-                if (interpolator != null) {
-                    fraction = interpolator.getInterpolation(fraction);
-                }
                 final float prevFraction = prevKeyframe.getFraction();
                 float intervalFraction = (fraction - prevFraction) /
                     (nextKeyframe.getFraction() - prevFraction);
+                // Apply interpolator on the proportional duration.
+                if (interpolator != null) {
+                    intervalFraction = interpolator.getInterpolation(intervalFraction);
+                }
                 return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(),
                         nextKeyframe.getValue());
             }
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 3f71d51..f9333739 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -50,9 +50,11 @@
  * value. Alternatively, you can leave the fractions off and the keyframes will be equally
  * distributed within the total duration. Also, a keyframe with no value will derive its value
  * from the target object when the animator starts, just like animators with only one
- * value specified.</p>
+ * value specified. In addition, an optional interpolator can be specified. The interpolator will
+ * be applied on the interval between the keyframe that the interpolator is set on and the previous
+ * keyframe. When no interpolator is supplied, the default linear interpolator will be used. </p>
  *
- * {@sample development/samples/ApiDemos/res/anim/object_animator_pvh_kf.xml KeyframeResources}
+ * {@sample development/samples/ApiDemos/res/anim/object_animator_pvh_kf_interpolated.xml KeyframeResources}
  *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index d143f8b..8f125d7 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2682,6 +2682,47 @@
     }
 
     /**
+     * Request that the system start watching for the calling process to exceed a pss
+     * size as given here.  Once called, the system will look for any occassions where it
+     * sees the associated process with a larger pss size and, when this happens, automatically
+     * pull a heap dump from it and allow the user to share the data.  Note that this request
+     * continues running even if the process is killed and restarted.  To remove the watch,
+     * use {@link #clearWatchHeapLimit()}.
+     *
+     * <p>This API only work if running on a debuggable (userdebug or eng) build.</p>
+     *
+     * <p>Callers can optionally implement {@link #ACTION_REPORT_HEAP_LIMIT} to directly
+     * handle heap limit reports themselves.</p>
+     *
+     * @param pssSize The size in bytes to set the limit at.
+     */
+    public void setWatchHeapLimit(long pssSize) {
+        try {
+            ActivityManagerNative.getDefault().setDumpHeapDebugLimit(null, 0, pssSize,
+                    mContext.getPackageName());
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Action an app can implement to handle reports from {@link #setWatchHeapLimit(long)}.
+     * If your package has an activity handling this action, it will be launched with the
+     * heap data provided to it the same way as {@link Intent#ACTION_SEND}.  Note that to
+     * match the activty must support this action and a MIME type of "*&#47;*".
+     */
+    public static final String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT";
+
+    /**
+     * Clear a heap watch limit previously set by {@link #setWatchHeapLimit(long)}.
+     */
+    public void clearWatchHeapLimit() {
+        try {
+            ActivityManagerNative.getDefault().setDumpHeapDebugLimit(null, 0, 0, null);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * @hide
      */
     public void startLockTaskMode(int taskId) {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1484af8..f63d13c 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2427,8 +2427,10 @@
         case SET_DUMP_HEAP_DEBUG_LIMIT_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             String procName = data.readString();
+            int uid = data.readInt();
             long maxMemSize = data.readLong();
-            setDumpHeapDebugLimit(procName, maxMemSize);
+            String reportPackage = data.readString();
+            setDumpHeapDebugLimit(procName, uid, maxMemSize, reportPackage);
             reply.writeNoException();
             return true;
         }
@@ -2450,6 +2452,15 @@
             reply.writeNoException();
             return true;
         }
+
+        case UPDATE_LOCK_TASK_PACKAGES_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int userId = data.readInt();
+            String[] packages = data.readStringArray();
+            updateLockTaskPackages(userId, packages);
+            reply.writeNoException();
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -5644,12 +5655,15 @@
     }
 
     @Override
-    public void setDumpHeapDebugLimit(String processName, long maxMemSize) throws RemoteException {
+    public void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize,
+            String reportPackage) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeString(processName);
+        data.writeInt(uid);
         data.writeLong(maxMemSize);
+        data.writeString(reportPackage);
         mRemote.transact(SET_DUMP_HEAP_DEBUG_LIMIT_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
@@ -5682,5 +5696,18 @@
         reply.recycle();
     }
 
+    @Override
+    public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(userId);
+        data.writeStringArray(packages);
+        mRemote.transact(UPDATE_LOCK_TASK_PACKAGES_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4880db1..81b1583 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -254,18 +254,21 @@
         }
     }
 
+    static final class AcquiringProviderRecord {
+        IActivityManager.ContentProviderHolder holder;
+        boolean acquiring = true;
+        int requests = 1;
+    }
+
     // The lock of mProviderMap protects the following variables.
-    final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
-        = new ArrayMap<ProviderKey, ProviderClientRecord>();
-    final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap
-        = new ArrayMap<IBinder, ProviderRefCount>();
-    final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders
-        = new ArrayMap<IBinder, ProviderClientRecord>();
-    final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName
-            = new ArrayMap<ComponentName, ProviderClientRecord>();
+    final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap = new ArrayMap<>();
+    final ArrayMap<ProviderKey, AcquiringProviderRecord> mAcquiringProviderMap = new ArrayMap<>();
+    final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap = new ArrayMap<>();
+    final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders = new ArrayMap<>();
+    final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName = new ArrayMap<>();
 
     final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
-        = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
+            = new ArrayMap<>();
 
     final GcIdler mGcIdler = new GcIdler();
     boolean mGcIdlerScheduled = false;
@@ -345,7 +348,7 @@
         }
     }
 
-    final class ProviderClientRecord {
+    static final class ProviderClientRecord {
         final String[] mNames;
         final IContentProvider mProvider;
         final ContentProvider mLocalProvider;
@@ -4693,22 +4696,57 @@
 
     public final IContentProvider acquireProvider(
             Context c, String auth, int userId, boolean stable) {
-        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
+        final ProviderKey key = new ProviderKey(auth, userId);
+        final IContentProvider provider = acquireExistingProvider(c, key, stable);
         if (provider != null) {
             return provider;
         }
+        AcquiringProviderRecord r;
+        boolean first = false;
+        synchronized (mAcquiringProviderMap) {
+            r = mAcquiringProviderMap.get(key);
+            if (r == null) {
+                r = new AcquiringProviderRecord();
+                mAcquiringProviderMap.put(key, r);
+                first = true;
+            } else {
+                r.requests++;
+            }
+        }
 
-        // There is a possible race here.  Another thread may try to acquire
-        // the same provider at the same time.  When this happens, we want to ensure
-        // that the first one wins.
-        // Note that we cannot hold the lock while acquiring and installing the
-        // provider since it might take a long time to run and it could also potentially
-        // be re-entrant in the case where the provider is in the same process.
         IActivityManager.ContentProviderHolder holder = null;
-        try {
-            holder = ActivityManagerNative.getDefault().getContentProvider(
-                    getApplicationThread(), auth, userId, stable);
-        } catch (RemoteException ex) {
+        if (first) {
+            // Multiple threads may try to acquire the same provider at the same time.
+            // When this happens, we only let the first one really gets provider.
+            // Other threads just wait for its result.
+            // Note that we cannot hold the lock while acquiring and installing the
+            // provider since it might take a long time to run and it could also potentially
+            // be re-entrant in the case where the provider is in the same process.
+            try {
+                holder = ActivityManagerNative.getDefault().getContentProvider(
+                        getApplicationThread(), auth, userId, stable);
+            } catch (RemoteException ex) {
+            }
+            synchronized (r) {
+                r.holder = holder;
+                r.acquiring = false;
+                r.notifyAll();
+            }
+        } else {
+            synchronized (r) {
+                while (r.acquiring) {
+                    try {
+                        r.wait();
+                    } catch (InterruptedException e) {
+                    }
+                }
+                holder = r.holder;
+            }
+        }
+        synchronized (mAcquiringProviderMap) {
+            if (--r.requests == 0) {
+                mAcquiringProviderMap.remove(key);
+            }
         }
         if (holder == null) {
             Slog.e(TAG, "Failed to find provider info for " + auth);
@@ -4792,8 +4830,12 @@
 
     public final IContentProvider acquireExistingProvider(
             Context c, String auth, int userId, boolean stable) {
+        return acquireExistingProvider(c, new ProviderKey(auth, userId), stable);
+    }
+
+    final IContentProvider acquireExistingProvider(
+            Context c, ProviderKey key, boolean stable) {
         synchronized (mProviderMap) {
-            final ProviderKey key = new ProviderKey(auth, userId);
             final ProviderClientRecord pr = mProviderMap.get(key);
             if (pr == null) {
                 return null;
@@ -4804,7 +4846,7 @@
             if (!jBinder.isBinderAlive()) {
                 // The hosting process of the provider has died; we can't
                 // use this one.
-                Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
+                Log.i(TAG, "Acquiring provider " + key.authority + " for user " +  key.userId
                         + ": existing object's process dead");
                 handleUnstableProviderDiedLocked(jBinder, true);
                 return null;
@@ -5126,18 +5168,12 @@
                     if (DEBUG_PROVIDER) {
                         Slog.v(TAG, "installProvider: lost the race, updating ref count");
                     }
-                    // We need to transfer our new reference to the existing
-                    // ref count, releasing the old one...  but only if
-                    // release is needed (that is, it is not running in the
-                    // system process).
+                    // The provider has already been installed, so we need
+                    // to increase reference count to the existing one, but
+                    // only if release is needed (that is, it is not running
+                    // in the system process or local to the process).
                     if (!noReleaseNeeded) {
                         incProviderRefLocked(prc, stable);
-                        try {
-                            ActivityManagerNative.getDefault().removeContentProvider(
-                                    holder.connection, stable);
-                        } catch (RemoteException e) {
-                            //do nothing content provider object is dead any way
-                        }
                     }
                 } else {
                     ProviderClientRecord client = installProviderAuthoritiesLocked(
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 2cb27b0..eafcdb2 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -350,10 +350,15 @@
             if (activityView != null) {
                 final ActivityViewCallback callback = activityView.mActivityViewCallback;
                 if (callback != null) {
+                    final WeakReference<ActivityViewCallback> callbackRef =
+                            new WeakReference<>(callback);
                     activityView.post(new Runnable() {
                         @Override
                         public void run() {
-                            callback.onAllActivitiesComplete(activityView);
+                            ActivityViewCallback callback = callbackRef.get();
+                            if (callback != null) {
+                                callback.onAllActivitiesComplete(activityView);
+                            }
                         }
                     });
                 }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 4bd2332..381c20c 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -208,8 +208,12 @@
     public static final int OP_ACTIVATE_VPN = 47;
     /** @hide Access the WallpaperManagerAPI to write wallpapers. */
     public static final int OP_WRITE_WALLPAPER = 48;
+    /** @hide Received the assist structure from an app. */
+    public static final int OP_ASSIST_STRUCTURE = 49;
+    /** @hide Received a screenshot from assist. */
+    public static final int OP_ASSIST_SCREENSHOT = 50;
     /** @hide */
-    public static final int _NUM_OP = 49;
+    public static final int _NUM_OP = 51;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION =
@@ -288,6 +292,8 @@
             OP_PROJECT_MEDIA,
             OP_ACTIVATE_VPN,
             OP_WRITE_WALLPAPER,
+            OP_ASSIST_STRUCTURE,
+            OP_ASSIST_SCREENSHOT,
     };
 
     /**
@@ -344,6 +350,8 @@
             null,
             OPSTR_ACTIVATE_VPN,
             null,
+            null,
+            null,
     };
 
     /**
@@ -400,6 +408,8 @@
             "PROJECT_MEDIA",
             "ACTIVATE_VPN",
             "WRITE_WALLPAPER",
+            "ASSIST_STRUCTURE",
+            "ASSIST_SCREENSHOT"
     };
 
     /**
@@ -456,6 +466,8 @@
             null, // no permission for projecting media
             null, // no permission for activating vpn
             null, // no permission for supporting wallpaper
+            null, // no permission for receiving assist structure
+            null, // no permission for receiving assist screenshot
     };
 
     /**
@@ -513,6 +525,8 @@
             null, //PROJECT_MEDIA
             UserManager.DISALLOW_CONFIG_VPN, // ACTIVATE_VPN
             UserManager.DISALLOW_WALLPAPER, // WRITE_WALLPAPER
+            null, // ASSIST_STRUCTURE
+            null, // ASSIST_SCREENSHOT
     };
 
     /**
@@ -569,6 +583,8 @@
             false, //PROJECT_MEDIA
             false, //ACTIVATE_VPN
             false, //WALLPAPER
+            false, //ASSIST_STRUCTURE
+            false, //ASSIST_SCREENSHOT
     };
 
     /**
@@ -624,6 +640,8 @@
             AppOpsManager.MODE_IGNORED, // OP_PROJECT_MEDIA
             AppOpsManager.MODE_IGNORED, // OP_ACTIVATE_VPN
             AppOpsManager.MODE_ALLOWED,
+            AppOpsManager.MODE_ALLOWED,
+            AppOpsManager.MODE_ALLOWED,
     };
 
     /**
@@ -683,6 +701,8 @@
             false,
             false,
             false,
+            false,
+            false,
     };
 
     private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 6d74905..10dcd85 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -36,6 +36,7 @@
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
+import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.KeySet;
 import android.content.pm.ManifestDigest;
 import android.content.pm.PackageInfo;
@@ -61,19 +62,19 @@
 import android.net.Uri;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.Display;
-import android.os.SystemProperties;
+
+import dalvik.system.VMRuntime;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.UserIcons;
 
-import dalvik.system.VMRuntime;
-
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
@@ -1309,6 +1310,45 @@
     }
 
     @Override
+    public void verifyIntentFilter(int id, int verificationCode, List<String> outFailedDomains) {
+        try {
+            mPM.verifyIntentFilter(id, verificationCode, outFailedDomains);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public int getIntentVerificationStatus(String packageName, int userId) {
+        try {
+            return mPM.getIntentVerificationStatus(packageName, userId);
+        } catch (RemoteException e) {
+            // Should never happen!
+            return PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+        }
+    }
+
+    @Override
+    public boolean updateIntentVerificationStatus(String packageName, int status, int userId) {
+        try {
+            return mPM.updateIntentVerificationStatus(packageName, status, userId);
+        } catch (RemoteException e) {
+            // Should never happen!
+            return false;
+        }
+    }
+
+    @Override
+    public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
+        try {
+            return mPM.getIntentFilterVerifications(packageName);
+        } catch (RemoteException e) {
+            // Should never happen!
+            return null;
+        }
+    }
+
+    @Override
     public void setInstallerPackageName(String targetPackage,
             String installerPackageName) {
         try {
@@ -1323,7 +1363,17 @@
         try {
             mPM.movePackage(packageName, observer, flags);
         } catch (RemoteException e) {
-            // Should never happen!
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    @Override
+    public void movePackageAndData(String packageName, String volumeUuid,
+            IPackageMoveObserver observer) {
+        try {
+            mPM.movePackageAndData(packageName, volumeUuid, observer);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
         }
     }
 
diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java
index c435ccb..1e159a3 100644
--- a/core/java/android/app/AssistStructure.java
+++ b/core/java/android/app/AssistStructure.java
@@ -17,24 +17,25 @@
 package android.app;
 
 import android.content.ComponentName;
-import android.content.res.Resources;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.Typeface;
+import android.os.Binder;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PooledStringReader;
 import android.os.PooledStringWriter;
+import android.os.RemoteException;
+import android.os.SystemClock;
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewAssistStructure;
-import android.view.ViewGroup;
 import android.view.ViewRootImpl;
 import android.view.WindowManagerGlobal;
-import android.widget.Checkable;
 
 import java.util.ArrayList;
 
@@ -52,111 +53,49 @@
      */
     public static final String ASSIST_KEY = "android:assist_structure";
 
-    final ComponentName mActivityComponent;
+    boolean mHaveData;
+
+    ComponentName mActivityComponent;
 
     final ArrayList<WindowNode> mWindowNodes = new ArrayList<>();
 
-    ViewAssistStructureImpl mTmpViewAssistStructureImpl = new ViewAssistStructureImpl();
-    Bundle mTmpExtras = new Bundle();
+    final ArrayList<ViewNodeBuilder> mPendingAsyncChildren = new ArrayList<>();
 
-    final static class ViewAssistStructureImpl extends ViewAssistStructure {
-        CharSequence mText;
-        int mTextSelectionStart = -1;
-        int mTextSelectionEnd = -1;
-        int mTextColor = ViewNode.TEXT_COLOR_UNDEFINED;
-        int mTextBackgroundColor = ViewNode.TEXT_COLOR_UNDEFINED;
-        float mTextSize = 0;
-        int mTextStyle = 0;
-        CharSequence mHint;
+    SendChannel mSendChannel;
+    IBinder mReceiveChannel;
 
-        @Override
-        public void setText(CharSequence text) {
-            mText = text;
-            mTextSelectionStart = mTextSelectionEnd = -1;
-        }
+    Rect mTmpRect = new Rect();
 
-        @Override
-        public void setText(CharSequence text, int selectionStart, int selectionEnd) {
-            mText = text;
-            mTextSelectionStart = selectionStart;
-            mTextSelectionEnd = selectionEnd;
-        }
+    static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1;
+    static final String DESCRIPTOR = "android.app.AssistStructure";
 
-        @Override
-        public void setTextPaint(TextPaint paint) {
-            mTextColor = paint.getColor();
-            mTextBackgroundColor = paint.bgColor;
-            mTextSize = paint.getTextSize();
-            mTextStyle = 0;
-            Typeface tf = paint.getTypeface();
-            if (tf != null) {
-                if (tf.isBold()) {
-                    mTextStyle |= ViewNode.TEXT_STYLE_BOLD;
-                }
-                if (tf.isItalic()) {
-                    mTextStyle |= ViewNode.TEXT_STYLE_ITALIC;
-                }
+    final class SendChannel extends Binder {
+        @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+                throws RemoteException {
+            if (code == TRANSACTION_XFER) {
+                data.enforceInterface(DESCRIPTOR);
+                writeContentToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+                return true;
+            } else {
+                return super.onTransact(code, data, reply, flags);
             }
-            int pflags = paint.getFlags();
-            if ((pflags& Paint.FAKE_BOLD_TEXT_FLAG) != 0) {
-                mTextStyle |= ViewNode.TEXT_STYLE_BOLD;
-            }
-            if ((pflags& Paint.UNDERLINE_TEXT_FLAG) != 0) {
-                mTextStyle |= ViewNode.TEXT_STYLE_UNDERLINE;
-            }
-            if ((pflags& Paint.STRIKE_THRU_TEXT_FLAG) != 0) {
-                mTextStyle |= ViewNode.TEXT_STYLE_STRIKE_THRU;
-            }
-        }
-
-        @Override
-        public void setHint(CharSequence hint) {
-            mHint = hint;
-        }
-
-        @Override
-        public CharSequence getText() {
-            return mText;
-        }
-
-        @Override
-        public int getTextSelectionStart() {
-            return mTextSelectionStart;
-        }
-
-        @Override
-        public int getTextSelectionEnd() {
-            return mTextSelectionEnd;
-        }
-
-        @Override
-        public CharSequence getHint() {
-            return mHint;
         }
     }
 
-    final static class ViewNodeTextImpl {
-        final CharSequence mText;
-        final int mTextSelectionStart;
-        final int mTextSelectionEnd;
+    final static class ViewNodeText {
+        CharSequence mText;
+        int mTextSelectionStart;
+        int mTextSelectionEnd;
         int mTextColor;
         int mTextBackgroundColor;
         float mTextSize;
         int mTextStyle;
-        final String mHint;
+        String mHint;
 
-        ViewNodeTextImpl(ViewAssistStructureImpl data) {
-            mText = data.mText;
-            mTextSelectionStart = data.mTextSelectionStart;
-            mTextSelectionEnd = data.mTextSelectionEnd;
-            mTextColor = data.mTextColor;
-            mTextBackgroundColor = data.mTextBackgroundColor;
-            mTextSize = data.mTextSize;
-            mTextStyle = data.mTextStyle;
-            mHint = data.mHint != null ? data.mHint.toString() : null;
+        ViewNodeText() {
         }
 
-        ViewNodeTextImpl(Parcel in) {
+        ViewNodeText(Parcel in) {
             mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
             mTextSelectionStart = in.readInt();
             mTextSelectionEnd = in.readInt();
@@ -199,7 +138,9 @@
             mWidth = rect.width();
             mHeight = rect.height();
             mTitle = root.getTitle();
-            mRoot = new ViewNode(assist, view);
+            mRoot = new ViewNode();
+            ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
+            view.dispatchProvideAssistStructure(builder);
         }
 
         WindowNode(Parcel in, PooledStringReader preader) {
@@ -260,16 +201,16 @@
         public static final int TEXT_STYLE_UNDERLINE = 1<<2;
         public static final int TEXT_STYLE_STRIKE_THRU = 1<<3;
 
-        final int mId;
-        final String mIdPackage;
-        final String mIdType;
-        final String mIdEntry;
-        final int mX;
-        final int mY;
-        final int mScrollX;
-        final int mScrollY;
-        final int mWidth;
-        final int mHeight;
+        int mId;
+        String mIdPackage;
+        String mIdType;
+        String mIdEntry;
+        int mX;
+        int mY;
+        int mScrollX;
+        int mScrollY;
+        int mWidth;
+        int mHeight;
 
         static final int FLAGS_DISABLED = 0x00000001;
         static final int FLAGS_VISIBILITY_MASK = View.VISIBLE|View.INVISIBLE|View.GONE;
@@ -283,104 +224,17 @@
         static final int FLAGS_CLICKABLE = 0x00004000;
         static final int FLAGS_LONG_CLICKABLE = 0x00200000;
 
-        final int mFlags;
+        int mFlags;
 
-        final String mClassName;
-        final CharSequence mContentDescription;
+        String mClassName;
+        CharSequence mContentDescription;
 
-        final ViewNodeTextImpl mText;
-        final Bundle mExtras;
+        ViewNodeText mText;
+        Bundle mExtras;
 
-        final ViewNode[] mChildren;
+        ViewNode[] mChildren;
 
-        ViewNode(AssistStructure assistStructure, View view) {
-            mId = view.getId();
-            if (mId > 0 && (mId&0xff000000) != 0 && (mId&0x00ff0000) != 0
-                    && (mId&0x0000ffff) != 0) {
-                String pkg, type, entry;
-                try {
-                    Resources res = view.getResources();
-                    entry = res.getResourceEntryName(mId);
-                    type = res.getResourceTypeName(mId);
-                    pkg = res.getResourcePackageName(mId);
-                } catch (Resources.NotFoundException e) {
-                    entry = type = pkg = null;
-                }
-                mIdPackage = pkg;
-                mIdType = type;
-                mIdEntry = entry;
-            } else {
-                mIdPackage = mIdType = mIdEntry = null;
-            }
-            mX = view.getLeft();
-            mY = view.getTop();
-            mScrollX = view.getScrollX();
-            mScrollY = view.getScrollY();
-            mWidth = view.getWidth();
-            mHeight = view.getHeight();
-            int flags = view.getVisibility();
-            if (!view.isEnabled()) {
-                flags |= FLAGS_DISABLED;
-            }
-            if (!view.isClickable()) {
-                flags |= FLAGS_CLICKABLE;
-            }
-            if (!view.isFocusable()) {
-                flags |= FLAGS_FOCUSABLE;
-            }
-            if (!view.isFocused()) {
-                flags |= FLAGS_FOCUSED;
-            }
-            if (!view.isAccessibilityFocused()) {
-                flags |= FLAGS_ACCESSIBILITY_FOCUSED;
-            }
-            if (!view.isSelected()) {
-                flags |= FLAGS_SELECTED;
-            }
-            if (!view.isActivated()) {
-                flags |= FLAGS_ACTIVATED;
-            }
-            if (!view.isLongClickable()) {
-                flags |= FLAGS_LONG_CLICKABLE;
-            }
-            if (view instanceof Checkable) {
-                flags |= FLAGS_CHECKABLE;
-                if (((Checkable)view).isChecked()) {
-                    flags |= FLAGS_CHECKED;
-                }
-            }
-            mFlags = flags;
-            mClassName = view.getAccessibilityClassName().toString();
-            mContentDescription = view.getContentDescription();
-            final ViewAssistStructureImpl viewData = assistStructure.mTmpViewAssistStructureImpl;
-            final Bundle extras = assistStructure.mTmpExtras;
-            view.onProvideAssistStructure(viewData, extras);
-            if (viewData.mText != null || viewData.mHint != null) {
-                mText = new ViewNodeTextImpl(viewData);
-                assistStructure.mTmpViewAssistStructureImpl = new ViewAssistStructureImpl();
-            } else {
-                mText = null;
-            }
-            if (!extras.isEmpty()) {
-                mExtras = extras;
-                assistStructure.mTmpExtras = new Bundle();
-            } else {
-                mExtras = null;
-            }
-            if (view instanceof ViewGroup) {
-                ViewGroup vg = (ViewGroup)view;
-                final int NCHILDREN = vg.getChildCount();
-                if (NCHILDREN > 0) {
-                    mChildren = new ViewNode[NCHILDREN];
-                    for (int i=0; i<NCHILDREN; i++) {
-                        mChildren[i] = new ViewNode(assistStructure, vg.getChildAt(i));
-                    }
-                } else {
-                    mChildren = null;
-                }
-            } else {
-                mChildren = null;
-            }
+        ViewNode() {
         }
 
         ViewNode(Parcel in, PooledStringReader preader) {
@@ -406,7 +260,7 @@
             mClassName = preader.readString();
             mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
             if (in.readInt() != 0) {
-                mText = new ViewNodeTextImpl(in);
+                mText = new ViewNodeText(in);
             } else {
                 mText = null;
             }
@@ -595,7 +449,250 @@
         }
     }
 
+    static class ViewNodeBuilder extends ViewAssistStructure {
+        final AssistStructure mAssist;
+        final ViewNode mNode;
+        final boolean mAsync;
+
+        ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) {
+            mAssist = assist;
+            mNode = node;
+            mAsync = async;
+        }
+
+        @Override
+        public void setId(int id, String packageName, String typeName, String entryName) {
+            mNode.mId = id;
+            mNode.mIdPackage = packageName;
+            mNode.mIdType = typeName;
+            mNode.mIdEntry = entryName;
+        }
+
+        @Override
+        public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
+            mNode.mX = left;
+            mNode.mY = top;
+            mNode.mScrollX = scrollX;
+            mNode.mScrollY = scrollY;
+            mNode.mWidth = width;
+            mNode.mHeight = height;
+        }
+
+        @Override
+        public void setVisibility(int visibility) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_VISIBILITY_MASK) | visibility;
+        }
+
+        @Override
+        public void setEnabled(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_DISABLED)
+                    | (state ? 0 : ViewNode.FLAGS_DISABLED);
+        }
+
+        @Override
+        public void setClickable(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CLICKABLE)
+                    | (state ? ViewNode.FLAGS_CLICKABLE : 0);
+        }
+
+        @Override
+        public void setLongClickable(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_LONG_CLICKABLE)
+                    | (state ? ViewNode.FLAGS_LONG_CLICKABLE : 0);
+        }
+
+        @Override
+        public void setFocusable(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSABLE)
+                    | (state ? ViewNode.FLAGS_FOCUSABLE : 0);
+        }
+
+        @Override
+        public void setFocused(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSED)
+                    | (state ? ViewNode.FLAGS_FOCUSED : 0);
+        }
+
+        @Override
+        public void setAccessibilityFocused(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACCESSIBILITY_FOCUSED)
+                    | (state ? ViewNode.FLAGS_ACCESSIBILITY_FOCUSED : 0);
+        }
+
+        @Override
+        public void setCheckable(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKABLE)
+                    | (state ? ViewNode.FLAGS_CHECKABLE : 0);
+        }
+
+        @Override
+        public void setChecked(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKED)
+                    | (state ? ViewNode.FLAGS_CHECKED : 0);
+        }
+
+        @Override
+        public void setSelected(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_SELECTED)
+                    | (state ? ViewNode.FLAGS_SELECTED : 0);
+        }
+
+        @Override
+        public void setActivated(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACTIVATED)
+                    | (state ? ViewNode.FLAGS_ACTIVATED : 0);
+        }
+
+        @Override
+        public void setClassName(String className) {
+            mNode.mClassName = className;
+        }
+
+        @Override
+        public void setContentDescription(CharSequence contentDescription) {
+            mNode.mContentDescription = contentDescription;
+        }
+
+        private final ViewNodeText getNodeText() {
+            if (mNode.mText != null) {
+                return mNode.mText;
+            }
+            mNode.mText = new ViewNodeText();
+            return mNode.mText;
+        }
+
+        @Override
+        public void setText(CharSequence text) {
+            ViewNodeText t = getNodeText();
+            t.mText = text;
+            t.mTextSelectionStart = t.mTextSelectionEnd = -1;
+        }
+
+        @Override
+        public void setText(CharSequence text, int selectionStart, int selectionEnd) {
+            ViewNodeText t = getNodeText();
+            t.mText = text;
+            t.mTextSelectionStart = selectionStart;
+            t.mTextSelectionEnd = selectionEnd;
+        }
+
+        @Override
+        public void setTextPaint(TextPaint paint) {
+            ViewNodeText t = getNodeText();
+            t.mTextColor = paint.getColor();
+            t.mTextBackgroundColor = paint.bgColor;
+            t.mTextSize = paint.getTextSize();
+            t.mTextStyle = 0;
+            Typeface tf = paint.getTypeface();
+            if (tf != null) {
+                if (tf.isBold()) {
+                    t.mTextStyle |= ViewNode.TEXT_STYLE_BOLD;
+                }
+                if (tf.isItalic()) {
+                    t.mTextStyle |= ViewNode.TEXT_STYLE_ITALIC;
+                }
+            }
+            int pflags = paint.getFlags();
+            if ((pflags& Paint.FAKE_BOLD_TEXT_FLAG) != 0) {
+                t.mTextStyle |= ViewNode.TEXT_STYLE_BOLD;
+            }
+            if ((pflags& Paint.UNDERLINE_TEXT_FLAG) != 0) {
+                t.mTextStyle |= ViewNode.TEXT_STYLE_UNDERLINE;
+            }
+            if ((pflags& Paint.STRIKE_THRU_TEXT_FLAG) != 0) {
+                t.mTextStyle |= ViewNode.TEXT_STYLE_STRIKE_THRU;
+            }
+        }
+
+        @Override
+        public void setHint(CharSequence hint) {
+            getNodeText().mHint = hint != null ? hint.toString() : null;
+        }
+
+        @Override
+        public CharSequence getText() {
+            return mNode.mText != null ? mNode.mText.mText : null;
+        }
+
+        @Override
+        public int getTextSelectionStart() {
+            return mNode.mText != null ? mNode.mText.mTextSelectionStart : -1;
+        }
+
+        @Override
+        public int getTextSelectionEnd() {
+            return mNode.mText != null ? mNode.mText.mTextSelectionEnd : -1;
+        }
+
+        @Override
+        public CharSequence getHint() {
+            return mNode.mText != null ? mNode.mText.mHint : null;
+        }
+
+        @Override
+        public Bundle editExtras() {
+            if (mNode.mExtras != null) {
+                return mNode.mExtras;
+            }
+            mNode.mExtras = new Bundle();
+            return mNode.mExtras;
+        }
+
+        @Override
+        public void clearExtras() {
+            mNode.mExtras = null;
+        }
+
+        @Override
+        public void setChildCount(int num) {
+            mNode.mChildren = new ViewNode[num];
+        }
+
+        @Override
+        public int getChildCount() {
+            return mNode.mChildren != null ? mNode.mChildren.length : 0;
+        }
+
+        @Override
+        public ViewAssistStructure newChild(int index) {
+            ViewNode node = new ViewNode();
+            mNode.mChildren[index] = node;
+            return new ViewNodeBuilder(mAssist, node, false);
+        }
+
+        @Override
+        public ViewAssistStructure asyncNewChild(int index) {
+            synchronized (mAssist) {
+                ViewNode node = new ViewNode();
+                mNode.mChildren[index] = node;
+                ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true);
+                mAssist.mPendingAsyncChildren.add(builder);
+                return builder;
+            }
+        }
+
+        @Override
+        public void asyncCommit() {
+            synchronized (mAssist) {
+                if (!mAsync) {
+                    throw new IllegalStateException("Child " + this
+                            + " was not created with ViewAssistStructure.asyncNewChild");
+                }
+                if (!mAssist.mPendingAsyncChildren.remove(this)) {
+                    throw new IllegalStateException("Child " + this + " already committed");
+                }
+                mAssist.notifyAll();
+            }
+        }
+
+        @Override
+        public Rect getTempRect() {
+            return mAssist.mTmpRect;
+        }
+    }
+
     AssistStructure(Activity activity) {
+        mHaveData = true;
         mActivityComponent = activity.getComponentName();
         ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
                 activity.getActivityToken());
@@ -606,13 +703,7 @@
     }
 
     AssistStructure(Parcel in) {
-        PooledStringReader preader = new PooledStringReader(in);
-        mActivityComponent = ComponentName.readFromParcel(in);
-        final int N = in.readInt();
-        for (int i=0; i<N; i++) {
-            mWindowNodes.add(new WindowNode(in, preader));
-        }
-        //dump();
+        mReceiveChannel = in.readStrongBinder();
     }
 
     /** @hide */
@@ -689,6 +780,7 @@
     }
 
     public ComponentName getActivityComponent() {
+        ensureData();
         return mActivityComponent;
     }
 
@@ -696,6 +788,7 @@
      * Return the number of window contents that have been collected in this assist data.
      */
     public int getWindowNodeCount() {
+        ensureData();
         return mWindowNodes.size();
     }
 
@@ -704,6 +797,7 @@
      * @param index Which window to retrieve, may be 0 to {@link #getWindowNodeCount()}-1.
      */
     public WindowNode getWindowNodeAt(int index) {
+        ensureData();
         return mWindowNodes.get(index);
     }
 
@@ -711,11 +805,47 @@
         return 0;
     }
 
-    public void writeToParcel(Parcel out, int flags) {
+    /** @hide */
+    public void ensureData() {
+        if (mHaveData) {
+            return;
+        }
+        mHaveData = true;
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(DESCRIPTOR);
+        try {
+            mReceiveChannel.transact(TRANSACTION_XFER, data, reply, 0);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failure reading AssistStructure data", e);
+            return;
+        }
+        readContentFromParcel(reply);
+        data.recycle();
+        reply.recycle();
+    }
+
+    void writeContentToParcel(Parcel out, int flags) {
+        // First make sure all content has been created.
+        boolean skipStructure = false;
+        synchronized (this) {
+            long endTime = SystemClock.uptimeMillis() + 5000;
+            long now;
+            while (mPendingAsyncChildren.size() > 0 && (now=SystemClock.uptimeMillis()) < endTime) {
+                try {
+                    wait(endTime-now);
+                } catch (InterruptedException e) {
+                }
+            }
+            if (mPendingAsyncChildren.size() > 0) {
+                // We waited too long, assume none of the assist structure is valid.
+                skipStructure = true;
+            }
+        }
         int start = out.dataPosition();
         PooledStringWriter pwriter = new PooledStringWriter(out);
         ComponentName.writeToParcel(mActivityComponent, out);
-        final int N = mWindowNodes.size();
+        final int N = skipStructure ? 0 : mWindowNodes.size();
         out.writeInt(N);
         for (int i=0; i<N; i++) {
             mWindowNodes.get(i).writeToParcel(out, pwriter);
@@ -724,6 +854,30 @@
         Log.i(TAG, "Flattened assist data: " + (out.dataPosition() - start) + " bytes");
     }
 
+    void readContentFromParcel(Parcel in) {
+        PooledStringReader preader = new PooledStringReader(in);
+        mActivityComponent = ComponentName.readFromParcel(in);
+        final int N = in.readInt();
+        for (int i=0; i<N; i++) {
+            mWindowNodes.add(new WindowNode(in, preader));
+        }
+        //dump();
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        if (mHaveData) {
+            // This object holds its data.  We want to write a send channel that the
+            // other side can use to retrieve that data.
+            if (mSendChannel == null) {
+                mSendChannel = new SendChannel();
+            }
+            out.writeStrongBinder(mSendChannel);
+        } else {
+            // This object doesn't hold its data, so just propagate along its receive channel.
+            out.writeStrongBinder(mReceiveChannel);
+        }
+    }
+
     public static final Parcelable.Creator<AssistStructure> CREATOR
             = new Parcelable.Creator<AssistStructure>() {
         public AssistStructure createFromParcel(Parcel in) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index d794aa3..4a1d6ff 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -482,11 +482,13 @@
     public void systemBackupRestored() throws RemoteException;
     public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException;
 
-    public void setDumpHeapDebugLimit(String processName, long maxMemSize) throws RemoteException;
+    public void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize,
+            String reportPackage) throws RemoteException;
     public void dumpHeapFinished(String path) throws RemoteException;
 
     public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake)
             throws RemoteException;
+    public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException;
 
     /*
      * Private non-Binder interfaces
@@ -822,4 +824,5 @@
     int SET_DUMP_HEAP_DEBUG_LIMIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+287;
     int DUMP_HEAP_FINISHED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+288;
     int SET_VOICE_KEEP_AWAKE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+289;
+    int UPDATE_LOCK_TASK_PACKAGES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+290;
 }
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 451af99..fe8e228 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -100,6 +100,11 @@
     void doFullBackup(in ParcelFileDescriptor data, int token, IBackupManager callbackBinder);
 
     /**
+     * Estimate how much data a full backup will deliver
+     */
+    void doMeasureFullBackup(int token, IBackupManager callbackBinder);
+
+    /**
      * Restore a single "file" to the application.  The file was typically obtained from
      * a full-backup dataset.  The agent reads 'size' bytes of file content
      * from the provided file descriptor.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b31ce04..e7f8f6d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -646,6 +646,11 @@
     public static final String CATEGORY_STATUS = "status";
 
     /**
+     * Notification category: user-scheduled reminder.
+     */
+    public static final String CATEGORY_REMINDER = "reminder";
+
+    /**
      * One of the predefined notification categories (see the <code>CATEGORY_*</code> constants)
      * that best describes this Notification.  May be used by the system for ranking and filtering.
      */
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index fd7bae7..b3aa6be 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -27,6 +27,7 @@
 import android.app.job.JobScheduler;
 import android.app.trust.TrustManager;
 import android.app.usage.IUsageStatsManager;
+import android.app.usage.NetworkStatsManager;
 import android.app.usage.UsageStatsManager;
 import android.appwidget.AppWidgetManager;
 import android.bluetooth.BluetoothManager;
@@ -98,8 +99,8 @@
 import android.os.storage.StorageManager;
 import android.print.IPrintManager;
 import android.print.PrintManager;
-import android.service.fingerprint.FingerprintManager;
-import android.service.fingerprint.IFingerprintService;
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.IFingerprintService;
 import android.service.persistentdata.IPersistentDataBlockService;
 import android.service.persistentdata.PersistentDataBlockManager;
 import android.telecom.TelecomManager;
@@ -401,13 +402,7 @@
                 new CachedServiceFetcher<StorageManager>() {
             @Override
             public StorageManager createService(ContextImpl ctx) {
-                try {
-                    return new StorageManager(
-                            ctx.getContentResolver(), ctx.mMainThread.getHandler().getLooper());
-                } catch (RemoteException rex) {
-                    Log.e(TAG, "Failed to create StorageManager", rex);
-                    return null;
-                }
+                return new StorageManager(ctx, ctx.mMainThread.getHandler().getLooper());
             }});
 
         registerService(Context.TELEPHONY_SERVICE, TelephonyManager.class,
@@ -639,6 +634,13 @@
                 return new UsageStatsManager(ctx.getOuterContext(), service);
             }});
 
+        registerService(Context.NETWORK_STATS_SERVICE, NetworkStatsManager.class,
+                new CachedServiceFetcher<NetworkStatsManager>() {
+            @Override
+            public NetworkStatsManager createService(ContextImpl ctx) {
+                return new NetworkStatsManager(ctx.getOuterContext());
+            }});
+
         registerService(Context.JOB_SCHEDULER_SERVICE, JobScheduler.class,
                 new StaticServiceFetcher<JobScheduler>() {
             @Override
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index da7bb05..7acf5f0 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -103,9 +103,9 @@
                     request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
                     if (DEBUG) Log.d(TAG, "onCompleteVoice: req="
                             + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
-                            + " result=" + args.arg1);
+                            + " result=" + args.arg2);
                     if (request != null) {
-                        ((CompleteVoiceRequest)request).onCompleteResult((Bundle) args.arg1);
+                        ((CompleteVoiceRequest)request).onCompleteResult((Bundle) args.arg2);
                         request.clear();
                     }
                     break;
@@ -297,6 +297,7 @@
          */
         public static final class Option implements Parcelable {
             final CharSequence mLabel;
+            final int mIndex;
             ArrayList<CharSequence> mSynonyms;
             Bundle mExtras;
 
@@ -308,6 +309,21 @@
              */
             public Option(CharSequence label) {
                 mLabel = label;
+                mIndex = -1;
+            }
+
+            /**
+             * Creates an option that a user can select with their voice by matching the label
+             * or one of several synonyms.
+             * @param label The label that will both be matched against what the user speaks
+             * and displayed visually.
+             * @param index The location of this option within the overall set of options.
+             * Can be used to help identify which the option when it is returned from the
+             * voice interactor.
+             */
+            public Option(CharSequence label, int index) {
+                mLabel = label;
+                mIndex = index;
             }
 
             /**
@@ -328,6 +344,14 @@
                 return mLabel;
             }
 
+            /**
+             * Return the index that was supplied in the constructor.
+             * If the option was constructed without an index, -1 is returned.
+             */
+            public int getIndex() {
+                return mIndex;
+            }
+
             public int countSynonyms() {
                 return mSynonyms != null ? mSynonyms.size() : 0;
             }
@@ -356,6 +380,7 @@
 
             Option(Parcel in) {
                 mLabel = in.readCharSequence();
+                mIndex = in.readInt();
                 mSynonyms = in.readCharSequenceList();
                 mExtras = in.readBundle();
             }
@@ -368,6 +393,7 @@
             @Override
             public void writeToParcel(Parcel dest, int flags) {
                 dest.writeCharSequence(mLabel);
+                dest.writeInt(mIndex);
                 dest.writeCharSequenceList(mSynonyms);
                 dest.writeBundle(mExtras);
             }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6dde07b..68f4707 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -20,7 +20,6 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.app.Activity;
-import android.app.admin.IDevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -176,7 +175,8 @@
      *
      * <p>This component is set as device owner and active admin when device owner provisioning is
      * started by an NFC message containing an NFC record with MIME type
-     * {@link #MIME_TYPE_PROVISIONING_NFC}.
+     * {@link #MIME_TYPE_PROVISIONING_NFC_V2}. For the NFC record, the component name should be
+     * flattened to a string, via {@link ComponentName#flattenToShortString()}.
      *
      * @see DeviceAdminReceiver
      */
@@ -346,7 +346,7 @@
      * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION} if the version of the
      * installed package is less than this version code.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE
@@ -363,10 +363,10 @@
         = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
 
     /**
-     * A String extra holding the SHA-1 checksum of the file at download location specified in
-     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}. If this doesn't match
-     * the file at the download location an error will be shown to the user and the user will be
-     * asked to factory reset the device.
+     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download
+     * location specified in {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}. If
+     * this doesn't match the file at the download location an error will be shown to the user and
+     * the user will be asked to factory reset the device.
      *
      * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
      * provisioning via an NFC bump.
@@ -392,21 +392,23 @@
      * A boolean extra indicating whether device encryption is required as part of Device Owner
      * provisioning.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
     public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION =
              "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
 
     /**
-     * On devices managed by a device owner app, a String representation of a Component name extra
-     * indicating the component of the application that is temporarily granted device owner
-     * privileges during device initialization and profile owner privileges during secondary user
-     * initialization.
+     * On devices managed by a device owner app, a {@link ComponentName} extra indicating the
+     * component of the application that is temporarily granted device owner privileges during
+     * device initialization and profile owner privileges during secondary user initialization.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
-     * provisioning via an NFC bump.
-     * @see ComponentName#unflattenFromString()
+     * <p>
+     * It can also be used in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts
+     * device owner provisioning via an NFC bump. For the NFC record, it should be flattened to a
+     * string first.
+     *
+     * @see ComponentName#flattenToShortString()
      */
     public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME
         = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
@@ -416,7 +418,7 @@
      * initializer package. When not provided it is assumed that the device initializer package is
      * already installed.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION
@@ -428,7 +430,7 @@
      * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION} if the version of
      * the installed package is less than this version code.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE
@@ -438,19 +440,20 @@
      * A String extra holding a http cookie header which should be used in the http request to the
      * url specified in {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER
         = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
 
     /**
-     * A String extra holding the SHA-1 checksum of the file at download location specified in
+     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download
+     * location specified in
      * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}. If this doesn't
      * match the file at the download location an error will be shown to the user and the user will
      * be asked to factory reset the device.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM
@@ -460,7 +463,7 @@
      * A String extra holding the MAC address of the Bluetooth device to connect to with status
      * updates during provisioning.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
     public static final String EXTRA_PROVISIONING_BT_MAC_ADDRESS
@@ -472,7 +475,7 @@
      *
      * <p>This value must be specified when {@code #EXTRA_PROVISIONING_BT_MAC_ADDRESS} is present.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
     public static final String EXTRA_PROVISIONING_BT_UUID
@@ -484,7 +487,7 @@
      *
      * <p>This value must be specified when {@code #EXTRA_PROVISIONING_BT_MAC_ADDRESS} is present.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
     public static final String EXTRA_PROVISIONING_BT_DEVICE_ID
@@ -494,31 +497,40 @@
      * A Boolean extra that that will cause a provisioned device to temporarily proxy network
      * traffic over Bluetooth. When a Wi-Fi network is available, the network proxy will stop.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
     public static final String EXTRA_PROVISIONING_BT_USE_PROXY
             = "android.app.extra.PROVISIONING_BT_USE_PROXY";
 
     /**
-     * This MIME type is used for starting the Device Owner provisioning.
+     * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
+     * holds data needed by the system to wipe factory reset protection. The data needed to wipe
+     * the device depend on the installed factory reset protection implementation. For example,
+     * if an account is needed to unlock a device, this extra may contain data used to
+     * authenticate that account.
      *
-     * <p>During device owner provisioning a device admin app is set as the owner of the device.
-     * A device owner has full control over the device. The device owner can not be modified by the
-     * user and the only way of resetting the device is if the device owner app calls a factory
-     * reset.
+     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
+     * provisioning via an NFC bump.
+     */
+    public static final String EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS
+            = "android.app.extra.PROVISIONING_RESET_PROTECTION_PARAMETERS";
+
+    /**
+     * This MIME type is used for starting the Device Owner provisioning that does not require
+     * provisioning features introduced in Android API level
+     * {@link android.os.Build.VERSION_CODES#MNC} or later levels.
      *
-     * <p> A typical use case would be a device that is owned by a company, but used by either an
-     * employee or client.
-     *
-     * <p> The NFC message should be send to an unprovisioned device.
+     * <p>For more information about the provisioning process see
+     * {@link #MIME_TYPE_PROVISIONING_NFC_V2}.
      *
      * <p>The NFC record must contain a serialized {@link java.util.Properties} object which
      * contains the following properties:
      * <ul>
-     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}, optional</li>
      * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER}, optional</li>
-     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM}</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM}, optional</li>
      * <li>{@link #EXTRA_PROVISIONING_LOCAL_TIME} (convert to String), optional</li>
      * <li>{@link #EXTRA_PROVISIONING_TIME_ZONE}, optional</li>
      * <li>{@link #EXTRA_PROVISIONING_LOCALE}, optional</li>
@@ -529,17 +541,56 @@
      * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_HOST}, optional</li>
      * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_PORT} (convert to String), optional</li>
      * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_BYPASS}, optional</li>
-     * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li>
-     * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li></ul>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li></ul>
      *
      * <p>
-     * In version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, it should also contain
-     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}.
-     * As of {@link android.os.Build.VERSION_CODES#MNC}, it should contain
-     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} instead, (although
-     * specifying only {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} is still supported).
-     * This componentName must have been converted to a String via
-     * {@link android.content.ComponentName#flattenToString()}
+     * As of {@link android.os.Build.VERSION_CODES#MNC}, the properties should contain
+     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} instead of
+     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}, (although specifying only
+     * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} is still supported).
+     *
+     * @see #MIME_TYPE_PROVISIONING_NFC_V2
+     *
+     */
+    public static final String MIME_TYPE_PROVISIONING_NFC
+        = "application/com.android.managedprovisioning";
+
+
+    /**
+     * This MIME type is used for starting the Device Owner provisioning that requires
+     * new provisioning features introduced in API version
+     * {@link android.os.Build.VERSION_CODES#MNC} in addition to those supported in earlier
+     * versions.
+     *
+     * <p>During device owner provisioning a device admin app is set as the owner of the device.
+     * A device owner has full control over the device. The device owner can not be modified by the
+     * user and the only way of resetting the device is if the device owner app calls a factory
+     * reset.
+     *
+     * <p> A typical use case would be a device that is owned by a company, but used by either an
+     * employee or client.
+     *
+     * <p> The NFC message should be sent to an unprovisioned device.
+     *
+     * <p>The NFC record must contain a serialized {@link java.util.Properties} object which
+     * contains the following properties in addition to properties listed at
+     * {@link #MIME_TYPE_PROVISIONING_NFC}:
+     * <ul>
+     * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}.
+     * Replaces {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}. The value of the property
+     * should be converted to a String via
+     * {@link android.content.ComponentName#flattenToString()}</li>
+     * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_BT_MAC_ADDRESS}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_BT_UUID}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_BT_DEVICE_ID}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_BT_USE_PROXY}, optional</li></ul>
      *
      * <p> When device owner provisioning has completed, an intent of the type
      * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the
@@ -551,8 +602,8 @@
      * <p>Input: Nothing.</p>
      * <p>Output: Nothing</p>
      */
-    public static final String MIME_TYPE_PROVISIONING_NFC
-        = "application/com.android.managedprovisioning";
+    public static final String MIME_TYPE_PROVISIONING_NFC_V2
+            = "application/com.android.managedprovisioning.v2";
 
     /**
      * Activity action: ask the user to add a new device administrator to the system.
@@ -577,11 +628,10 @@
     /**
      * @hide
      * Activity action: ask the user to add a new device administrator as the profile owner
-     * for this user. Only system privileged apps that have MANAGE_USERS and MANAGE_DEVICE_ADMINS
-     * permission can call this API.
+     * for this user. Only system apps can launch this intent.
      *
-     * <p>The ComponentName of the profile owner admin is pass in {@link #EXTRA_DEVICE_ADMIN} extra
-     * field. This will invoke a UI to bring the user through adding the profile owner admin
+     * <p>The ComponentName of the profile owner admin is passed in the {@link #EXTRA_DEVICE_ADMIN}
+     * extra field. This will invoke a UI to bring the user through adding the profile owner admin
      * to remotely control restrictions on the user.
      *
      * <p>The intent must be invoked via {@link Activity#startActivityForResult()} to receive the
@@ -593,8 +643,8 @@
      * field to provide the user with additional explanation (in addition
      * to your component's description) about what is being added.
      *
-     * <p>If there is already a profile owner active or the caller doesn't have the required
-     * permissions, the operation will return a failure result.
+     * <p>If there is already a profile owner active or the caller is not a system app, the
+     * operation will return a failure result.
      */
     @SystemApi
     public static final String ACTION_SET_PROFILE_OWNER
@@ -2603,8 +2653,8 @@
      *        called by the device owner.
      * @param initializer Which {@link DeviceAdminReceiver} to make device initializer.
      * @param initializerName The user-visible name of the device initializer.
-     * @return whether the package was successfully registered as the device initializer.
-     * @throws IllegalArgumentException if the package name is null or invalid
+     * @return whether the component was successfully registered as the device initializer.
+     * @throws IllegalArgumentException if the componentname is null or invalid
      * @throws IllegalStateException if the caller is not device owner or the device has
      *         already been provisioned or a device initializer already exists.
      */
@@ -2674,6 +2724,25 @@
     }
 
     /**
+     * @hide
+     * Gets the device initializer component of the system.
+     *
+     * @return the component name of the device initializer.
+     */
+    @SystemApi
+    public ComponentName getDeviceInitializerComponent() {
+        if (mService != null) {
+            try {
+                return mService.getDeviceInitializerComponent();
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed to get device initializer");
+            }
+        }
+        return null;
+    }
+
+
+    /**
      * Sets the enabled state of the user. A user should be enabled only once it is ready to
      * be used.
      *
@@ -3129,6 +3198,22 @@
     }
 
     /**
+     * Start Quick Contact on the managed profile for the current user, if the policy allows.
+     * @hide
+     */
+    public void startManagedQuickContact(String actualLookupKey, long actualContactId,
+            Intent originalIntent) {
+        if (mService != null) {
+            try {
+                mService.startManagedQuickContact(
+                        actualLookupKey, actualContactId, originalIntent);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
      * Called by the profile owner of a managed profile so that some intents sent in the managed
      * profile can also be resolved in the parent, or vice versa.
      * Only activity intents are supported.
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index a1f1d92..0a0d77d 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -60,4 +60,13 @@
      */
     public abstract void addOnCrossProfileWidgetProvidersChangeListener(
             OnCrossProfileWidgetProvidersChangeListener listener);
+
+    /**
+     * Checks if an app with given uid is an active device admin of its user and has the policy
+     * specified.
+     * @param uid App uid.
+     * @param reqPolicy Required policy, for policies see {@link DevicePolicyManager}.
+     * @return true if the uid is an active admin with the given policy.
+     */
+    public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy);
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9ca52e5..c68311e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -189,6 +189,7 @@
     void setCrossProfileCallerIdDisabled(in ComponentName who, boolean disabled);
     boolean getCrossProfileCallerIdDisabled(in ComponentName who);
     boolean getCrossProfileCallerIdDisabledForUser(int userId);
+    void startManagedQuickContact(String lookupKey, long contactId, in Intent originalIntent);
 
     void setTrustAgentConfiguration(in ComponentName admin, in ComponentName agent,
             in PersistableBundle args);
@@ -209,6 +210,7 @@
     void clearDeviceInitializer(in ComponentName who);
     boolean setDeviceInitializer(in ComponentName who, in ComponentName initializer, String initializerName);
     String getDeviceInitializer();
+    ComponentName getDeviceInitializerComponent();
 
     void setUserIcon(in ComponentName admin, in Bitmap icon);
 }
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 7f89100..2bf267a 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -424,10 +424,12 @@
         }
 
         // And now that we know where it lives, semantically, back it up appropriately
-        Log.i(TAG, "backupFile() of " + filePath + " => domain=" + domain
+        // In the measurement case, backupToTar() updates the size in output and returns
+        // without transmitting any file data.
+        if (DEBUG) Log.i(TAG, "backupFile() of " + filePath + " => domain=" + domain
                 + " rootpath=" + rootpath);
-        FullBackup.backupToTar(getPackageName(), domain, null, rootpath, filePath,
-                output.getData());
+        
+        FullBackup.backupToTar(getPackageName(), domain, null, rootpath, filePath, output);
     }
 
     /**
@@ -477,9 +479,8 @@
                     continue;
                 }
 
-                // Finally, back this file up before proceeding
-                FullBackup.backupToTar(packageName, domain, null, rootPath, filePath,
-                        output.getData());
+                // Finally, back this file up (or measure it) before proceeding
+                FullBackup.backupToTar(packageName, domain, null, rootPath, filePath, output);
             }
         }
     }
@@ -640,7 +641,7 @@
 
                 Binder.restoreCallingIdentity(ident);
                 try {
-                    callbackBinder.opComplete(token);
+                    callbackBinder.opComplete(token, 0);
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
@@ -670,7 +671,7 @@
 
                 Binder.restoreCallingIdentity(ident);
                 try {
-                    callbackBinder.opComplete(token);
+                    callbackBinder.opComplete(token, 0);
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
@@ -692,10 +693,10 @@
             try {
                 BackupAgent.this.onFullBackup(new FullBackupDataOutput(data));
             } catch (IOException ex) {
-                Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
+                Log.d(TAG, "onFullBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
                 throw new RuntimeException(ex);
             } catch (RuntimeException ex) {
-                Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
+                Log.d(TAG, "onFullBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
                 throw ex;
             } finally {
                 // ... and then again after, as in the doBackup() case
@@ -713,13 +714,37 @@
 
                 Binder.restoreCallingIdentity(ident);
                 try {
-                    callbackBinder.opComplete(token);
+                    callbackBinder.opComplete(token, 0);
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
             }
         }
 
+        public void doMeasureFullBackup(int token, IBackupManager callbackBinder) {
+            // Ensure that we're running with the app's normal permission level
+            final long ident = Binder.clearCallingIdentity();
+            FullBackupDataOutput measureOutput = new FullBackupDataOutput();
+
+            waitForSharedPrefs();
+            try {
+                BackupAgent.this.onFullBackup(measureOutput);
+            } catch (IOException ex) {
+                Log.d(TAG, "onFullBackup[M] (" + BackupAgent.this.getClass().getName() + ") threw", ex);
+                throw new RuntimeException(ex);
+            } catch (RuntimeException ex) {
+                Log.d(TAG, "onFullBackup[M] (" + BackupAgent.this.getClass().getName() + ") threw", ex);
+                throw ex;
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+                try {
+                    callbackBinder.opComplete(token, measureOutput.getSize());
+                } catch (RemoteException e) {
+                    // timeout, so we're safe
+                }
+            }
+        }
+
         @Override
         public void doRestoreFile(ParcelFileDescriptor data, long size,
                 int type, String domain, String path, long mode, long mtime,
@@ -728,6 +753,7 @@
             try {
                 BackupAgent.this.onRestoreFile(data, size, type, domain, path, mode, mtime);
             } catch (IOException e) {
+                Log.d(TAG, "onRestoreFile (" + BackupAgent.this.getClass().getName() + ") threw", e);
                 throw new RuntimeException(e);
             } finally {
                 // Ensure that any side-effect SharedPreferences writes have landed
@@ -735,7 +761,7 @@
 
                 Binder.restoreCallingIdentity(ident);
                 try {
-                    callbackBinder.opComplete(token);
+                    callbackBinder.opComplete(token, 0);
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
@@ -747,13 +773,16 @@
             long ident = Binder.clearCallingIdentity();
             try {
                 BackupAgent.this.onRestoreFinished();
+            } catch (Exception e) {
+                Log.d(TAG, "onRestoreFinished (" + BackupAgent.this.getClass().getName() + ") threw", e);
+                throw e;
             } finally {
                 // Ensure that any side-effect SharedPreferences writes have landed
                 waitForSharedPrefs();
 
                 Binder.restoreCallingIdentity(ident);
                 try {
-                    callbackBinder.opComplete(token);
+                    callbackBinder.opComplete(token, 0);
                 } catch (RemoteException e) {
                     // we'll time out anyway, so we're safe
                 }
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index e853540..1131ff9 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -393,6 +393,26 @@
     }
 
     /**
+     * Called after {@link #performFullBackup} to make sure that the transport is willing to
+     * handle a full-data backup operation of the specified size on the current package.
+     * If the transport returns anything other than TRANSPORT_OK, the package's backup
+     * operation will be skipped (and {@link #finishBackup() invoked} with no data for that
+     * package being passed to {@link #sendBackupData}.
+     *
+     * Added in MNC (API 23).
+     *
+     * @param size The estimated size of the full-data payload for this app.  This includes
+     *         manifest and archive format overhead, but is not guaranteed to be precise.
+     * @return TRANSPORT_OK if the platform is to proceed with the full-data backup,
+     *         TRANSPORT_PACKAGE_REJECTED if the proposed payload size is too large for
+     *         the transport to handle, or TRANSPORT_ERROR to indicate a fatal error
+     *         condition that means the platform cannot perform a backup at this time.
+     */
+    public int checkFullBackupSize(long size) {
+        return BackupTransport.TRANSPORT_OK;
+    }
+
+    /**
      * Tells the transport to read {@code numBytes} bytes of data from the socket file
      * descriptor provided in the {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)}
      * call, and deliver those bytes to the datastore.
@@ -444,7 +464,7 @@
      * transport level).
      *
      * <p>After this method returns zero, the system will then call
-     * {@link #getNextFullRestorePackage()} to begin the restore process for the next
+     * {@link #nextRestorePackage()} to begin the restore process for the next
      * application, and the sequence begins again.
      *
      * <p>The transport should always close this socket when returning from this method.
@@ -588,6 +608,11 @@
         }
 
         @Override
+        public int checkFullBackupSize(long size) {
+            return BackupTransport.this.checkFullBackupSize(size);
+        }
+
+        @Override
         public int sendBackupData(int numBytes) throws RemoteException {
             return BackupTransport.this.sendBackupData(numBytes);
         }
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index e5b47c6..259884e 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -58,7 +58,7 @@
      * @hide
      */
     static public native int backupToTar(String packageName, String domain,
-            String linkdomain, String rootpath, String path, BackupDataOutput output);
+            String linkdomain, String rootpath, String path, FullBackupDataOutput output);
 
     /**
      * Copy data from a socket to the given File location on permanent storage.  The
diff --git a/core/java/android/app/backup/FullBackupDataOutput.java b/core/java/android/app/backup/FullBackupDataOutput.java
index 99dab1f..94704b9 100644
--- a/core/java/android/app/backup/FullBackupDataOutput.java
+++ b/core/java/android/app/backup/FullBackupDataOutput.java
@@ -9,7 +9,14 @@
  */
 public class FullBackupDataOutput {
     // Currently a name-scoping shim around BackupDataOutput
-    private BackupDataOutput mData;
+    private final BackupDataOutput mData;
+    private long mSize;
+
+    /** @hide - used only in measure operation */
+    public FullBackupDataOutput() {
+        mData = null;
+        mSize = 0;
+    }
 
     /** @hide */
     public FullBackupDataOutput(ParcelFileDescriptor fd) {
@@ -18,4 +25,14 @@
 
     /** @hide */
     public BackupDataOutput getData() { return mData; }
+
+    /** @hide - used for measurement pass */
+    public void addSize(long size) {
+        if (size > 0) {
+            mSize += size;
+        }
+    }
+
+    /** @hide - used for measurement pass */
+    public long getSize() { return mSize; }
 }
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 41ad936..8f36dc4 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -286,11 +286,14 @@
      * Notify the backup manager that a BackupAgent has completed the operation
      * corresponding to the given token.
      *
-     * @param token The transaction token passed to a BackupAgent's doBackup() or
-     *        doRestore() method.
+     * @param token The transaction token passed to the BackupAgent method being
+     *        invoked.
+     * @param result In the case of a full backup measure operation, the estimated
+     *        total file size that would result from the operation. Unused in all other
+     *        cases.
      * {@hide}
      */
-    void opComplete(int token);
+    void opComplete(int token, long result);
 
     /**
      * Make the device's backup and restore machinery (in)active.  When it is inactive,
diff --git a/core/java/android/app/backup/RecentsBackupHelper.java b/core/java/android/app/backup/RecentsBackupHelper.java
index fd69d20..1a64da6 100644
--- a/core/java/android/app/backup/RecentsBackupHelper.java
+++ b/core/java/android/app/backup/RecentsBackupHelper.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package android.app.backup;
 
 import android.content.Context;
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
new file mode 100644
index 0000000..af7c053
--- /dev/null
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -0,0 +1,233 @@
+/**
+ * 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.app.usage;
+
+import android.app.usage.NetworkUsageStats.Bucket;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkIdentity;
+import android.net.NetworkTemplate;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+/**
+ * Provides access to network usage history and statistics. Usage data is collected in
+ * discrete bins of time called 'Buckets'. See {@link NetworkUsageStats.Bucket} for details.
+ * <p />
+ * Queries can define a time interval in the form of start and end timestamps (Long.MIN_VALUE and
+ * Long.MAX_VALUE can be used to simulate open ended intervals). All queries (except
+ * {@link #querySummaryForDevice}) collect only network usage of apps belonging to the same user
+ * as the client. In addition tethering usage, usage by removed users and apps, and usage by system
+ * is also included in the results.
+ * <h3>
+ * Summary queries
+ * </h3>
+ * These queries aggregate network usage across the whole interval. Therefore there will be only one
+ * bucket for a particular key and state combination. In case of the user-wide and device-wide
+ * summaries a single bucket containing the totalised network usage is returned.
+ * <h3>
+ * History queries
+ * </h3>
+ * These queries do not aggregate over time but do aggregate over state. Therefore there can be
+ * multiple buckets for a particular key but all Bucket's state is going to be
+ * {@link NetworkUsageStats.Bucket#STATE_ALL}.
+ * <p />
+ * <b>NOTE:</b> This API requires the permission
+ * {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, which is a system-level permission and
+ * will not be granted to third-party apps. However, declaring the permission implies intention to
+ * use the API and the user of the device can grant permission through the Settings application.
+ * Profile owner apps are automatically granted permission to query data on the profile they manage
+ * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps likewise get
+ * access to usage data of the primary user.
+ */
+public class NetworkStatsManager {
+    private final static String TAG = "NetworkStatsManager";
+
+    private final Context mContext;
+
+    /**
+     * {@hide}
+     */
+    public NetworkStatsManager(Context context) {
+        mContext = context;
+    }
+    /**
+     * Query network usage statistics summaries. Result is summarised data usage for the whole
+     * device. Result is a single Bucket aggregated over time, state and uid.
+     *
+     * @param networkType As defined in {@link ConnectivityManager}, e.g.
+     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
+     *            etc.
+     * @param subscriberId If applicable, the subscriber id of the network interface.
+     * @param startTime Start of period. Defined in terms of "Unix time", see
+     *            {@link java.lang.System#currentTimeMillis}.
+     * @param endTime End of period. Defined in terms of "Unix time", see
+     *            {@link java.lang.System#currentTimeMillis}.
+     * @return Bucket object or null if permissions are insufficient or error happened during
+     *         statistics collection.
+     */
+    public Bucket querySummaryForDevice(int networkType, String subscriberId,
+            long startTime, long endTime) throws SecurityException, RemoteException {
+        NetworkTemplate template = createTemplate(networkType, subscriberId);
+        if (template == null) {
+            return null;
+        }
+
+        Bucket bucket = null;
+        NetworkUsageStats stats = new NetworkUsageStats(mContext, template, startTime, endTime);
+        bucket = stats.getDeviceSummaryForNetwork(startTime, endTime);
+
+        stats.close();
+        return bucket;
+    }
+
+    /**
+     * Query network usage statistics summaries. Result is summarised data usage for all uids
+     * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
+     *
+     * @param networkType As defined in {@link ConnectivityManager}, e.g.
+     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
+     *            etc.
+     * @param subscriberId If applicable, the subscriber id of the network interface.
+     * @param startTime Start of period. Defined in terms of "Unix time", see
+     *            {@link java.lang.System#currentTimeMillis}.
+     * @param endTime End of period. Defined in terms of "Unix time", see
+     *            {@link java.lang.System#currentTimeMillis}.
+     * @return Bucket object or null if permissions are insufficient or error happened during
+     *         statistics collection.
+     */
+    public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
+            long endTime) throws SecurityException, RemoteException {
+        NetworkTemplate template = createTemplate(networkType, subscriberId);
+        if (template == null) {
+            return null;
+        }
+
+        NetworkUsageStats stats;
+        stats = new NetworkUsageStats(mContext, template, startTime, endTime);
+        stats.startSummaryEnumeration(startTime, endTime);
+
+        stats.close();
+        return stats.getSummaryAggregate();
+    }
+
+    /**
+     * Query network usage statistics summaries. Result filtered to include only uids belonging to
+     * calling user. Result is aggregated over time, hence all buckets will have the same start and
+     * end timestamps. Not aggregated over state or uid.
+     *
+     * @param networkType As defined in {@link ConnectivityManager}, e.g.
+     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
+     *            etc.
+     * @param subscriberId If applicable, the subscriber id of the network interface.
+     * @param startTime Start of period. Defined in terms of "Unix time", see
+     *            {@link java.lang.System#currentTimeMillis}.
+     * @param endTime End of period. Defined in terms of "Unix time", see
+     *            {@link java.lang.System#currentTimeMillis}.
+     * @return Statistics object or null if permissions are insufficient or error happened during
+     *         statistics collection.
+     */
+    public NetworkUsageStats querySummary(int networkType, String subscriberId, long startTime,
+            long endTime) throws SecurityException, RemoteException {
+        NetworkTemplate template = createTemplate(networkType, subscriberId);
+        if (template == null) {
+            return null;
+        }
+
+        NetworkUsageStats result;
+        result = new NetworkUsageStats(mContext, template, startTime, endTime);
+        result.startSummaryEnumeration(startTime, endTime);
+
+        return result;
+    }
+
+    /**
+     * Query network usage statistics details. Only usable for uids belonging to calling user.
+     * Result is aggregated over state but not aggregated over time.
+     *
+     * @param networkType As defined in {@link ConnectivityManager}, e.g.
+     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
+     *            etc.
+     * @param subscriberId If applicable, the subscriber id of the network interface.
+     * @param startTime Start of period. Defined in terms of "Unix time", see
+     *            {@link java.lang.System#currentTimeMillis}.
+     * @param endTime End of period. Defined in terms of "Unix time", see
+     *            {@link java.lang.System#currentTimeMillis}.
+     * @param uid UID of app
+     * @return Statistics object or null if permissions are insufficient or error happened during
+     *         statistics collection.
+     */
+    public NetworkUsageStats queryDetailsForUid(int networkType, String subscriberId,
+            long startTime, long endTime, int uid) throws SecurityException, RemoteException {
+        NetworkTemplate template = createTemplate(networkType, subscriberId);
+        if (template == null) {
+            return null;
+        }
+
+        NetworkUsageStats result;
+        result = new NetworkUsageStats(mContext, template, startTime, endTime);
+        result.startHistoryEnumeration(uid);
+
+        return result;
+    }
+
+    /**
+     * Query network usage statistics details. Result filtered to include only uids belonging to
+     * calling user. Result is aggregated over state but not aggregated over time or uid.
+     *
+     * @param networkType As defined in {@link ConnectivityManager}, e.g.
+     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
+     *            etc.
+     * @param subscriberId If applicable, the subscriber id of the network interface.
+     * @param startTime Start of period. Defined in terms of "Unix time", see
+     *            {@link java.lang.System#currentTimeMillis}.
+     * @param endTime End of period. Defined in terms of "Unix time", see
+     *            {@link java.lang.System#currentTimeMillis}.
+     * @return Statistics object or null if permissions are insufficient or error happened during
+     *         statistics collection.
+     */
+    public NetworkUsageStats queryDetails(int networkType, String subscriberId, long startTime,
+            long endTime) throws SecurityException, RemoteException {
+        NetworkTemplate template = createTemplate(networkType, subscriberId);
+        if (template == null) {
+            return null;
+        }
+        NetworkUsageStats result;
+        result = new NetworkUsageStats(mContext, template, startTime, endTime);
+        result.startUserUidEnumeration();
+        return result;
+    }
+
+    private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
+        NetworkTemplate template = null;
+        switch (networkType) {
+            case ConnectivityManager.TYPE_MOBILE: {
+                template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
+                } break;
+            case ConnectivityManager.TYPE_WIFI: {
+                template = NetworkTemplate.buildTemplateWifiWildcard();
+                } break;
+            default: {
+                Log.w(TAG, "Cannot create template for network type " + networkType
+                        + ", subscriberId '" + NetworkIdentity.scrubSubscriberId(subscriberId) +
+                        "'.");
+            }
+        }
+        return template;
+    }
+}
diff --git a/core/java/android/app/usage/NetworkUsageStats.java b/core/java/android/app/usage/NetworkUsageStats.java
new file mode 100644
index 0000000..990d231
--- /dev/null
+++ b/core/java/android/app/usage/NetworkUsageStats.java
@@ -0,0 +1,479 @@
+/**
+ * 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.app.usage;
+
+import android.content.Context;
+import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStats;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.net.TrafficStats;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import dalvik.system.CloseGuard;
+
+/**
+ * Class providing enumeration over buckets of network usage statistics. NetworkUsageStats objects
+ * are returned as results to various queries in {@link NetworkStatsManager}.
+ */
+public final class NetworkUsageStats implements AutoCloseable {
+    private final static String TAG = "NetworkUsageStats";
+
+    private final CloseGuard mCloseGuard = CloseGuard.get();
+
+    /**
+     * Start timestamp of stats collected
+     */
+    private final long mStartTimeStamp;
+
+    /**
+     * End timestamp of stats collected
+     */
+    private final long mEndTimeStamp;
+
+
+    /**
+     * Non-null array indicates the query enumerates over uids.
+     */
+    private int[] mUids;
+
+    /**
+     * Index of the current uid in mUids when doing uid enumeration or a single uid value,
+     * depending on query type.
+     */
+    private int mUidOrUidIndex;
+
+    /**
+     * The session while the query requires it, null if all the stats have been collected or close()
+     * has been called.
+     */
+    private INetworkStatsSession mSession;
+    private NetworkTemplate mTemplate;
+
+    /**
+     * Results of a summary query.
+     */
+    private NetworkStats mSummary = null;
+
+    /**
+     * Results of detail queries.
+     */
+    private NetworkStatsHistory mHistory = null;
+
+    /**
+     * Where we are in enumerating over the current result.
+     */
+    private int mEnumerationIndex = 0;
+
+    /**
+     * Recycling entry objects to prevent heap fragmentation.
+     */
+    private NetworkStats.Entry mRecycledSummaryEntry = null;
+    private NetworkStatsHistory.Entry mRecycledHistoryEntry = null;
+
+    /** @hide */
+    NetworkUsageStats(Context context, NetworkTemplate template, long startTimestamp,
+            long endTimestamp) throws RemoteException, SecurityException {
+        final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
+                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+        // Open network stats session
+        mSession = statsService.openSessionForUsageStats(context.getOpPackageName());
+        mCloseGuard.open("close");
+        mTemplate = template;
+        mStartTimeStamp = startTimestamp;
+        mEndTimeStamp = endTimestamp;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
+            }
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    // -------------------------BEGINNING OF PUBLIC API-----------------------------------
+
+    /**
+     * Buckets are the smallest elements of a query result. As some dimensions of a result may be
+     * aggregated (e.g. time or state) some values may be equal across all buckets.
+     */
+    public static class Bucket {
+        /**
+         * Combined usage across all other states.
+         */
+        public static final int STATE_ALL = -1;
+
+        /**
+         * Usage not accounted in any other states.
+         */
+        public static final int STATE_DEFAULT = 0x1;
+
+        /**
+         * Foreground usage.
+         */
+        public static final int STATE_FOREGROUND = 0x2;
+
+        /**
+         * Special UID value for removed apps.
+         */
+        public static final int UID_REMOVED = -4;
+
+        /**
+         * Special UID value for data usage by tethering.
+         */
+        public static final int UID_TETHERING = -5;
+
+        private int mUid;
+        private int mState;
+        private long mBeginTimeStamp;
+        private long mEndTimeStamp;
+        private long mRxBytes;
+        private long mRxPackets;
+        private long mTxBytes;
+        private long mTxPackets;
+
+        private static int convertState(int networkStatsSet) {
+            switch (networkStatsSet) {
+                case NetworkStats.SET_ALL : return STATE_ALL;
+                case NetworkStats.SET_DEFAULT : return STATE_DEFAULT;
+                case NetworkStats.SET_FOREGROUND : return STATE_FOREGROUND;
+            }
+            return 0;
+        }
+
+        private static int convertUid(int uid) {
+            switch (uid) {
+                case TrafficStats.UID_REMOVED: return UID_REMOVED;
+                case TrafficStats.UID_TETHERING: return UID_TETHERING;
+            }
+            return uid;
+        }
+
+        public Bucket() {
+        }
+
+        /**
+         * Key of the bucket. Usually an app uid or one of the following special values:<p />
+         * <ul>
+         * <li>{@link #UID_REMOVED}</li>
+         * <li>{@link #UID_TETHERING}</li>
+         * <li>{@link android.os.Process#SYSTEM_UID}</li>
+         * </ul>
+         * @return Bucket key.
+         */
+        public int getUid() {
+            return mUid;
+        }
+
+        /**
+         * Usage state. One of the following values:<p/>
+         * <ul>
+         * <li>{@link #STATE_ALL}</li>
+         * <li>{@link #STATE_DEFAULT}</li>
+         * <li>{@link #STATE_FOREGROUND}</li>
+         * </ul>
+         * @return Usage state.
+         */
+        public int getState() {
+            return mState;
+        }
+
+        /**
+         * Start timestamp of the bucket's time interval. Defined in terms of "Unix time", see
+         * {@link java.lang.System#currentTimeMillis}.
+         * @return Start of interval.
+         */
+        public long getStartTimeStamp() {
+            return mBeginTimeStamp;
+        }
+
+        /**
+         * End timestamp of the bucket's time interval. Defined in terms of "Unix time", see
+         * {@link java.lang.System#currentTimeMillis}.
+         * @return End of interval.
+         */
+        public long getEndTimeStamp() {
+            return mEndTimeStamp;
+        }
+
+        /**
+         * Number of bytes received during the bucket's time interval. Statistics are measured at
+         * the network layer, so they include both TCP and UDP usage.
+         * @return Number of bytes.
+         */
+        public long getRxBytes() {
+            return mRxBytes;
+        }
+
+        /**
+         * Number of bytes transmitted during the bucket's time interval. Statistics are measured at
+         * the network layer, so they include both TCP and UDP usage.
+         * @return Number of bytes.
+         */
+        public long getTxBytes() {
+            return mTxBytes;
+        }
+
+        /**
+         * Number of packets received during the bucket's time interval. Statistics are measured at
+         * the network layer, so they include both TCP and UDP usage.
+         * @return Number of packets.
+         */
+        public long getRxPackets() {
+            return mRxPackets;
+        }
+
+        /**
+         * Number of packets transmitted during the bucket's time interval. Statistics are measured
+         * at the network layer, so they include both TCP and UDP usage.
+         * @return Number of packets.
+         */
+        public long getTxPackets() {
+            return mTxPackets;
+        }
+    }
+
+    /**
+     * Fills the recycled bucket with data of the next bin in the enumeration.
+     * @param bucketOut Bucket to be filled with data.
+     * @return true if successfully filled the bucket, false otherwise.
+     */
+    public boolean getNextBucket(Bucket bucketOut) {
+        if (mSummary != null) {
+            return getNextSummaryBucket(bucketOut);
+        } else {
+            return getNextHistoryBucket(bucketOut);
+        }
+    }
+
+    /**
+     * Check if it is possible to ask for a next bucket in the enumeration.
+     * @return true if there is at least one more bucket.
+     */
+    public boolean hasNextBucket() {
+        if (mSummary != null) {
+            return mEnumerationIndex < mSummary.size();
+        } else if (mHistory != null) {
+            return mEnumerationIndex < mHistory.size()
+                    || hasNextUid();
+        }
+        return false;
+    }
+
+    /**
+     * Closes the enumeration. Call this method before this object gets out of scope.
+     */
+    @Override
+    public void close() {
+        if (mSession != null) {
+            try {
+                mSession.close();
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
+                // Otherwise, meh
+            }
+        }
+        mSession = null;
+        if (mCloseGuard != null) {
+            mCloseGuard.close();
+        }
+    }
+
+    // -------------------------END OF PUBLIC API-----------------------------------
+
+    /**
+     * Collects device summary results into a Bucket.
+     * @param startTime
+     * @param endTime
+     * @throws RemoteException
+     */
+    Bucket getDeviceSummaryForNetwork(long startTime, long endTime) throws RemoteException {
+        mSummary = mSession.getDeviceSummaryForNetwork(mTemplate, startTime, endTime);
+
+        // Setting enumeration index beyond end to avoid accidental enumeration over data that does
+        // not belong to the calling user.
+        mEnumerationIndex = mSummary.size();
+
+        return getSummaryAggregate();
+    }
+
+    /**
+     * Collects summary results and sets summary enumeration mode.
+     * @param startTime
+     * @param endTime
+     * @throws RemoteException
+     */
+    void startSummaryEnumeration(long startTime, long endTime) throws RemoteException {
+        mSummary = mSession.getSummaryForAllUid(mTemplate, startTime, endTime, false);
+
+        mEnumerationIndex = 0;
+    }
+
+    /**
+     * Collects history results for uid and resets history enumeration index.
+     */
+    void startHistoryEnumeration(int uid) {
+        mHistory = null;
+        try {
+            mHistory = mSession.getHistoryForUid(mTemplate, uid, NetworkStats.SET_ALL,
+                    NetworkStats.TAG_NONE, NetworkStatsHistory.FIELD_ALL);
+            setSingleUid(uid);
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+            // Leaving mHistory null
+        }
+        mEnumerationIndex = 0;
+    }
+
+    /**
+     * Starts uid enumeration for current user.
+     * @throws RemoteException
+     */
+    void startUserUidEnumeration() throws RemoteException {
+        setUidEnumeration(mSession.getRelevantUids());
+        stepHistory();
+    }
+
+    /**
+     * Steps to next uid in enumeration and collects history for that.
+     */
+    private void stepHistory(){
+        if (hasNextUid()) {
+            stepUid();
+            mHistory = null;
+            try {
+                mHistory = mSession.getHistoryForUid(mTemplate, getUid(), NetworkStats.SET_ALL,
+                        NetworkStats.TAG_NONE, NetworkStatsHistory.FIELD_ALL);
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
+                // Leaving mHistory null
+            }
+            mEnumerationIndex = 0;
+        }
+    }
+
+    private void fillBucketFromSummaryEntry(Bucket bucketOut) {
+        bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
+        bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
+        bucketOut.mBeginTimeStamp = mStartTimeStamp;
+        bucketOut.mEndTimeStamp = mEndTimeStamp;
+        bucketOut.mRxBytes = mRecycledSummaryEntry.rxBytes;
+        bucketOut.mRxPackets = mRecycledSummaryEntry.rxPackets;
+        bucketOut.mTxBytes = mRecycledSummaryEntry.txBytes;
+        bucketOut.mTxPackets = mRecycledSummaryEntry.txPackets;
+    }
+
+    /**
+     * Getting the next item in summary enumeration.
+     * @param bucketOut Next item will be set here.
+     * @return true if a next item could be set.
+     */
+    private boolean getNextSummaryBucket(Bucket bucketOut) {
+        if (bucketOut != null && mEnumerationIndex < mSummary.size()) {
+            mRecycledSummaryEntry = mSummary.getValues(mEnumerationIndex++, mRecycledSummaryEntry);
+            fillBucketFromSummaryEntry(bucketOut);
+            return true;
+        }
+        return false;
+    }
+
+    Bucket getSummaryAggregate() {
+        if (mSummary == null) {
+            return null;
+        }
+        Bucket bucket = new Bucket();
+        if (mRecycledSummaryEntry == null) {
+            mRecycledSummaryEntry = new NetworkStats.Entry();
+        }
+        mSummary.getTotal(mRecycledSummaryEntry);
+        fillBucketFromSummaryEntry(bucket);
+        return bucket;
+    }
+    /**
+     * Getting the next item in a history enumeration.
+     * @param bucketOut Next item will be set here.
+     * @return true if a next item could be set.
+     */
+    private boolean getNextHistoryBucket(Bucket bucketOut) {
+        if (bucketOut != null && mHistory != null) {
+            if (mEnumerationIndex < mHistory.size()) {
+                mRecycledHistoryEntry = mHistory.getValues(mEnumerationIndex++,
+                        mRecycledHistoryEntry);
+                bucketOut.mUid = Bucket.convertUid(getUid());
+                bucketOut.mState = Bucket.STATE_ALL;
+                bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
+                bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart +
+                        mRecycledHistoryEntry.bucketDuration;
+                bucketOut.mRxBytes = mRecycledHistoryEntry.rxBytes;
+                bucketOut.mRxPackets = mRecycledHistoryEntry.rxPackets;
+                bucketOut.mTxBytes = mRecycledHistoryEntry.txBytes;
+                bucketOut.mTxPackets = mRecycledHistoryEntry.txPackets;
+                return true;
+            } else if (hasNextUid()) {
+                stepHistory();
+                return getNextHistoryBucket(bucketOut);
+            }
+        }
+        return false;
+    }
+
+    // ------------------ UID LOGIC------------------------
+
+    private boolean isUidEnumeration() {
+        return mUids != null;
+    }
+
+    private boolean hasNextUid() {
+        return isUidEnumeration() && (mUidOrUidIndex + 1) < mUids.length;
+    }
+
+    private int getUid() {
+        // Check if uid enumeration.
+        if (isUidEnumeration()) {
+            if (mUidOrUidIndex < 0 || mUidOrUidIndex >= mUids.length) {
+                throw new IndexOutOfBoundsException(
+                        "Index=" + mUidOrUidIndex + " mUids.length=" + mUids.length);
+            }
+            return mUids[mUidOrUidIndex];
+        }
+        // Single uid mode.
+        return mUidOrUidIndex;
+    }
+
+    private void setSingleUid(int uid) {
+        mUidOrUidIndex = uid;
+    }
+
+    private void setUidEnumeration(int[] uids) {
+        mUids = uids;
+        mUidOrUidIndex = -1;
+    }
+
+    private void stepUid() {
+        if (mUids != null) {
+            ++mUidOrUidIndex;
+        }
+    }
+}
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 0122069..8b3fc2e 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -57,4 +57,41 @@
      * Prepares the UsageStatsService for shutdown.
      */
     public abstract void prepareShutdown();
+
+    /**
+     * Returns true if the app has not been used for a certain amount of time. How much time?
+     * Could be hours, could be days, who knows?
+     *
+     * @param packageName
+     * @param userId
+     * @return
+     */
+    public abstract boolean isAppIdle(String packageName, int userId);
+
+    /**
+     * Returns the most recent time that the specified package was active for the given user.
+     * @param packageName The package to search.
+     * @param userId The user id of the user of interest.
+     * @return The timestamp of when the package was last used, or -1 if it hasn't been used.
+     */
+    public abstract long getLastPackageAccessTime(String packageName, int userId);
+
+    /**
+     * Sets up a listener for changes to packages being accessed.
+     * @param listener A listener within the system process.
+     */
+    public abstract void addAppIdleStateChangeListener(
+            AppIdleStateChangeListener listener);
+
+    /**
+     * Removes a listener that was previously added for package usage state changes.
+     * @param listener The listener within the system process to remove.
+     */
+    public abstract void removeAppIdleStateChangeListener(
+            AppIdleStateChangeListener listener);
+
+    public interface AppIdleStateChangeListener {
+        void onAppIdleStateChanged(String packageName, int userId, boolean idle);
+    }
+
 }
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index be26eac..edb768d0 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
 import android.bluetooth.le.BluetoothLeAdvertiser;
 import android.bluetooth.le.BluetoothLeScanner;
 import android.bluetooth.le.ScanCallback;
@@ -206,6 +207,23 @@
             "android.bluetooth.adapter.action.REQUEST_ENABLE";
 
     /**
+     * Activity Action: Show a system activity that allows user to enable BLE scans even when
+     * Bluetooth is turned off.<p>
+     *
+     * Notification of result of this activity is posted using
+     * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
+     * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
+     * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
+     * error occurred.
+     *
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
+            "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
+
+    /**
      * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
      * has changed.
      * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
@@ -916,6 +934,22 @@
     }
 
     /**
+     * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
+     *
+     * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
+     * fetch scan results even when Bluetooth is turned off.<p>
+     *
+     * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
+     *
+     * @hide
+     */
+    @SystemApi
+    public boolean isBleScanAlwaysAvailable() {
+        // TODO: implement after Settings UI change.
+        return false;
+    }
+
+    /**
      * Returns whether peripheral mode is supported.
      *
      * @hide
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index 7eae439..0106686 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -25,6 +25,13 @@
  * parameters for the scan.
  */
 public final class ScanSettings implements Parcelable {
+
+    /**
+     * A special Bluetooth LE scan mode. Applications using this scan mode will passively listen for
+     * other scan results without starting BLE scans themselves.
+     */
+    public static final int SCAN_MODE_OPPORTUNISTIC = -1;
+
     /**
      * Perform Bluetooth LE scan in low power mode. This is the default scan mode as it consumes the
      * least power.
@@ -177,7 +184,7 @@
          * @throws IllegalArgumentException If the {@code scanMode} is invalid.
          */
         public Builder setScanMode(int scanMode) {
-            if (scanMode < SCAN_MODE_LOW_POWER || scanMode > SCAN_MODE_LOW_LATENCY) {
+            if (scanMode < SCAN_MODE_OPPORTUNISTIC || scanMode > SCAN_MODE_LOW_LATENCY) {
                 throw new IllegalArgumentException("invalid scan mode " + scanMode);
             }
             mScanMode = scanMode;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 39a70be..9450dce 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.AttrRes;
 import android.annotation.CheckResult;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -474,8 +475,7 @@
      *
      * @see android.content.res.Resources.Theme#obtainStyledAttributes(int[])
      */
-    public final TypedArray obtainStyledAttributes(
-            int[] attrs) {
+    public final TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) {
         return getTheme().obtainStyledAttributes(attrs);
     }
 
@@ -487,7 +487,7 @@
      * @see android.content.res.Resources.Theme#obtainStyledAttributes(int, int[])
      */
     public final TypedArray obtainStyledAttributes(
-            @StyleableRes int resid, int[] attrs) throws Resources.NotFoundException {
+            @StyleRes int resid, @StyleableRes int[] attrs) throws Resources.NotFoundException {
         return getTheme().obtainStyledAttributes(resid, attrs);
     }
 
@@ -499,7 +499,7 @@
      * @see android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
      */
     public final TypedArray obtainStyledAttributes(
-            AttributeSet set, int[] attrs) {
+            AttributeSet set, @StyleableRes int[] attrs) {
         return getTheme().obtainStyledAttributes(set, attrs, 0, 0);
     }
 
@@ -511,7 +511,8 @@
      * @see android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
      */
     public final TypedArray obtainStyledAttributes(
-            AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
+            AttributeSet set, @StyleableRes int[] attrs, @AttrRes int defStyleAttr,
+            @StyleRes int defStyleRes) {
         return getTheme().obtainStyledAttributes(
             set, attrs, defStyleAttr, defStyleRes);
     }
@@ -2149,7 +2150,7 @@
             CONNECTIVITY_SERVICE,
             //@hide: UPDATE_LOCK_SERVICE,
             //@hide: NETWORKMANAGEMENT_SERVICE,
-            //@hide: NETWORK_STATS_SERVICE,
+            NETWORK_STATS_SERVICE,
             //@hide: NETWORK_POLICY_SERVICE,
             WIFI_SERVICE,
             WIFI_PASSPOINT_SERVICE,
@@ -2259,6 +2260,9 @@
      * <dd> A {@link android.os.BatteryManager} for managing battery state
      * <dt> {@link #JOB_SCHEDULER_SERVICE} ("taskmanager")
      * <dd>  A {@link android.app.job.JobScheduler} for managing scheduled tasks
+     * <dt> {@link #NETWORK_STATS_SERVICE} ("netstats")
+     * <dd> A {@link android.app.usage.NetworkStatsManager NetworkStatsManager} for querying network
+     * usage statistics.
      * </dl>
      *
      * <p>Note:  System services obtained via this API may be closely associated with
@@ -2316,6 +2320,8 @@
      * @see android.os.BatteryManager
      * @see #JOB_SCHEDULER_SERVICE
      * @see android.app.job.JobScheduler
+     * @see #NETWORK_STATS_SERVICE
+     * @see android.app.usage.NetworkStatsManager
      */
     public abstract Object getSystemService(@ServiceName @NonNull String name);
 
@@ -2334,7 +2340,8 @@
      * {@link android.telephony.TelephonyManager}, {@link android.telephony.SubscriptionManager},
      * {@link android.view.inputmethod.InputMethodManager},
      * {@link android.app.UiModeManager}, {@link android.app.DownloadManager},
-     * {@link android.os.BatteryManager}, {@link android.app.job.JobScheduler}.
+     * {@link android.os.BatteryManager}, {@link android.app.job.JobScheduler},
+     * {@link android.app.usage.NetworkStatsManager}.
      * </p><p>
      * Note: System services obtained via this API may be closely associated with
      * the Context in which they are obtained from.  In general, do not share the
@@ -2563,7 +2570,13 @@
      */
     public static final String NETWORKMANAGEMENT_SERVICE = "network_management";
 
-    /** {@hide} */
+    /**
+     * Use with {@link #getSystemService} to retrieve a {@link
+     * android.app.usage.NetworkStatsManager} for querying network usage stats.
+     *
+     * @see #getSystemService
+     * @see android.app.usage.NetworkStatsManager
+     */
     public static final String NETWORK_STATS_SERVICE = "netstats";
     /** {@hide} */
     public static final String NETWORK_POLICY_SERVICE = "netpolicy";
@@ -2819,7 +2832,7 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
-     * {@link android.bluetooth.BluetoothAdapter} for using Bluetooth.
+     * {@link android.bluetooth.BluetoothManager} for using Bluetooth.
      *
      * @see #getSystemService
      */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 9be96a1..eea47b7 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1041,6 +1041,18 @@
      */
     public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
     /**
+     * Activity action: Activate the current SIM card.  If SIM cards do not require activation,
+     * sending this intent is a no-op.
+     * <p>Input: No data should be specified.  get*Extra may have an optional
+     * {@link #EXTRA_SIM_ACTIVATION_RESPONSE} field containing a PendingIntent through which to
+     * send the activation result.
+     * <p>Output: nothing.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_SIM_ACTIVATION_REQUEST =
+            "android.intent.action.SIM_ACTIVATION_REQUEST";
+    /**
      * Activity Action: Send a message to someone specified by the data.
      * <p>Input: {@link #getData} is URI describing the target.
      * <p>Output: nothing.
@@ -1502,6 +1514,66 @@
      */
     public static final String METADATA_SETUP_VERSION = "android.SETUP_VERSION";
 
+    /**
+     * Activity action: Launch UI to manage the permissions of an app.
+     * <p>
+     * Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose permissions
+     * will be managed by the launched UI.
+     * </p>
+     * <p>
+     * Output: Nothing.
+     * </p>
+     *
+     * @see #EXTRA_PACKAGE_NAME
+     *
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_MANAGE_APP_PERMISSIONS =
+            "android.intent.action.MANAGE_APP_PERMISSIONS";
+
+    /**
+     * Intent extra: An app package name.
+     * <p>
+     * Type: String
+     * </p>S
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
+
+    /**
+     * Activity action: Launch UI to manage which apps have a given permission.
+     * <p>
+     * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission access
+     * to which will be managed by the launched UI.
+     * </p>
+     * <p>
+     * Output: Nothing.
+     * </p>
+     *
+     * @see #EXTRA_PERMISSION_NAME
+     *
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_MANAGE_PERMISSION_APPS =
+            "android.intent.action.MANAGE_PERMISSION_APPS";
+
+    /**
+     * Intent extra: The name of a permission.
+     * <p>
+     * Type: String
+     * </p>
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent broadcast actions (see action variable).
@@ -1851,6 +1923,19 @@
     public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
 
     /**
+     * Broadcast Action: Sent to the system intent filter verifier when an intent filter
+     * needs to be verified. The data contains the filter data hosts to be verified against.
+     * <p class="note">
+     * This is a protected intent that can only be sent by the system.
+     * </p>
+     *
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
+
+    /**
      * Broadcast Action: Resources for a set of packages (which were
      * previously unavailable) are currently
      * available since the media on which they exist is available.
@@ -2823,6 +2908,24 @@
     /** {@hide} */
     public static final String EXTRA_SETTING_NEW_VALUE = "new_value";
 
+    /**
+     * Activity Action: Process a piece of text.
+     * <p>Input: {@link #EXTRA_PROCESS_TEXT} contains the text to be processed.
+     * {@link #EXTRA_PROCESS_TEXT_READONLY} states if the resulting text will be read-only.</p>
+     * <p>Output: {@link #EXTRA_PROCESS_TEXT} contains the processed text.</p>
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_PROCESS_TEXT = "android.intent.action.PROCESS_TEXT";
+    /**
+     * The name of the extra used to define the text to be processed.
+     */
+    public static final String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
+    /**
+     * The name of the extra used to define if the processed text will be used as read-only.
+     */
+    public static final String EXTRA_PROCESS_TEXT_READONLY =
+            "android.intent.extra.PROCESS_TEXT_READONLY";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent categories (see addCategory()).
@@ -3547,6 +3650,15 @@
     /** {@hide} */
     public static final String EXTRA_REASON = "android.intent.extra.REASON";
 
+    /**
+     * Optional {@link android.app.PendingIntent} extra used to deliver the result of the SIM
+     * activation request.
+     * TODO: Add information about the structure and response data used with the pending intent.
+     * @hide
+     */
+    public static final String EXTRA_SIM_ACTIVATION_RESPONSE =
+            "android.intent.extra.SIM_ACTIVATION_RESPONSE";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Intent flags (see mFlags variable).
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 1240a23..590d791 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -16,10 +16,12 @@
 
 package android.content;
 
+import android.content.pm.PackageParser;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PatternMatcher;
+import android.text.TextUtils;
 import android.util.AndroidException;
 import android.util.Log;
 import android.util.Printer;
@@ -150,6 +152,7 @@
     private static final String CAT_STR = "cat";
     private static final String NAME_STR = "name";
     private static final String ACTION_STR = "action";
+    private static final String AUTO_VERIFY_STR = "autoVerify";
 
     /**
      * The filter {@link #setPriority} value at which system high-priority
@@ -247,6 +250,19 @@
      */
     public static final int NO_MATCH_CATEGORY = -4;
 
+    /**
+     * HTTP scheme.
+     *
+     * @see #addDataScheme(String)
+     */
+    public static final String SCHEME_HTTP = "http";
+    /**
+     * HTTPS scheme.
+     *
+     * @see #addDataScheme(String)
+     */
+    public static final String SCHEME_HTTPS = "https";
+
     private int mPriority;
     private final ArrayList<String> mActions;
     private ArrayList<String> mCategories = null;
@@ -257,6 +273,13 @@
     private ArrayList<String> mDataTypes = null;
     private boolean mHasPartialTypes = false;
 
+    private static final int STATE_VERIFY_AUTO         = 0x00000001;
+    private static final int STATE_NEED_VERIFY         = 0x00000010;
+    private static final int STATE_NEED_VERIFY_CHECKED = 0x00000100;
+    private static final int STATE_VERIFIED            = 0x00001000;
+
+    private int mVerifyState;
+
     // These functions are the start of more optimized code for managing
     // the string sets...  not yet implemented.
 
@@ -326,7 +349,7 @@
         public MalformedMimeTypeException(String name) {
             super(name);
         }
-    };
+    }
 
     /**
      * Create a new IntentFilter instance with a specified action and MIME
@@ -421,6 +444,7 @@
             mDataPaths = new ArrayList<PatternMatcher>(o.mDataPaths);
         }
         mHasPartialTypes = o.mHasPartialTypes;
+        mVerifyState = o.mVerifyState;
     }
 
     /**
@@ -452,6 +476,94 @@
     }
 
     /**
+     * Set whether this filter will needs to be automatically verified against its data URIs or not.
+     * The default is false.
+     *
+     * The verification would need to happen only and only if the Intent action is
+     * {@link android.content.Intent#ACTION_VIEW} and the Intent category is
+     * {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent data scheme
+     * is "http" or "https".
+     *
+     * True means that the filter will need to use its data URIs to be verified.
+     *
+     * @param autoVerify The new autoVerify value.
+     *
+     * @see #getAutoVerify()
+     * @see #addAction(String)
+     * @see #getAction(int)
+     * @see #addCategory(String)
+     * @see #getCategory(int)
+     * @see #addDataScheme(String)
+     * @see #getDataScheme(int)
+     *
+     * @hide
+     */
+    public final void setAutoVerify(boolean autoVerify) {
+        mVerifyState &= ~STATE_VERIFY_AUTO;
+        if (autoVerify) mVerifyState |= STATE_VERIFY_AUTO;
+    }
+
+    /**
+     * Return if this filter will needs to be automatically verified again its data URIs or not.
+     *
+     * @return True if the filter will needs to be automatically verified. False otherwise.
+     *
+     * @see #setAutoVerify(boolean)
+     *
+     * @hide
+     */
+    public final boolean getAutoVerify() {
+        return ((mVerifyState & STATE_VERIFY_AUTO) == 1);
+    }
+
+    /**
+     * Return if this filter needs to be automatically verified again its data URIs or not.
+     *
+     * @return True if the filter needs to be automatically verified. False otherwise.
+     *
+     * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
+     * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
+     * data scheme is "http" or "https".
+     *
+     * @see #setAutoVerify(boolean)
+     *
+     * @hide
+     */
+    public final boolean needsVerification() {
+        return hasAction(Intent.ACTION_VIEW) &&
+                hasCategory(Intent.CATEGORY_BROWSABLE) &&
+                (hasDataScheme(SCHEME_HTTP) || hasDataScheme(SCHEME_HTTPS)) &&
+                getAutoVerify();
+    }
+
+    /**
+     * Return if this filter has been verified
+     *
+     * @return true if the filter has been verified or if autoVerify is false.
+     *
+     * @hide
+     */
+    public final boolean isVerified() {
+        if ((mVerifyState & STATE_NEED_VERIFY_CHECKED) == STATE_NEED_VERIFY_CHECKED) {
+            return ((mVerifyState & STATE_NEED_VERIFY) == STATE_NEED_VERIFY);
+        }
+        return false;
+    }
+
+    /**
+     * Set if this filter has been verified
+     *
+     * @param verified true if this filter has been verified. False otherwise.
+     *
+     * @hide
+     */
+    public void setVerified(boolean verified) {
+        mVerifyState |= STATE_NEED_VERIFY_CHECKED;
+        mVerifyState &= ~STATE_VERIFIED;
+        if (verified) mVerifyState |= STATE_VERIFIED;
+    }
+
+    /**
      * Add a new Intent action to match against.  If any actions are included
      * in the filter, then an Intent's action must be one of those values for
      * it to match.  If no actions are included, the Intent action is ignored.
@@ -1333,6 +1445,7 @@
      * Write the contents of the IntentFilter as an XML stream.
      */
     public void writeToXml(XmlSerializer serializer) throws IOException {
+        serializer.attribute(null, AUTO_VERIFY_STR, Boolean.toString(getAutoVerify()));
         int N = countActions();
         for (int i=0; i<N; i++) {
             serializer.startTag(null, ACTION_STR);
@@ -1407,6 +1520,9 @@
 
     public void readFromXml(XmlPullParser parser) throws XmlPullParserException,
             IOException {
+        String autoVerify = parser.getAttributeValue(null, AUTO_VERIFY_STR);
+        setAutoVerify(TextUtils.isEmpty(autoVerify) ? false : Boolean.getBoolean(autoVerify));
+
         int outerDepth = parser.getDepth();
         int type;
         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1548,6 +1664,11 @@
                     sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes);
             du.println(sb.toString());
         }
+        {
+            sb.setLength(0);
+            sb.append(prefix); sb.append("AutoVerify="); sb.append(getAutoVerify());
+            du.println(sb.toString());
+        }
     }
 
     public static final Parcelable.Creator<IntentFilter> CREATOR
@@ -1614,6 +1735,7 @@
         }
         dest.writeInt(mPriority);
         dest.writeInt(mHasPartialTypes ? 1 : 0);
+        dest.writeInt(getAutoVerify() ? 1 : 0);
     }
 
     /**
@@ -1680,6 +1802,7 @@
         }
         mPriority = source.readInt();
         mHasPartialTypes = source.readInt() > 0;
+        setAutoVerify(source.readInt() > 0);
     }
 
     private final boolean findMimeType(String type) {
@@ -1724,4 +1847,27 @@
 
         return false;
     }
+
+    /**
+     * @hide
+     */
+    public ArrayList<String> getHostsList() {
+        ArrayList<String> result = new ArrayList<>();
+        Iterator<IntentFilter.AuthorityEntry> it = authoritiesIterator();
+        if (it != null) {
+            while (it.hasNext()) {
+                IntentFilter.AuthorityEntry entry = it.next();
+                result.add(entry.getHost());
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @hide
+     */
+    public String[] getHosts() {
+        ArrayList<String> list = getHostsList();
+        return list.toArray(new String[list.size()]);
+    }
 }
diff --git a/core/java/android/content/RestrictionEntry.java b/core/java/android/content/RestrictionEntry.java
index 6d79626..342ee38 100644
--- a/core/java/android/content/RestrictionEntry.java
+++ b/core/java/android/content/RestrictionEntry.java
@@ -20,6 +20,9 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 /**
  * Applications can expose restrictions for a restricted user on a
  * multiuser device. The administrator can configure these restrictions that will then be
@@ -33,19 +36,19 @@
 public class RestrictionEntry implements Parcelable {
 
     /**
-     * A type of restriction. Use this type for information that needs to be transferred across
-     * but shouldn't be presented to the user in the UI. Stores a single String value.
+     * Hidden restriction type. Use this type for information that needs to be transferred
+     * across but shouldn't be presented to the user in the UI. Stores a single String value.
      */
     public static final int TYPE_NULL         = 0;
 
     /**
-     * A type of restriction. Use this for storing a boolean value, typically presented as
+     * Restriction of type "bool". Use this for storing a boolean value, typically presented as
      * a checkbox in the UI.
      */
     public static final int TYPE_BOOLEAN      = 1;
 
     /**
-     * A type of restriction. Use this for storing a string value, typically presented as
+     * Restriction of type "choice". Use this for storing a string value, typically presented as
      * a single-select list. Call {@link #setChoiceEntries(String[])} and
      * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user
      * and the corresponding values, respectively.
@@ -53,7 +56,7 @@
     public static final int TYPE_CHOICE       = 2;
 
     /**
-     * A type of restriction. Use this for storing a string value, typically presented as
+     * Internal restriction type. Use this for storing a string value, typically presented as
      * a single-select list. Call {@link #setChoiceEntries(String[])} and
      * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user
      * and the corresponding values, respectively.
@@ -64,8 +67,8 @@
     public static final int TYPE_CHOICE_LEVEL = 3;
 
     /**
-     * A type of restriction. Use this for presenting a multi-select list where more than one
-     * entry can be selected, such as for choosing specific titles to white-list.
+     * Restriction of type "multi-select". Use this for presenting a multi-select list where more
+     * than one entry can be selected, such as for choosing specific titles to white-list.
      * Call {@link #setChoiceEntries(String[])} and
      * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user
      * and the corresponding values, respectively.
@@ -75,18 +78,30 @@
     public static final int TYPE_MULTI_SELECT = 4;
 
     /**
-     * A type of restriction. Use this for storing an integer value. The range of values
+     * Restriction of type "integer". Use this for storing an integer value. The range of values
      * is from {@link Integer#MIN_VALUE} to {@link Integer#MAX_VALUE}.
      */
     public static final int TYPE_INTEGER = 5;
 
     /**
-     * A type of restriction. Use this for storing a string value.
+     * Restriction of type "string". Use this for storing a string value.
      * @see #setSelectedString
      * @see #getSelectedString
      */
     public static final int TYPE_STRING = 6;
 
+    /**
+     * Restriction of type "bundle". Use this for storing {@link android.os.Bundle bundles} of
+     * restrictions
+     */
+    public static final int TYPE_BUNDLE = 7;
+
+    /**
+     * Restriction of type "bundle_array". Use this for storing arrays of
+     * {@link android.os.Bundle bundles} of restrictions
+     */
+    public static final int TYPE_BUNDLE_ARRAY = 8;
+
     /** The type of restriction. */
     private int mType;
 
@@ -100,13 +115,13 @@
     private String mDescription;
 
     /** The user-visible set of choices used for single-select and multi-select lists. */
-    private String [] mChoiceEntries;
+    private String[] mChoiceEntries;
 
     /** The values corresponding to the user-visible choices. The value(s) of this entry will
      * one or more of these, returned by {@link #getAllSelectedStrings()} and
      * {@link #getSelectedString()}.
      */
-    private String [] mChoiceValues;
+    private String[] mChoiceValues;
 
     /* The chosen value, whose content depends on the type of the restriction. */
     private String mCurrentValue;
@@ -115,6 +130,12 @@
     private String[] mCurrentValues;
 
     /**
+     * List of nested restrictions. Used by {@link #TYPE_BUNDLE bundle} and
+     * {@link #TYPE_BUNDLE_ARRAY bundle_array} restrictions.
+     */
+    private RestrictionEntry[] mRestrictions;
+
+    /**
      * Constructor for specifying the type and key, with no initial value;
      *
      * @param type the restriction type.
@@ -170,6 +191,35 @@
     }
 
     /**
+     * Constructor for {@link #TYPE_BUNDLE}/{@link #TYPE_BUNDLE_ARRAY} type.
+     * @param key the unique key for this restriction
+     * @param restrictionEntries array of nested restriction entries. If the entry, being created
+     * represents a {@link #TYPE_BUNDLE_ARRAY bundle-array}, {@code restrictionEntries} array may
+     * only contain elements of type {@link #TYPE_BUNDLE bundle}.
+     * @param isBundleArray true if this restriction represents
+     * {@link #TYPE_BUNDLE_ARRAY bundle-array} type, otherwise the type will be set to
+     * {@link #TYPE_BUNDLE bundle}.
+     */
+    public RestrictionEntry(String key, RestrictionEntry[] restrictionEntries,
+            boolean isBundleArray) {
+        mKey = key;
+        if (isBundleArray) {
+            mType = TYPE_BUNDLE_ARRAY;
+            if (restrictionEntries != null) {
+                for (RestrictionEntry restriction : restrictionEntries) {
+                    if (restriction.getType() != TYPE_BUNDLE) {
+                        throw new IllegalArgumentException("bundle_array restriction can only have "
+                                + "nested restriction entries of type bundle");
+                    }
+                }
+            }
+        } else {
+            mType = TYPE_BUNDLE;
+        }
+        setRestrictions(restrictionEntries);
+    }
+
+    /**
      * Sets the type for this restriction.
      * @param type the type for this restriction.
      */
@@ -283,6 +333,22 @@
     }
 
     /**
+     * Returns array of possible restriction entries that this entry may contain.
+     */
+    public RestrictionEntry[] getRestrictions() {
+        return mRestrictions;
+    }
+
+   /**
+    * Sets an array of possible restriction entries, that this entry may contain.
+    * <p>This method is only relevant for types {@link #TYPE_BUNDLE} and
+    * {@link #TYPE_BUNDLE_ARRAY}
+    */
+    public void setRestrictions(RestrictionEntry[] restrictions) {
+        mRestrictions = restrictions;
+    }
+
+    /**
      * Returns the list of possible string values set earlier.
      * @return the list of possible values.
      */
@@ -362,27 +428,30 @@
         this.mTitle = title;
     }
 
-    private boolean equalArrays(String[] one, String[] other) {
-        if (one.length != other.length) return false;
-        for (int i = 0; i < one.length; i++) {
-            if (!one[i].equals(other[i])) return false;
-        }
-        return true;
-    }
-
     @Override
     public boolean equals(Object o) {
         if (o == this) return true;
         if (!(o instanceof RestrictionEntry)) return false;
         final RestrictionEntry other = (RestrictionEntry) o;
-        // Make sure that either currentValue matches or currentValues matches.
-        return mType == other.mType && mKey.equals(other.mKey)
-                &&
-                ((mCurrentValues == null && other.mCurrentValues == null
-                  && mCurrentValue != null && mCurrentValue.equals(other.mCurrentValue))
-                 ||
-                 (mCurrentValue == null && other.mCurrentValue == null
-                  && mCurrentValues != null && equalArrays(mCurrentValues, other.mCurrentValues)));
+        if (mType != other.mType || mKey.equals(other.mKey)) {
+            return false;
+        }
+        if (mCurrentValues == null && other.mCurrentValues == null
+                && mRestrictions == null && other.mRestrictions == null
+                && Objects.equals(mCurrentValue, other.mCurrentValue)) {
+            return true;
+        }
+        if (mCurrentValue == null && other.mCurrentValue == null
+                && mRestrictions == null && other.mRestrictions == null
+                && Arrays.equals(mCurrentValues, other.mCurrentValues)) {
+            return true;
+        }
+        if (mCurrentValue == null && other.mCurrentValue == null
+                && mCurrentValue == null && other.mCurrentValue == null
+                && Arrays.equals(mRestrictions, other.mRestrictions)) {
+            return true;
+        }
+        return false;
     }
 
     @Override
@@ -397,28 +466,28 @@
                     result = 31 * result + value.hashCode();
                 }
             }
+        } else if (mRestrictions != null) {
+            result = 31 * result + Arrays.hashCode(mRestrictions);
         }
         return result;
     }
 
-    private String[] readArray(Parcel in) {
-        int count = in.readInt();
-        String[] values = new String[count];
-        for (int i = 0; i < count; i++) {
-            values[i] = in.readString();
-        }
-        return values;
-    }
-
     public RestrictionEntry(Parcel in) {
         mType = in.readInt();
         mKey = in.readString();
         mTitle = in.readString();
         mDescription = in.readString();
-        mChoiceEntries = readArray(in);
-        mChoiceValues = readArray(in);
+        mChoiceEntries = in.readStringArray();
+        mChoiceValues = in.readStringArray();
         mCurrentValue = in.readString();
-        mCurrentValues = readArray(in);
+        mCurrentValues = in.readStringArray();
+        Parcelable[] parcelables = in.readParcelableArray(null);
+        if (parcelables != null) {
+            mRestrictions = new RestrictionEntry[parcelables.length];
+            for (int i = 0; i < parcelables.length; i++) {
+                mRestrictions[i] = (RestrictionEntry) parcelables[i];
+            }
+        }
     }
 
     @Override
@@ -426,27 +495,17 @@
         return 0;
     }
 
-    private void writeArray(Parcel dest, String[] values) {
-        if (values == null) {
-            dest.writeInt(0);
-        } else {
-            dest.writeInt(values.length);
-            for (int i = 0; i < values.length; i++) {
-                dest.writeString(values[i]);
-            }
-        }
-    }
-
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mType);
         dest.writeString(mKey);
         dest.writeString(mTitle);
         dest.writeString(mDescription);
-        writeArray(dest, mChoiceEntries);
-        writeArray(dest, mChoiceValues);
+        dest.writeStringArray(mChoiceEntries);
+        dest.writeStringArray(mChoiceValues);
         dest.writeString(mCurrentValue);
-        writeArray(dest, mCurrentValues);
+        dest.writeStringArray(mCurrentValues);
+        dest.writeParcelableArray(mRestrictions, 0);
     }
 
     public static final Creator<RestrictionEntry> CREATOR = new Creator<RestrictionEntry>() {
@@ -461,6 +520,16 @@
 
     @Override
     public String toString() {
-        return "RestrictionsEntry {type=" + mType + ", key=" + mKey + ", value=" + mCurrentValue + "}";
+        return "RestrictionEntry{" +
+                "mType=" + mType +
+                ", mKey='" + mKey + '\'' +
+                ", mTitle='" + mTitle + '\'' +
+                ", mDescription='" + mDescription + '\'' +
+                ", mChoiceEntries=" + Arrays.toString(mChoiceEntries) +
+                ", mChoiceValues=" + Arrays.toString(mChoiceValues) +
+                ", mCurrentValue='" + mCurrentValue + '\'' +
+                ", mCurrentValues=" + Arrays.toString(mCurrentValues) +
+                ", mRestrictions=" + Arrays.toString(mRestrictions) +
+                '}';
     }
 }
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index 21a6a0d..1fac06e 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -32,12 +32,14 @@
 import android.util.Xml;
 
 import com.android.internal.R;
+import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -71,12 +73,15 @@
  *         android:key="string"
  *         android:title="string resource"
  *         android:restrictionType=["bool" | "string" | "integer"
- *                                         | "choice" | "multi-select" | "hidden"]
+ *                                         | "choice" | "multi-select" | "hidden"
+ *                                         | "bundle" | "bundle_array"]
  *         android:description="string resource"
  *         android:entries="string-array resource"
  *         android:entryValues="string-array resource"
- *         android:defaultValue="reference"
- *         /&gt;
+ *         android:defaultValue="reference" &gt;
+ *             &lt;restriction ... /&gt;
+ *             ...
+ *     &lt;/restriction&gt;
  *     &lt;restriction ... /&gt;
  *     ...
  * &lt;/restrictions&gt;
@@ -97,6 +102,9 @@
  * administrator controlling the values, if the title is not sufficient.</li>
  * </ul>
  * <p>
+ * Only restrictions of type {@code bundle} and {@code bundle_array} can have one or multiple nested
+ * restriction elements.
+ * <p>
  * In your manifest's <code>application</code> section, add the meta-data tag to point to
  * the restrictions XML file as shown below:
  * <pre>
@@ -537,9 +545,7 @@
 
         XmlResourceParser xml =
                 appInfo.loadXmlMetaData(mContext.getPackageManager(), META_DATA_APP_RESTRICTIONS);
-        List<RestrictionEntry> restrictions = loadManifestRestrictions(packageName, xml);
-
-        return restrictions;
+        return loadManifestRestrictions(packageName, xml);
     }
 
     private List<RestrictionEntry> loadManifestRestrictions(String packageName,
@@ -550,23 +556,16 @@
         } catch (NameNotFoundException nnfe) {
             return null;
         }
-        ArrayList<RestrictionEntry> restrictions = new ArrayList<RestrictionEntry>();
+        ArrayList<RestrictionEntry> restrictions = new ArrayList<>();
         RestrictionEntry restriction;
 
         try {
             int tagType = xml.next();
             while (tagType != XmlPullParser.END_DOCUMENT) {
                 if (tagType == XmlPullParser.START_TAG) {
-                    if (xml.getName().equals(TAG_RESTRICTION)) {
-                        AttributeSet attrSet = Xml.asAttributeSet(xml);
-                        if (attrSet != null) {
-                            TypedArray a = appContext.obtainStyledAttributes(attrSet,
-                                    com.android.internal.R.styleable.RestrictionEntry);
-                            restriction = loadRestriction(appContext, a);
-                            if (restriction != null) {
-                                restrictions.add(restriction);
-                            }
-                        }
+                    restriction = loadRestrictionElement(appContext, xml);
+                    if (restriction != null) {
+                        restrictions.add(restriction);
                     }
                 }
                 tagType = xml.next();
@@ -582,7 +581,21 @@
         return restrictions;
     }
 
-    private RestrictionEntry loadRestriction(Context appContext, TypedArray a) {
+    private RestrictionEntry loadRestrictionElement(Context appContext, XmlResourceParser xml)
+            throws IOException, XmlPullParserException {
+        if (xml.getName().equals(TAG_RESTRICTION)) {
+            AttributeSet attrSet = Xml.asAttributeSet(xml);
+            if (attrSet != null) {
+                TypedArray a = appContext.obtainStyledAttributes(attrSet,
+                        com.android.internal.R.styleable.RestrictionEntry);
+                return loadRestriction(appContext, a, xml);
+            }
+        }
+        return null;
+    }
+
+    private RestrictionEntry loadRestriction(Context appContext, TypedArray a, XmlResourceParser xml)
+            throws IOException, XmlPullParserException {
         String key = a.getString(R.styleable.RestrictionEntry_key);
         int restrictionType = a.getInt(
                 R.styleable.RestrictionEntry_restrictionType, -1);
@@ -633,9 +646,90 @@
                 restriction.setSelectedState(
                         a.getBoolean(R.styleable.RestrictionEntry_defaultValue, false));
                 break;
+            case RestrictionEntry.TYPE_BUNDLE:
+            case RestrictionEntry.TYPE_BUNDLE_ARRAY:
+                final int outerDepth = xml.getDepth();
+                List<RestrictionEntry> restrictionEntries = new ArrayList<>();
+                while (XmlUtils.nextElementWithin(xml, outerDepth)) {
+                    RestrictionEntry childEntry = loadRestrictionElement(appContext, xml);
+                    if (childEntry == null) {
+                        Log.w(TAG, "Child entry cannot be loaded for bundle restriction " + key);
+                    } else {
+                        restrictionEntries.add(childEntry);
+                        if (restrictionType == RestrictionEntry.TYPE_BUNDLE_ARRAY
+                                && childEntry.getType() != RestrictionEntry.TYPE_BUNDLE) {
+                            Log.w(TAG, "bundle_array " + key
+                                    + " can only contain entries of type bundle");
+                        }
+                    }
+                }
+                restriction.setRestrictions(restrictionEntries.toArray(new RestrictionEntry[
+                        restrictionEntries.size()]));
+                break;
             default:
                 Log.w(TAG, "Unknown restriction type " + restrictionType);
         }
         return restriction;
     }
+
+    /**
+     * Converts a list of restrictions to the corresponding bundle, using the following mapping:
+     * <table>
+     *     <tr><th>RestrictionEntry</th><th>Bundle</th></tr>
+     *     <tr><td>{@link RestrictionEntry#TYPE_BOOLEAN}</td><td>{@link Bundle#putBoolean}</td></tr>
+     *     <tr><td>{@link RestrictionEntry#TYPE_CHOICE}, {@link RestrictionEntry#TYPE_CHOICE}</td>
+     *     <td>{@link Bundle#putStringArray}</td></tr>
+     *     <tr><td>{@link RestrictionEntry#TYPE_INTEGER}</td><td>{@link Bundle#putInt}</td></tr>
+     *     <tr><td>{@link RestrictionEntry#TYPE_STRING}</td><td>{@link Bundle#putString}</td></tr>
+     *     <tr><td>{@link RestrictionEntry#TYPE_BUNDLE}</td><td>{@link Bundle#putBundle}</td></tr>
+     *     <tr><td>{@link RestrictionEntry#TYPE_BUNDLE_ARRAY}</td>
+     *     <td>{@link Bundle#putParcelableArray}</td></tr>
+     * </table>
+     * @param entries list of restrictions
+     */
+    public static Bundle convertRestrictionsToBundle(List<RestrictionEntry> entries) {
+        final Bundle bundle = new Bundle();
+        for (RestrictionEntry entry : entries) {
+            addRestrictionToBundle(bundle, entry);
+        }
+        return bundle;
+    }
+
+    private static Bundle addRestrictionToBundle(Bundle bundle, RestrictionEntry entry) {
+        switch (entry.getType()) {
+            case RestrictionEntry.TYPE_BOOLEAN:
+                bundle.putBoolean(entry.getKey(), entry.getSelectedState());
+                break;
+            case RestrictionEntry.TYPE_CHOICE:
+            case RestrictionEntry.TYPE_CHOICE_LEVEL:
+            case RestrictionEntry.TYPE_MULTI_SELECT:
+                bundle.putStringArray(entry.getKey(), entry.getAllSelectedStrings());
+                break;
+            case RestrictionEntry.TYPE_INTEGER:
+                bundle.putInt(entry.getKey(), entry.getIntValue());
+                break;
+            case RestrictionEntry.TYPE_STRING:
+            case RestrictionEntry.TYPE_NULL:
+                bundle.putString(entry.getKey(), entry.getSelectedString());
+                break;
+            case RestrictionEntry.TYPE_BUNDLE:
+                RestrictionEntry[] restrictions = entry.getRestrictions();
+                Bundle childBundle = convertRestrictionsToBundle(Arrays.asList(restrictions));
+                bundle.putBundle(entry.getKey(), childBundle);
+                break;
+            case RestrictionEntry.TYPE_BUNDLE_ARRAY:
+                restrictions = entry.getRestrictions();
+                Bundle[] bundleArray = new Bundle[restrictions.length];
+                for (int i = 0; i < restrictions.length; i++) {
+                    bundleArray[i] = addRestrictionToBundle(new Bundle(), restrictions[i]);
+                }
+                bundle.putParcelableArray(entry.getKey(), bundleArray);
+                break;
+            default:
+                throw new IllegalArgumentException(
+                        "Unsupported restrictionEntry type: " + entry.getType());
+        }
+        return bundle;
+    }
+
 }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 8f17845..5bdb7bb 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -340,8 +340,6 @@
      * cleartext network traffic, in which case platform components (e.g., HTTP stacks,
      * {@code WebView}, {@code MediaPlayer}) will refuse app's requests to use cleartext traffic.
      * Third-party libraries are encouraged to honor this flag as well.
-     *
-     * @hide
      */
     public static final int FLAG_USES_CLEARTEXT_TRAFFIC = 1<<27;
 
@@ -379,7 +377,8 @@
      * {@link #FLAG_LARGE_HEAP}, {@link #FLAG_STOPPED},
      * {@link #FLAG_SUPPORTS_RTL}, {@link #FLAG_INSTALLED},
      * {@link #FLAG_IS_DATA_ONLY}, {@link #FLAG_IS_GAME},
-     * {@link #FLAG_FULL_BACKUP_ONLY}, {@link #FLAG_MULTIARCH}.
+     * {@link #FLAG_FULL_BACKUP_ONLY}, {@link #FLAG_USES_CLEARTEXT_TRAFFIC},
+     * {@link #FLAG_MULTIARCH}.
      */
     public int flags = 0;
 
@@ -422,6 +421,14 @@
     public static final int PRIVATE_FLAG_PRIVILEGED = 1<<3;
 
     /**
+     * Value for {@link #flags}: {@code true} if the application has any IntentFiler with some
+     * data URI using HTTP or HTTPS with an associated VIEW action.
+     *
+     * {@hide}
+     */
+    public static final int PRIVATE_FLAG_HAS_DOMAIN_URLS = 1<<4;
+
+    /**
      * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
      * {@hide}
      */
@@ -452,6 +459,8 @@
     public int largestWidthLimitDp = 0;
 
     /** {@hide} */
+    public String volumeUuid;
+    /** {@hide} */
     public String scanSourceDir;
     /** {@hide} */
     public String scanPublicSourceDir;
@@ -655,7 +664,7 @@
         }
         pw.println(prefix + "dataDir=" + dataDir);
         if (sharedLibraryFiles != null) {
-            pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
+            pw.println(prefix + "sharedLibraryFiles=" + Arrays.toString(sharedLibraryFiles));
         }
         pw.println(prefix + "enabled=" + enabled + " targetSdkVersion=" + targetSdkVersion
                 + " versionCode=" + versionCode);
@@ -719,6 +728,7 @@
         requiresSmallestWidthDp = orig.requiresSmallestWidthDp;
         compatibleWidthLimitDp = orig.compatibleWidthLimitDp;
         largestWidthLimitDp = orig.largestWidthLimitDp;
+        volumeUuid = orig.volumeUuid;
         scanSourceDir = orig.scanSourceDir;
         scanPublicSourceDir = orig.scanPublicSourceDir;
         sourceDir = orig.sourceDir;
@@ -771,6 +781,7 @@
         dest.writeInt(requiresSmallestWidthDp);
         dest.writeInt(compatibleWidthLimitDp);
         dest.writeInt(largestWidthLimitDp);
+        dest.writeString(volumeUuid);
         dest.writeString(scanSourceDir);
         dest.writeString(scanPublicSourceDir);
         dest.writeString(sourceDir);
@@ -822,6 +833,7 @@
         requiresSmallestWidthDp = source.readInt();
         compatibleWidthLimitDp = source.readInt();
         largestWidthLimitDp = source.readInt();
+        volumeUuid = source.readString();
         scanSourceDir = source.readString();
         scanPublicSourceDir = source.readString();
         sourceDir = source.readString();
@@ -914,6 +926,20 @@
     /**
      * @hide
      */
+    public boolean isSystemApp() {
+        return (flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+    }
+
+    /**
+     * @hide
+     */
+    public boolean isUpdatedSystemApp() {
+        return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
+    }
+
+    /**
+     * @hide
+     */
     @Override protected ApplicationInfo getApplicationInfo() {
         return this;
     }
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index ba62cd6..154ff85 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -44,7 +44,8 @@
     void registerCallback(IPackageInstallerCallback callback, int userId);
     void unregisterCallback(IPackageInstallerCallback callback);
 
-    void uninstall(String packageName, int flags, in IntentSender statusReceiver, int userId);
+    void uninstall(String packageName, String callerPackageName, int flags,
+            in IntentSender statusReceiver, int userId);
 
     void setPermissionsResult(int sessionId, boolean accepted);
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c6d97f1..eed0df5 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -31,6 +31,7 @@
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
+import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.KeySet;
 import android.content.pm.PackageInfo;
@@ -268,6 +269,12 @@
     void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage);
 
     /**
+     * Backup/restore support - only the system uid may use these.
+     */
+    byte[] getPreferredActivityBackup(int userId);
+    void restorePreferredActivities(in byte[] backup, int userId);
+
+    /**
      * Report the set of 'Home' activity candidates, plus (if any) which of them
      * is the current "always use this one" setting.
      */
@@ -425,7 +432,8 @@
     PackageCleanItem nextPackageToClean(in PackageCleanItem lastPackage);
 
     void movePackage(String packageName, IPackageMoveObserver observer, int flags);
-    
+    void movePackageAndData(String packageName, String volumeUuid, IPackageMoveObserver observer);
+
     boolean addPermissionAsync(in PermissionInfo info);
 
     boolean setInstallLocation(int loc);
@@ -436,6 +444,11 @@
     void verifyPendingInstall(int id, int verificationCode);
     void extendVerificationTimeout(int id, int verificationCodeAtTimeout, long millisecondsToDelay);
 
+    void verifyIntentFilter(int id, int verificationCode, in List<String> failedDomains);
+    int getIntentVerificationStatus(String packageName, int userId);
+    boolean updateIntentVerificationStatus(String packageName, int status, int userId);
+    List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName);
+
     VerifierDeviceIdentity getVerifierDeviceIdentity();
 
     boolean isFirstBoot();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/core/java/android/content/pm/IntentFilterVerificationInfo.aidl
similarity index 75%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to core/java/android/content/pm/IntentFilterVerificationInfo.aidl
index 272c321..00220e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/core/java/android/content/pm/IntentFilterVerificationInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+package android.content.pm;
 
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
-}
+parcelable IntentFilterVerificationInfo;
diff --git a/core/java/android/content/pm/IntentFilterVerificationInfo.java b/core/java/android/content/pm/IntentFilterVerificationInfo.java
new file mode 100644
index 0000000..60cb4a8
--- /dev/null
+++ b/core/java/android/content/pm/IntentFilterVerificationInfo.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * The {@link com.android.server.pm.PackageManagerService} maintains some
+ * {@link IntentFilterVerificationInfo}s for each domain / package / class name per user.
+ *
+ * @hide
+ */
+public final class IntentFilterVerificationInfo implements Parcelable {
+    private static final String TAG = IntentFilterVerificationInfo.class.getName();
+
+    private static final String TAG_DOMAIN = "domain";
+    private static final String ATTR_DOMAIN_NAME = "name";
+    private static final String ATTR_PACKAGE_NAME = "packageName";
+    private static final String ATTR_STATUS = "status";
+
+    private String[] mDomains;
+    private String mPackageName;
+    private int mMainStatus;
+
+    public IntentFilterVerificationInfo() {
+        mPackageName = null;
+        mDomains = new String[0];
+        mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+    }
+
+    public IntentFilterVerificationInfo(String packageName, String[] domains) {
+        mPackageName = packageName;
+        mDomains = domains;
+        mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+    }
+
+    public IntentFilterVerificationInfo(XmlPullParser parser)
+            throws IOException, XmlPullParserException {
+        readFromXml(parser);
+    }
+
+    public IntentFilterVerificationInfo(Parcel source) {
+        readFromParcel(source);
+    }
+
+    public String[] getDomains() {
+        return mDomains;
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public int getStatus() {
+        return mMainStatus;
+    }
+
+    public void setStatus(int s) {
+        if (s >= INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED &&
+                s <= INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
+            mMainStatus = s;
+        } else {
+            Log.w(TAG, "Trying to set a non supported status: " + s);
+        }
+    }
+
+    public String getDomainsString() {
+        StringBuilder sb = new StringBuilder();
+        for (String str : mDomains) {
+            if (sb.length() > 0) {
+                sb.append(" ");
+            }
+            sb.append(str);
+        }
+        return sb.toString();
+    }
+
+    String getStringFromXml(XmlPullParser parser, String attribute, String defaultValue) {
+        String value = parser.getAttributeValue(null, attribute);
+        if (value == null) {
+            String msg = "Missing element under " + TAG +": " + attribute + " at " +
+                    parser.getPositionDescription();
+            Log.w(TAG, msg);
+            return defaultValue;
+        } else {
+            return value;
+        }
+    }
+
+    int getIntFromXml(XmlPullParser parser, String attribute, int defaultValue) {
+        String value = parser.getAttributeValue(null, attribute);
+        if (TextUtils.isEmpty(value)) {
+            String msg = "Missing element under " + TAG +": " + attribute + " at " +
+                    parser.getPositionDescription();
+            Log.w(TAG, msg);
+            return defaultValue;
+        } else {
+            return Integer.parseInt(value);
+        }
+    }
+
+    public void readFromXml(XmlPullParser parser) throws XmlPullParserException,
+            IOException {
+        mPackageName = getStringFromXml(parser, ATTR_PACKAGE_NAME, null);
+        if (mPackageName == null) {
+            Log.e(TAG, "Package name cannot be null!");
+        }
+        int status = getIntFromXml(parser, ATTR_STATUS, -1);
+        if (status == -1) {
+            Log.e(TAG, "Unknown status value: " + status);
+        }
+        mMainStatus = status;
+
+        ArrayList<String> list = new ArrayList<>();
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG
+                    || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals(TAG_DOMAIN)) {
+                String name = getStringFromXml(parser, ATTR_DOMAIN_NAME, null);
+                if (!TextUtils.isEmpty(name)) {
+                    if (list == null) {
+                        list = new ArrayList<>();
+                    }
+                    list.add(name);
+                }
+            } else {
+                Log.w(TAG, "Unknown tag parsing IntentFilter: " + tagName);
+            }
+            XmlUtils.skipCurrentTag(parser);
+        }
+
+        mDomains = list.toArray(new String[list.size()]);
+    }
+
+    public void writeToXml(XmlSerializer serializer) throws IOException {
+        serializer.attribute(null, ATTR_PACKAGE_NAME, mPackageName);
+        serializer.attribute(null, ATTR_STATUS, String.valueOf(mMainStatus));
+        for (String str : mDomains) {
+            serializer.startTag(null, TAG_DOMAIN);
+            serializer.attribute(null, ATTR_DOMAIN_NAME, str);
+            serializer.endTag(null, TAG_DOMAIN);
+        }
+    }
+
+    public String getStatusString() {
+        return getStatusStringFromValue(mMainStatus);
+    }
+
+    public static String getStatusStringFromValue(int val) {
+        switch (val) {
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK       : return "ask";
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS    : return "always";
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER     : return "never";
+            default:
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED : return "undefined";
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    private void readFromParcel(Parcel source) {
+        mPackageName = source.readString();
+        mMainStatus = source.readInt();
+        mDomains = source.readStringArray();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mPackageName);
+        dest.writeInt(mMainStatus);
+        dest.writeStringArray(mDomains);
+    }
+
+    public static final Creator<IntentFilterVerificationInfo> CREATOR =
+            new Creator<IntentFilterVerificationInfo>() {
+                public IntentFilterVerificationInfo createFromParcel(Parcel source) {
+                    return new IntentFilterVerificationInfo(source);
+                }
+                public IntentFilterVerificationInfo[] newArray(int size) {
+                    return new IntentFilterVerificationInfo[size];
+                }
+            };
+
+}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 80efd0b..b7ee82d 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -423,7 +423,7 @@
      */
     public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) {
         try {
-            mInstaller.uninstall(packageName, 0, statusReceiver, mUserId);
+            mInstaller.uninstall(packageName, mInstallerPackageName, 0, statusReceiver, mUserId);
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
@@ -887,6 +887,8 @@
         public Uri referrerUri;
         /** {@hide} */
         public String abiOverride;
+        /** {@hide} */
+        public String volumeUuid;
 
         /**
          * Construct parameters for a new package install session.
@@ -911,6 +913,7 @@
             originatingUri = source.readParcelable(null);
             referrerUri = source.readParcelable(null);
             abiOverride = source.readString();
+            volumeUuid = source.readString();
         }
 
         /**
@@ -1008,6 +1011,7 @@
             pw.printPair("originatingUri", originatingUri);
             pw.printPair("referrerUri", referrerUri);
             pw.printPair("abiOverride", abiOverride);
+            pw.printPair("volumeUuid", volumeUuid);
             pw.println();
         }
 
@@ -1028,6 +1032,7 @@
             dest.writeParcelable(originatingUri, flags);
             dest.writeParcelable(referrerUri, flags);
             dest.writeString(abiOverride);
+            dest.writeString(volumeUuid);
         }
 
         public static final Parcelable.Creator<SessionParams>
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 59a16da..4c99d09 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -43,7 +43,9 @@
 import android.os.Environment;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.storage.VolumeInfo;
 import android.util.AndroidException;
+
 import com.android.internal.util.ArrayUtils;
 
 import java.io.File;
@@ -339,15 +341,17 @@
     public static final int INSTALL_ALLOW_TEST = 0x00000004;
 
     /**
-     * Flag parameter for {@link #installPackage} to indicate that this
-     * package has to be installed on the sdcard.
+     * Flag parameter for {@link #installPackage} to indicate that this package
+     * must be installed to an ASEC on a {@link VolumeInfo#TYPE_PUBLIC}.
+     *
      * @hide
      */
     public static final int INSTALL_EXTERNAL = 0x00000008;
 
     /**
      * Flag parameter for {@link #installPackage} to indicate that this package
-     * has to be installed on the sdcard.
+     * must be installed to internal storage.
+     *
      * @hide
      */
     public static final int INSTALL_INTERNAL = 0x00000010;
@@ -969,6 +973,60 @@
     public static final int VERIFICATION_REJECT = -1;
 
     /**
+     * Used as the {@code verificationCode} argument for
+     * {@link PackageManager#verifyIntentFilter} to indicate that the calling
+     * IntentFilter Verifier confirms that the IntentFilter is verified.
+     *
+     * @hide
+     */
+    public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1;
+
+    /**
+     * Used as the {@code verificationCode} argument for
+     * {@link PackageManager#verifyIntentFilter} to indicate that the calling
+     * IntentFilter Verifier confirms that the IntentFilter is NOT verified.
+     *
+     * @hide
+     */
+    public static final int INTENT_FILTER_VERIFICATION_FAILURE = -1;
+
+    /**
+     * Internal status code to indicate that an IntentFilter verification result is not specified.
+     *
+     * @hide
+     */
+    public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED = 0;
+
+    /**
+     * Used as the {@code status} argument for {@link PackageManager#updateIntentVerificationStatus}
+     * to indicate that the User will always be prompted the Intent Disambiguation Dialog if there
+     * are two or more Intent resolved for the IntentFilter's domain(s).
+     *
+     * @hide
+     */
+    public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK = 1;
+
+    /**
+     * Used as the {@code status} argument for {@link PackageManager#updateIntentVerificationStatus}
+     * to indicate that the User will never be prompted the Intent Disambiguation Dialog if there
+     * are two or more resolution of the Intent. The default App for the domain(s) specified in the
+     * IntentFilter will also ALWAYS be used.
+     *
+     * @hide
+     */
+    public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS = 2;
+
+    /**
+     * Used as the {@code status} argument for {@link PackageManager#updateIntentVerificationStatus}
+     * to indicate that the User may be prompted the Intent Disambiguation Dialog if there
+     * are two or more Intent resolved. The default App for the domain(s) specified in the
+     * IntentFilter will also NEVER be presented to the User.
+     *
+     * @hide
+     */
+    public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER = 3;
+
+    /**
      * Can be used as the {@code millisecondsToDelay} argument for
      * {@link PackageManager#extendVerificationTimeout}. This is the
      * maximum time {@code PackageManager} waits for the verification
@@ -1600,6 +1658,12 @@
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_GAMEPAD = "android.hardware.gamepad";
 
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device has a full implementation of the android.media.midi.* APIs.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_MIDI = "android.software.midi";
 
     /**
      * Action to external storage service to clean out removed apps.
@@ -1674,8 +1738,52 @@
             = "android.content.pm.extra.VERIFICATION_VERSION_CODE";
 
     /**
-     * The action used to request that the user approve a grant permissions
-     * request from the application.
+     * Extra field name for the ID of a intent filter pending verification. Passed to
+     * an intent filter verifier and is used to call back to
+     * {@link PackageManager#verifyIntentFilter(int, int)}
+     *
+     * @hide
+     */
+    public static final String EXTRA_INTENT_FILTER_VERIFICATION_ID
+            = "android.content.pm.extra.INTENT_FILTER_VERIFICATION_ID";
+
+    /**
+     * Extra field name for the scheme used for an intent filter pending verification. Passed to
+     * an intent filter verifier and is used to construct the URI to verify against.
+     *
+     * Usually this is "https"
+     *
+     * @hide
+     */
+    public static final String EXTRA_INTENT_FILTER_VERIFICATION_URI_SCHEME
+            = "android.content.pm.extra.INTENT_FILTER_VERIFICATION_URI_SCHEME";
+
+    /**
+     * Extra field name for the host names to be used for an intent filter pending verification.
+     * Passed to an intent filter verifier and is used to construct the URI to verify the
+     * intent filter.
+     *
+     * This is a space delimited list of hosts.
+     *
+     * @hide
+     */
+    public static final String EXTRA_INTENT_FILTER_VERIFICATION_HOSTS
+            = "android.content.pm.extra.INTENT_FILTER_VERIFICATION_HOSTS";
+
+    /**
+     * Extra field name for the package name to be used for an intent filter pending verification.
+     * Passed to an intent filter verifier and is used to check the verification responses coming
+     * from the hosts. Each host response will need to include the package name of APK containing
+     * the intent filter.
+     *
+     * @hide
+     */
+    public static final String EXTRA_INTENT_FILTER_VERIFICATION_PACKAGE_NAME
+            = "android.content.pm.extra.INTENT_FILTER_VERIFICATION_PACKAGE_NAME";
+
+    /**
+     * The action used to request that the user approve a permission request
+     * from the application.
      *
      * @hide
      */
@@ -3455,6 +3563,85 @@
             int verificationCodeAtTimeout, long millisecondsToDelay);
 
     /**
+     * Allows a package listening to the
+     * {@link Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION intent filter verification
+     * broadcast} to respond to the package manager. The response must include
+     * the {@code verificationCode} which is one of
+     * {@link PackageManager#INTENT_FILTER_VERIFICATION_SUCCESS} or
+     * {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}.
+     *
+     * @param verificationId pending package identifier as passed via the
+     *            {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
+     * @param verificationCode either {@link PackageManager#INTENT_FILTER_VERIFICATION_SUCCESS}
+     *            or {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}.
+     * @param outFailedDomains a list of failed domains if the verificationCode is
+     *            {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}, otherwise null;
+     * @throws SecurityException if the caller does not have the
+     *            INTENT_FILTER_VERIFICATION_AGENT permission.
+     *
+     * @hide
+     */
+    public abstract void verifyIntentFilter(int verificationId, int verificationCode,
+            List<String> outFailedDomains);
+
+    /**
+     * Get the status of a Domain Verification Result for an IntentFilter. This is
+     * related to the {@link android.content.IntentFilter#setAutoVerify(boolean)} and
+     * {@link android.content.IntentFilter#getAutoVerify()}
+     *
+     * This is used by the ResolverActivity to change the status depending on what the User select
+     * in the Disambiguation Dialog and also used by the Settings App for changing the default App
+     * for a domain.
+     *
+     * @param packageName The package name of the Activity associated with the IntentFilter.
+     * @param userId The user id.
+     *
+     * @return The status to set to. This can be
+     *              {@link #INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK} or
+     *              {@link #INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS} or
+     *              {@link #INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER} or
+     *              {@link #INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED}
+     *
+     * @hide
+     */
+    public abstract int getIntentVerificationStatus(String packageName, int userId);
+
+    /**
+     * Allow to change the status of a Intent Verification status for all IntentFilter of an App.
+     * This is related to the {@link android.content.IntentFilter#setAutoVerify(boolean)} and
+     * {@link android.content.IntentFilter#getAutoVerify()}
+     *
+     * This is used by the ResolverActivity to change the status depending on what the User select
+     * in the Disambiguation Dialog and also used by the Settings App for changing the default App
+     * for a domain.
+     *
+     * @param packageName The package name of the Activity associated with the IntentFilter.
+     * @param status The status to set to. This can be
+     *              {@link #INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK} or
+     *              {@link #INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS} or
+     *              {@link #INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER}
+     * @param userId The user id.
+     *
+     * @return true if the status has been set. False otherwise.
+     *
+     * @hide
+     */
+    public abstract boolean updateIntentVerificationStatus(String packageName, int status,
+            int userId);
+
+    /**
+     * Get the list of IntentFilterVerificationInfo for a specific package and User.
+     *
+     * @param packageName the package name. When this parameter is set to a non null value,
+     *                    the results will be filtered by the package name provided.
+     *                    Otherwise, there will be no filtering and it will return a list
+     *                    corresponding for all packages for the provided userId.
+     * @return a list of IntentFilterVerificationInfo for a specific package and User.
+     */
+    public abstract List<IntentFilterVerificationInfo> getIntentFilterVerifications(
+            String packageName);
+
+    /**
      * Change the installer associated with a given package.  There are limitations
      * on how the installer package can be changed; in particular:
      * <ul>
@@ -3916,8 +4103,12 @@
      *
      * @hide
      */
-    public abstract void movePackage(
-            String packageName, IPackageMoveObserver observer, int flags);
+    @Deprecated
+    public abstract void movePackage(String packageName, IPackageMoveObserver observer, int flags);
+
+    /** {@hide} */
+    public abstract void movePackageAndData(String packageName, String volumeUuid,
+            IPackageMoveObserver observer);
 
     /**
      * Returns the device identity that verifiers can use to associate their scheme to a particular
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e5859d03..c1e6a4d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -376,16 +376,6 @@
         return path.endsWith(".apk");
     }
 
-    /*
-    public static PackageInfo generatePackageInfo(PackageParser.Package p,
-            int gids[], int flags, long firstInstallTime, long lastUpdateTime,
-            HashSet<String> grantedPermissions) {
-        PackageUserState state = new PackageUserState();
-        return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
-                grantedPermissions, state, UserHandle.getCallingUserId());
-    }
-    */
-
     /**
      * Generate and return the {@link PackageInfo} for a parsed package.
      *
@@ -394,7 +384,7 @@
      */
     public static PackageInfo generatePackageInfo(PackageParser.Package p,
             int gids[], int flags, long firstInstallTime, long lastUpdateTime,
-            ArraySet<String> grantedPermissions, PackageUserState state) {
+            Set<String> grantedPermissions, PackageUserState state) {
 
         return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime,
                 grantedPermissions, state, UserHandle.getCallingUserId());
@@ -574,7 +564,7 @@
                 for (int i=0; i<N; i++) {
                     final String perm = p.requestedPermissions.get(i);
                     pi.requestedPermissions[i] = perm;
-                    // The notion of requried permissions is deprecated but for compatibility.
+                    // The notion of required permissions is deprecated but for compatibility.
                     pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
                     if (grantedPermissions != null && grantedPermissions.contains(perm)) {
                         pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
@@ -614,7 +604,7 @@
     public final static int PARSE_MUST_BE_APK = 1<<2;
     public final static int PARSE_IGNORE_PROCESSES = 1<<3;
     public final static int PARSE_FORWARD_LOCK = 1<<4;
-    public final static int PARSE_ON_SDCARD = 1<<5;
+    public final static int PARSE_EXTERNAL_STORAGE = 1<<5;
     public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
     public final static int PARSE_IS_PRIVILEGED = 1<<7;
     public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
@@ -1418,7 +1408,7 @@
         }
 
         /* Set the global "on SD card" flag */
-        if ((flags & PARSE_ON_SDCARD) != 0) {
+        if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
         }
 
@@ -2760,15 +2750,51 @@
             }
         }
 
-        addSharedLibrariesForBackwardCompatibility(owner);
+        modifySharedLibrariesForBackwardCompatibility(owner);
+
+        if (hasDomainURLs(owner)) {
+            owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+        } else {
+            owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+        }
 
         return true;
     }
 
-    private static void addSharedLibrariesForBackwardCompatibility(Package owner) {
-        if (owner.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
-            owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, "org.apache.http.legacy");
+    private static void modifySharedLibrariesForBackwardCompatibility(Package owner) {
+        // "org.apache.http.legacy" is now a part of the boot classpath so it doesn't need
+        // to be an explicit dependency.
+        //
+        // A future change will remove this library from the boot classpath, at which point
+        // all apps that target SDK 21 and earlier will have it automatically added to their
+        // dependency lists.
+        owner.usesLibraries = ArrayUtils.remove(owner.usesLibraries, "org.apache.http.legacy");
+        owner.usesOptionalLibraries = ArrayUtils.remove(owner.usesOptionalLibraries,
+                "org.apache.http.legacy");
+    }
+
+    /**
+     * Check if one of the IntentFilter as an action VIEW and a HTTP/HTTPS data URI
+     */
+    private static boolean hasDomainURLs(Package pkg) {
+        if (pkg == null || pkg.activities == null) return false;
+        final ArrayList<Activity> activities = pkg.activities;
+        final int countActivities = activities.size();
+        for (int n=0; n<countActivities; n++) {
+            Activity activity = activities.get(n);
+            ArrayList<ActivityIntentInfo> filters = activity.intents;
+            if (filters == null) continue;
+            final int countFilters = filters.size();
+            for (int m=0; m<countFilters; m++) {
+                ActivityIntentInfo aii = filters.get(m);
+                if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
+                if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
+                        aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
+                    return true;
+                }
+            }
         }
+        return false;
     }
 
     /**
@@ -3159,7 +3185,7 @@
 
             if (parser.getName().equals("intent-filter")) {
                 ActivityIntentInfo intent = new ActivityIntentInfo(a);
-                if (!parseIntent(res, parser, attrs, true, intent, outError)) {
+                if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
                     return null;
                 }
                 if (intent.countActions() == 0) {
@@ -3171,7 +3197,7 @@
                 }
             } else if (!receiver && parser.getName().equals("preferred")) {
                 ActivityIntentInfo intent = new ActivityIntentInfo(a);
-                if (!parseIntent(res, parser, attrs, false, intent, outError)) {
+                if (!parseIntent(res, parser, attrs, false, false, intent, outError)) {
                     return null;
                 }
                 if (intent.countActions() == 0) {
@@ -3351,7 +3377,7 @@
 
             if (parser.getName().equals("intent-filter")) {
                 ActivityIntentInfo intent = new ActivityIntentInfo(a);
-                if (!parseIntent(res, parser, attrs, true, intent, outError)) {
+                if (!parseIntent(res, parser, attrs, true, true, intent, outError)) {
                     return null;
                 }
                 if (intent.countActions() == 0) {
@@ -3531,7 +3557,7 @@
 
             if (parser.getName().equals("intent-filter")) {
                 ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
-                if (!parseIntent(res, parser, attrs, true, intent, outError)) {
+                if (!parseIntent(res, parser, attrs, true, false, intent, outError)) {
                     return false;
                 }
                 outInfo.intents.add(intent);
@@ -3790,7 +3816,7 @@
 
             if (parser.getName().equals("intent-filter")) {
                 ServiceIntentInfo intent = new ServiceIntentInfo(s);
-                if (!parseIntent(res, parser, attrs, true, intent, outError)) {
+                if (!parseIntent(res, parser, attrs, true, false, intent, outError)) {
                     return null;
                 }
 
@@ -3991,7 +4017,7 @@
             = "http://schemas.android.com/apk/res/android";
 
     private boolean parseIntent(Resources res, XmlPullParser parser, AttributeSet attrs,
-            boolean allowGlobs, IntentInfo outInfo, String[] outError)
+            boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
             throws XmlPullParserException, IOException {
 
         TypedArray sa = res.obtainAttributes(attrs,
@@ -4016,6 +4042,12 @@
         outInfo.banner = sa.getResourceId(
                 com.android.internal.R.styleable.AndroidManifestIntentFilter_banner, 0);
 
+        if (allowAutoVerify) {
+            outInfo.setAutoVerify(sa.getBoolean(
+                    com.android.internal.R.styleable.AndroidManifestIntentFilter_autoVerify,
+                    false));
+        }
+
         sa.recycle();
 
         int outerDepth = parser.getDepth();
@@ -4409,6 +4441,20 @@
             return applicationInfo.isForwardLocked();
         }
 
+        /**
+         * @hide
+         */
+        public boolean isSystemApp() {
+            return applicationInfo.isSystemApp();
+        }
+
+        /**
+         * @hide
+         */
+        public boolean isUpdatedSystemApp() {
+            return applicationInfo.isUpdatedSystemApp();
+        }
+
         public String toString() {
             return "Package{"
                 + Integer.toHexString(System.identityHashCode(this))
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index a9c7be3..92b8055 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -37,10 +37,14 @@
     public ArraySet<String> disabledComponents;
     public ArraySet<String> enabledComponents;
 
+    public int domainVerificationStatus;
+
     public PackageUserState() {
         installed = true;
         hidden = false;
         enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+        domainVerificationStatus =
+                PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
     }
 
     public PackageUserState(PackageUserState o) {
@@ -51,9 +55,10 @@
         hidden = o.hidden;
         lastDisableAppCaller = o.lastDisableAppCaller;
         disabledComponents = o.disabledComponents != null
-                ? new ArraySet<String>(o.disabledComponents) : null;
+                ? new ArraySet<>(o.disabledComponents) : null;
         enabledComponents = o.enabledComponents != null
-                ? new ArraySet<String>(o.enabledComponents) : null;
+                ? new ArraySet<>(o.enabledComponents) : null;
         blockUninstall = o.blockUninstall;
+        domainVerificationStatus = o.domainVerificationStatus;
     }
 }
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index fe3aec9..7b141f0 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -143,6 +143,11 @@
      */
     public boolean system;
 
+    /**
+     * @hide Does the associated IntentFilter needs verification ?
+     */
+    public boolean filterNeedsVerification;
+
     private ComponentInfo getComponentInfo() {
         if (activityInfo != null) return activityInfo;
         if (serviceInfo != null) return serviceInfo;
@@ -283,6 +288,7 @@
         resolvePackageName = orig.resolvePackageName;
         system = orig.system;
         targetUserId = orig.targetUserId;
+        filterNeedsVerification = orig.filterNeedsVerification;
     }
 
     public String toString() {
@@ -344,6 +350,7 @@
         dest.writeInt(targetUserId);
         dest.writeInt(system ? 1 : 0);
         dest.writeInt(noResourceId ? 1 : 0);
+        dest.writeInt(filterNeedsVerification ? 1 : 0);
     }
 
     public static final Creator<ResolveInfo> CREATOR
@@ -389,6 +396,7 @@
         targetUserId = source.readInt();
         system = source.readInt() != 0;
         noResourceId = source.readInt() != 0;
+        filterNeedsVerification = source.readInt() != 0;
     }
     
     public static class DisplayNameComparator
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 7d8dff3..fdafb04 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -71,10 +71,15 @@
  */
 public class ColorStateList implements Parcelable {
     private static final String TAG = "ColorStateList";
+
     private static final int DEFAULT_COLOR = Color.RED;
     private static final int[][] EMPTY = new int[][] { new int[0] };
-    private static final SparseArray<WeakReference<ColorStateList>> sCache =
-                            new SparseArray<WeakReference<ColorStateList>>();
+
+    /** Thread-safe cache of single-color ColorStateLists. */
+    private static final SparseArray<WeakReference<ColorStateList>> sCache = new SparseArray<>();
+
+    /** Lazily-created factory for this color state list. */
+    private ColorStateListFactory mFactory;
 
     private int[][] mThemeAttrs;
     private int mChangingConfigurations;
@@ -125,7 +130,7 @@
             }
 
             final ColorStateList csl = new ColorStateList(EMPTY, new int[] { color });
-            sCache.put(color, new WeakReference<ColorStateList>(csl));
+            sCache.put(color, new WeakReference<>(csl));
             return csl;
         }
     }
@@ -141,11 +146,13 @@
      */
     private ColorStateList(ColorStateList orig) {
         if (orig != null) {
+            mChangingConfigurations = orig.mChangingConfigurations;
             mStateSpecs = orig.mStateSpecs;
             mDefaultColor = orig.mDefaultColor;
             mIsOpaque = orig.mIsOpaque;
 
-            // Deep copy, this may change due to theming.
+            // Deep copy, these may change due to applyTheme().
+            mThemeAttrs = orig.mThemeAttrs.clone();
             mColors = orig.mColors.clone();
         }
     }
@@ -329,6 +336,7 @@
      * attributes.
      *
      * @return whether a theme can be applied to this color state list
+     * @hide only for resource preloading
      */
     public boolean canApplyTheme() {
         return mThemeAttrs != null;
@@ -336,10 +344,15 @@
 
     /**
      * Applies a theme to this color state list.
+     * <p>
+     * <strong>Note:</strong> Applying a theme may affect the changing
+     * configuration parameters of this color state list. After calling this
+     * method, any dependent configurations must be updated by obtaining the
+     * new configuration mask from {@link #getChangingConfigurations()}.
      *
      * @param t the theme to apply
      */
-    public void applyTheme(Theme t) {
+    private void applyTheme(Theme t) {
         if (mThemeAttrs == null) {
             return;
         }
@@ -376,6 +389,38 @@
         onColorsChanged();
     }
 
+    /**
+     * Returns an appropriately themed color state list.
+     *
+     * @param t the theme to apply
+     * @return a copy of the color state list with the theme applied, or the
+     *         color state list itself if there were no unresolved theme
+     *         attributes
+     * @hide only for resource preloading
+     */
+    public ColorStateList obtainForTheme(Theme t) {
+        if (t == null || !canApplyTheme()) {
+            return this;
+        }
+
+        final ColorStateList clone = new ColorStateList(this);
+        clone.applyTheme(t);
+        return clone;
+    }
+
+    /**
+     * Returns a mask of the configuration parameters for which this color
+     * state list may change, requiring that it be re-created.
+     *
+     * @return a mask of the changing configuration parameters, as defined by
+     *         {@link android.content.pm.ActivityInfo}
+     *
+     * @see android.content.pm.ActivityInfo
+     */
+    public int getChangingConfigurations() {
+        return mChangingConfigurations;
+    }
+
     private int modulateColorAlpha(int baseColor, float alphaMod) {
         if (alphaMod == 1.0f) {
             return baseColor;
@@ -383,8 +428,7 @@
 
         final int baseAlpha = Color.alpha(baseColor);
         final int alpha = MathUtils.constrain((int) (baseAlpha * alphaMod + 0.5f), 0, 255);
-        final int color = (baseColor & 0xFFFFFF) | (alpha << 24);
-        return color;
+        return (baseColor & 0xFFFFFF) | (alpha << 24);
     }
 
     /**
@@ -534,14 +578,18 @@
     }
 
     /**
-     * @return A factory that can create new instances of this ColorStateList.
+     * @return a factory that can create new instances of this ColorStateList
+     * @hide only for resource preloading
      */
-    ColorStateListFactory getFactory() {
-        return new ColorStateListFactory(this);
+    public ConstantState<ColorStateList> getConstantState() {
+        if (mFactory != null) {
+            mFactory = new ColorStateListFactory(this);
+        }
+        return mFactory;
     }
 
-    static class ColorStateListFactory extends ConstantState<ColorStateList> {
-        final ColorStateList mSrc;
+    private static class ColorStateListFactory extends ConstantState<ColorStateList> {
+        private final ColorStateList mSrc;
 
         public ColorStateListFactory(ColorStateList src) {
             mSrc = src;
@@ -559,13 +607,7 @@
 
         @Override
         public ColorStateList newInstance(Resources res, Theme theme) {
-            if (theme == null || !mSrc.canApplyTheme()) {
-                return mSrc;
-            }
-
-            final ColorStateList clone = new ColorStateList(mSrc);
-            clone.applyTheme(theme);
-            return clone;
+            return mSrc.obtainForTheme(theme);
         }
     }
 
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 14af584..bc6d4ce 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1284,14 +1284,12 @@
 
     /**
      * Set the locale. This is the preferred way for setting up the locale (instead of using the
-     * direct accessor). This will also set the userLocale and layout direction according to
-     * the locale.
+     * direct accessor). This will also set the layout direction according to the locale.
      *
      * @param loc The locale. Can be null.
      */
     public void setLocale(Locale loc) {
         locale = loc;
-        userSetLocale = true;
         setLayoutDirection(locale);
     }
 
@@ -1314,7 +1312,8 @@
      * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction
      * corresponding to the Locale.
      *
-     * @see {@link View#LAYOUT_DIRECTION_LTR} and {@link View#LAYOUT_DIRECTION_RTL}
+     * @see View#LAYOUT_DIRECTION_LTR
+     * @see View#LAYOUT_DIRECTION_RTL
      */
     public void setLayoutDirection(Locale locale) {
         // There is a "1" difference between the configuration values for
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 95ad57e..334d180 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -16,7 +16,10 @@
 
 package android.content.res;
 
+import android.annotation.AttrRes;
 import android.annotation.ColorInt;
+import android.annotation.StyleRes;
+import android.annotation.StyleableRes;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -41,7 +44,6 @@
 import android.annotation.StringRes;
 import android.annotation.XmlRes;
 import android.content.pm.ActivityInfo;
-import android.content.res.ColorStateList.ColorStateListFactory;
 import android.graphics.Movie;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -111,12 +113,15 @@
     // single-threaded, and after that these are immutable.
     private static final LongSparseArray<ConstantState>[] sPreloadedDrawables;
     private static final LongSparseArray<ConstantState> sPreloadedColorDrawables
-            = new LongSparseArray<ConstantState>();
-    private static final LongSparseArray<ColorStateListFactory> sPreloadedColorStateLists
-            = new LongSparseArray<ColorStateListFactory>();
+            = new LongSparseArray<>();
+    private static final LongSparseArray<android.content.res.ConstantState<ColorStateList>>
+            sPreloadedColorStateLists = new LongSparseArray<>();
+
+    private static final String CACHE_NOT_THEMED = "";
+    private static final String CACHE_NULL_THEME = "null_theme";
 
     // Pool of TypedArrays targeted to this Resources object.
-    final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<TypedArray>(5);
+    final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
 
     // Used by BridgeResources in layoutlib
     static Resources mSystem = null;
@@ -128,21 +133,19 @@
     private final Object mAccessLock = new Object();
     private final Configuration mTmpConfig = new Configuration();
     private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> mDrawableCache =
-            new ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>>();
+            new ArrayMap<>();
     private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> mColorDrawableCache =
-            new ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>>();
+            new ArrayMap<>();
     private final ConfigurationBoundResourceCache<ColorStateList> mColorStateListCache =
-            new ConfigurationBoundResourceCache<ColorStateList>(this);
+            new ConfigurationBoundResourceCache<>(this);
     private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
-            new ConfigurationBoundResourceCache<Animator>(this);
+            new ConfigurationBoundResourceCache<>(this);
     private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
-            new ConfigurationBoundResourceCache<StateListAnimator>(this);
+            new ConfigurationBoundResourceCache<>(this);
 
     private TypedValue mTmpValue = new TypedValue();
     private boolean mPreloading;
 
-    private TypedArray mCachedStyledAttributes = null;
-
     private int mLastCachedXmlBlockIndex = -1;
     private final int[] mCachedXmlBlockIds = { 0, 0, 0, 0 };
     private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4];
@@ -157,8 +160,8 @@
 
     static {
         sPreloadedDrawables = new LongSparseArray[2];
-        sPreloadedDrawables[0] = new LongSparseArray<ConstantState>();
-        sPreloadedDrawables[1] = new LongSparseArray<ConstantState>();
+        sPreloadedDrawables[0] = new LongSparseArray<>();
+        sPreloadedDrawables[1] = new LongSparseArray<>();
     }
 
     /**
@@ -1475,7 +1478,7 @@
          * @see #obtainStyledAttributes(int, int[])
          * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
          */
-        public TypedArray obtainStyledAttributes(int[] attrs) {
+        public TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) {
             final int len = attrs.length;
             final TypedArray array = TypedArray.obtain(Resources.this, len);
             array.mTheme = this;
@@ -1503,7 +1506,8 @@
          * @see #obtainStyledAttributes(int[])
          * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
          */
-        public TypedArray obtainStyledAttributes(int resid, int[] attrs) throws NotFoundException {
+        public TypedArray obtainStyledAttributes(@StyleRes int resid, @StyleableRes int[] attrs)
+                throws NotFoundException {
             final int len = attrs.length;
             final TypedArray array = TypedArray.obtain(Resources.this, len);
             array.mTheme = this;
@@ -1586,7 +1590,7 @@
          * @see #obtainStyledAttributes(int, int[])
          */
         public TypedArray obtainStyledAttributes(AttributeSet set,
-                int[] attrs, int defStyleAttr, int defStyleRes) {
+                @StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
             final int len = attrs.length;
             final TypedArray array = TypedArray.obtain(Resources.this, len);
 
@@ -1876,7 +1880,7 @@
             // the framework.
             mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
 
-            int configChanges = calcConfigChanges(config);
+            final int configChanges = calcConfigChanges(config);
             if (mConfiguration.locale == null) {
                 mConfiguration.locale = Locale.getDefault();
                 mConfiguration.setLayoutDirection(mConfiguration.locale);
@@ -1891,7 +1895,8 @@
             if (mConfiguration.locale != null) {
                 locale = adjustLanguageTag(mConfiguration.locale.toLanguageTag());
             }
-            int width, height;
+
+            final int width, height;
             if (mMetrics.widthPixels >= mMetrics.heightPixels) {
                 width = mMetrics.widthPixels;
                 height = mMetrics.heightPixels;
@@ -1901,12 +1906,15 @@
                 //noinspection SuspiciousNameCombination
                 height = mMetrics.widthPixels;
             }
-            int keyboardHidden = mConfiguration.keyboardHidden;
-            if (keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
-                    && mConfiguration.hardKeyboardHidden
-                            == Configuration.HARDKEYBOARDHIDDEN_YES) {
+
+            final int keyboardHidden;
+            if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
+                    && mConfiguration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
                 keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
+            } else {
+                keyboardHidden = mConfiguration.keyboardHidden;
             }
+
             mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
                     locale, mConfiguration.orientation,
                     mConfiguration.touchscreen,
@@ -2436,8 +2444,8 @@
             }
         }
 
-        // Next, check preloaded drawables. These are unthemed but may have
-        // themeable attributes.
+        // Next, check preloaded drawables. These may contain unresolved theme
+        // attributes.
         final ConstantState cs;
         if (isColorDrawable) {
             cs = sPreloadedColorDrawables.get(key);
@@ -2445,42 +2453,49 @@
             cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
         }
 
-        final Drawable dr;
+        Drawable dr;
         if (cs != null) {
-            final Drawable clonedDr = cs.newDrawable(this);
-            if (theme != null) {
-                dr = clonedDr.mutate();
-                dr.applyTheme(theme);
-                dr.clearMutated();
-            } else {
-                dr = clonedDr;
-            }
+            dr = cs.newDrawable(this);
         } else if (isColorDrawable) {
             dr = new ColorDrawable(value.data);
         } else {
-            dr = loadDrawableForCookie(value, id, theme);
+            dr = loadDrawableForCookie(value, id, null);
+        }
+
+        // Determine if the drawable has unresolved theme attributes. If it
+        // does, we'll need to apply a theme and store it in a theme-specific
+        // cache.
+        final String cacheKey;
+        if (!dr.canApplyTheme()) {
+            cacheKey = CACHE_NOT_THEMED;
+        } else if (theme == null) {
+            cacheKey = CACHE_NULL_THEME;
+        } else {
+            cacheKey = theme.getKey();
+            dr = dr.mutate();
+            dr.applyTheme(theme);
+            dr.clearMutated();
         }
 
         // If we were able to obtain a drawable, store it in the appropriate
-        // cache (either preload or themed).
+        // cache: preload, not themed, null theme, or theme-specific.
         if (dr != null) {
             dr.setChangingConfigurations(value.changingConfigurations);
-            cacheDrawable(value, theme, isColorDrawable, caches, key, dr);
+            cacheDrawable(value, isColorDrawable, caches, cacheKey, key, dr);
         }
 
         return dr;
     }
 
-    private void cacheDrawable(TypedValue value, Theme theme, boolean isColorDrawable,
+    private void cacheDrawable(TypedValue value, boolean isColorDrawable,
             ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
-            long key, Drawable dr) {
+            String cacheKey, long key, Drawable dr) {
         final ConstantState cs = dr.getConstantState();
         if (cs == null) {
             return;
         }
 
         if (mPreloading) {
-            // Preloaded drawables never have a theme, but may be themeable.
             final int changingConfigs = cs.getChangingConfigurations();
             if (isColorDrawable) {
                 if (verifyPreloadConfig(changingConfigs, 0, value.resourceId, "drawable")) {
@@ -2502,16 +2517,15 @@
             }
         } else {
             synchronized (mAccessLock) {
-                final String themeKey = theme == null ? "" : theme.mKey;
-                LongSparseArray<WeakReference<ConstantState>> themedCache = caches.get(themeKey);
+                LongSparseArray<WeakReference<ConstantState>> themedCache = caches.get(cacheKey);
                 if (themedCache == null) {
                     // Clean out the caches before we add more. This shouldn't
                     // happen very often.
                     pruneCaches(caches);
-                    themedCache = new LongSparseArray<WeakReference<ConstantState>>(1);
-                    caches.put(themeKey, themedCache);
+                    themedCache = new LongSparseArray<>(1);
+                    caches.put(cacheKey, themedCache);
                 }
-                themedCache.put(key, new WeakReference<ConstantState>(cs));
+                themedCache.put(key, new WeakReference<>(cs));
             }
         }
     }
@@ -2607,42 +2621,43 @@
             ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
             long key, Theme theme) {
         synchronized (mAccessLock) {
-            final String themeKey = theme != null ? theme.mKey : "";
-            final LongSparseArray<WeakReference<ConstantState>> themedCache = caches.get(themeKey);
-            if (themedCache != null) {
-                final Drawable themedDrawable = getCachedDrawableLocked(themedCache, key);
-                if (themedDrawable != null) {
-                    return themedDrawable;
-                }
+            // First search theme-agnostic cache.
+            final Drawable unthemedDrawable = getCachedDrawableLocked(
+                    caches, key, CACHE_NOT_THEMED);
+            if (unthemedDrawable != null) {
+                return unthemedDrawable;
             }
 
-            // No cached drawable, we'll need to create a new one.
-            return null;
+            // Next search theme-specific cache.
+            final String themeKey = theme != null ? theme.getKey() : CACHE_NULL_THEME;
+            return getCachedDrawableLocked(caches, key, themeKey);
         }
     }
 
-    private ConstantState getConstantStateLocked(
-            LongSparseArray<WeakReference<ConstantState>> drawableCache, long key) {
-        final WeakReference<ConstantState> wr = drawableCache.get(key);
-        if (wr != null) {   // we have the key
-            final ConstantState entry = wr.get();
+    private Drawable getCachedDrawableLocked(
+            ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
+            long key, String themeKey) {
+        final LongSparseArray<WeakReference<ConstantState>> cache = caches.get(themeKey);
+        if (cache != null) {
+            final ConstantState entry = getConstantStateLocked(cache, key);
             if (entry != null) {
-                //Log.i(TAG, "Returning cached drawable @ #" +
-                //        Integer.toHexString(((Integer)key).intValue())
-                //        + " in " + this + ": " + entry);
-                return entry;
-            } else {  // our entry has been purged
-                drawableCache.delete(key);
+                return entry.newDrawable(this);
             }
         }
         return null;
     }
 
-    private Drawable getCachedDrawableLocked(
+    private ConstantState getConstantStateLocked(
             LongSparseArray<WeakReference<ConstantState>> drawableCache, long key) {
-        final ConstantState entry = getConstantStateLocked(drawableCache, key);
-        if (entry != null) {
-            return entry.newDrawable(this);
+        final WeakReference<ConstantState> wr = drawableCache.get(key);
+        if (wr != null) {
+            final ConstantState entry = wr.get();
+            if (entry != null) {
+                return entry;
+            } else {
+                // Our entry has been purged.
+                drawableCache.delete(key);
+            }
         }
         return null;
     }
@@ -2665,7 +2680,8 @@
         // Handle inline color definitions.
         if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
                 && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
-            final ColorStateListFactory factory = sPreloadedColorStateLists.get(key);
+            final android.content.res.ConstantState<ColorStateList> factory =
+                    sPreloadedColorStateLists.get(key);
             if (factory != null) {
                 return factory.newInstance();
             }
@@ -2675,7 +2691,7 @@
             if (mPreloading) {
                 if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
                         "color")) {
-                    sPreloadedColorStateLists.put(key, csl.getFactory());
+                    sPreloadedColorStateLists.put(key, csl.getConstantState());
                 }
             }
 
@@ -2689,7 +2705,8 @@
             return csl;
         }
 
-        final ColorStateListFactory factory = sPreloadedColorStateLists.get(key);
+        final android.content.res.ConstantState<ColorStateList> factory =
+                sPreloadedColorStateLists.get(key);
         if (factory != null) {
             csl = factory.newInstance(this, theme);
         }
@@ -2702,10 +2719,10 @@
             if (mPreloading) {
                 if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
                         "color")) {
-                    sPreloadedColorStateLists.put(key, csl.getFactory());
+                    sPreloadedColorStateLists.put(key, csl.getConstantState());
                 }
             } else {
-                cache.put(key, theme, csl.getFactory());
+                cache.put(key, theme, csl.getConstantState());
             }
         }
 
@@ -2830,15 +2847,6 @@
                 + Integer.toHexString(id));
     }
 
-    /*package*/ void recycleCachedStyledAttributes(TypedArray attrs) {
-        synchronized (mAccessLock) {
-            final TypedArray cached = mCachedStyledAttributes;
-            if (cached == null || cached.mData.length < attrs.mData.length) {
-                mCachedStyledAttributes = attrs;
-            }
-        }
-    }
-
     /**
      * Obtains styled attributes from the theme, if available, or unstyled
      * resources if the theme is null.
diff --git a/core/java/android/database/DatabaseErrorHandler.java b/core/java/android/database/DatabaseErrorHandler.java
index f0c5452..55ad921 100644
--- a/core/java/android/database/DatabaseErrorHandler.java
+++ b/core/java/android/database/DatabaseErrorHandler.java
@@ -19,13 +19,12 @@
 import android.database.sqlite.SQLiteDatabase;
 
 /**
- * An interface to let the apps define the actions to take when the following errors are detected
- *   database corruption
+ * An interface to let apps define an action to take when database corruption is detected.
  */
 public interface DatabaseErrorHandler {
 
     /**
-     * defines the method to be invoked when database corruption is detected.
+     * The method invoked when database corruption is detected.
      * @param dbObj the {@link SQLiteDatabase} object representing the database on which corruption
      * is detected.
      */
diff --git a/core/java/android/database/DefaultDatabaseErrorHandler.java b/core/java/android/database/DefaultDatabaseErrorHandler.java
index b234e34..7fa2b40 100755
--- a/core/java/android/database/DefaultDatabaseErrorHandler.java
+++ b/core/java/android/database/DefaultDatabaseErrorHandler.java
@@ -24,7 +24,7 @@
 import android.util.Pair;
 
 /**
- * Default class used to define the actions to take when the database corruption is reported
+ * Default class used to define the action to take when database corruption is reported
  * by sqlite.
  * <p>
  * An application can specify an implementation of {@link DatabaseErrorHandler} on the
@@ -38,7 +38,7 @@
  * The specified {@link DatabaseErrorHandler} is used to handle database corruption errors, if they
  * occur.
  * <p>
- * If null is specified for DatabaeErrorHandler param in the above calls, then this class is used
+ * If null is specified for the DatabaseErrorHandler param in the above calls, this class is used
  * as the default {@link DatabaseErrorHandler}.
  */
 public final class DefaultDatabaseErrorHandler implements DatabaseErrorHandler {
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
index d5dfaf6..9bc2f46 100644
--- a/core/java/android/hardware/ICameraService.aidl
+++ b/core/java/android/hardware/ICameraService.aidl
@@ -75,4 +75,11 @@
                     out BinderHolder device);
 
     int setTorchMode(String CameraId, boolean enabled, IBinder clientBinder);
+
+    /**
+     * Notify the camera service of a system event.  Should only be called from system_server.
+     *
+     * Callers require the android.permission.CAMERA_SEND_SYSTEM_EVENTS permission.
+     */
+    oneway void notifySystemEvent(int eventId, int arg0);
 }
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index a6c3ea4..88fa339 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -54,11 +54,13 @@
     // Looper associated with the context in which this instance was created.
     private final Looper mMainLooper;
     private final int mTargetSdkLevel;
+    private final String mPackageName;
 
     /** {@hide} */
     public SystemSensorManager(Context context, Looper mainLooper) {
         mMainLooper = mainLooper;
         mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
+        mPackageName = context.getPackageName();
         synchronized(sSensorModuleLock) {
             if (!sSensorModuleInitialized) {
                 sSensorModuleInitialized = true;
@@ -117,14 +119,14 @@
             if (queue == null) {
                 Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
                 queue = new SensorEventQueue(listener, looper, this);
-                if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags)) {
+                if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {
                     queue.dispose();
                     return false;
                 }
                 mSensorListeners.put(listener, queue);
                 return true;
             } else {
-                return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags);
+                return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
             }
         }
     }
@@ -165,14 +167,14 @@
             TriggerEventQueue queue = mTriggerListeners.get(listener);
             if (queue == null) {
                 queue = new TriggerEventQueue(listener, mMainLooper, this);
-                if (!queue.addSensor(sensor, 0, 0, 0)) {
+                if (!queue.addSensor(sensor, 0, 0)) {
                     queue.dispose();
                     return false;
                 }
                 mTriggerListeners.put(listener, queue);
                 return true;
             } else {
-                return queue.addSensor(sensor, 0, 0, 0);
+                return queue.addSensor(sensor, 0, 0);
             }
         }
     }
@@ -223,9 +225,9 @@
      */
     private static abstract class BaseEventQueue {
         private native long nativeInitBaseEventQueue(BaseEventQueue eventQ, MessageQueue msgQ,
-                float[] scratch);
+                float[] scratch, String packageName);
         private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
-                int maxBatchReportLatencyUs, int reservedFlags);
+                int maxBatchReportLatencyUs);
         private static native int nativeDisableSensor(long eventQ, int handle);
         private static native void nativeDestroySensorEventQueue(long eventQ);
         private static native int nativeFlushSensor(long eventQ);
@@ -238,7 +240,8 @@
         protected final SystemSensorManager mManager;
 
         BaseEventQueue(Looper looper, SystemSensorManager manager) {
-            nSensorEventQueue = nativeInitBaseEventQueue(this, looper.getQueue(), mScratch);
+            nSensorEventQueue = nativeInitBaseEventQueue(this, looper.getQueue(), mScratch,
+                    manager.mPackageName);
             mCloseGuard.open("dispose");
             mManager = manager;
         }
@@ -248,7 +251,7 @@
         }
 
         public boolean addSensor(
-                Sensor sensor, int delayUs, int maxBatchReportLatencyUs, int reservedFlags) {
+                Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {
             // Check if already present.
             int handle = sensor.getHandle();
             if (mActiveSensors.get(handle)) return false;
@@ -256,10 +259,10 @@
             // Get ready to receive events before calling enable.
             mActiveSensors.put(handle, true);
             addSensorEvent(sensor);
-            if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags) != 0) {
+            if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {
                 // Try continuous mode if batching fails.
                 if (maxBatchReportLatencyUs == 0 ||
-                    maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0, 0) != 0) {
+                    maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) {
                   removeSensor(sensor, false);
                   return false;
                 }
@@ -328,11 +331,11 @@
         }
 
         private int enableSensor(
-                Sensor sensor, int rateUs, int maxBatchReportLatencyUs, int reservedFlags) {
+                Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
             if (nSensorEventQueue == 0) throw new NullPointerException();
             if (sensor == null) throw new NullPointerException();
             return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs,
-                    maxBatchReportLatencyUs, reservedFlags);
+                    maxBatchReportLatencyUs);
         }
 
         private int disableSensor(Sensor sensor) {
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index a0217c2..f28c96e 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -991,7 +991,8 @@
      * <ul>
      * <li>Processed (but stalling): any non-RAW format with a stallDurations &gt; 0.
      * Typically JPEG format (ImageFormat#JPEG).</li>
-     * <li>Raw formats: ImageFormat#RAW_SENSOR, ImageFormat#RAW10 and ImageFormat#RAW_OPAQUE.</li>
+     * <li>Raw formats: ImageFormat#RAW_SENSOR, ImageFormat#RAW10, ImageFormat#RAW12,
+     * and ImageFormat#RAW_OPAQUE.</li>
      * <li>Processed (but not-stalling): any non-RAW format without a stall duration.
      * Typically ImageFormat#YUV_420_888, ImageFormat#NV21, ImageFormat#YV12.</li>
      * </ul>
@@ -1023,6 +1024,7 @@
      * <ul>
      * <li>ImageFormat#RAW_SENSOR</li>
      * <li>ImageFormat#RAW10</li>
+     * <li>ImageFormat#RAW12</li>
      * <li>Opaque <code>RAW</code></li>
      * </ul>
      * <p>LEGACY mode devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} <code>==</code> LEGACY)
@@ -2352,8 +2354,8 @@
      * <p>Camera devices that support the MANUAL_POST_PROCESSING capability will always contain
      * at least one of below mode combinations:</p>
      * <ul>
-     * <li>CONTRAST_CURVE and FAST</li>
-     * <li>GAMMA_VALUE, PRESET_CURVE, and FAST</li>
+     * <li>CONTRAST_CURVE, FAST and HIGH_QUALITY</li>
+     * <li>GAMMA_VALUE, PRESET_CURVE, FAST and HIGH_QUALITY</li>
      * </ul>
      * <p>This includes all FULL level devices.</p>
      * <p><b>Range of valid values:</b><br>
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 7f901c8..85c574a 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -852,8 +852,8 @@
 
     /**
      * <p>Color correction processing operates at improved
-     * quality but reduced capture rate (relative to sensor raw
-     * output).</p>
+     * quality but the capture rate might be reduced (relative to sensor
+     * raw output rate)</p>
      * <p>Advanced white balance adjustments above and beyond
      * the specified white balance pipeline may be applied.</p>
      * <p>If AWB is enabled with <code>{@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} != OFF</code>, then
@@ -883,8 +883,8 @@
     public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1;
 
     /**
-     * <p>Aberration correction operates at improved quality but reduced
-     * capture rate (relative to sensor raw output).</p>
+     * <p>Aberration correction operates at improved quality but the capture rate might be
+     * reduced (relative to sensor raw output rate)</p>
      * @see CaptureRequest#COLOR_CORRECTION_ABERRATION_MODE
      */
     public static final int COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY = 2;
@@ -1797,7 +1797,7 @@
     public static final int EDGE_MODE_FAST = 1;
 
     /**
-     * <p>Apply high-quality edge enhancement, at a cost of reducing output frame rate.</p>
+     * <p>Apply high-quality edge enhancement, at a cost of possibly reduced output frame rate.</p>
      * @see CaptureRequest#EDGE_MODE
      */
     public static final int EDGE_MODE_HIGH_QUALITY = 2;
@@ -1852,7 +1852,7 @@
 
     /**
      * <p>High-quality hot pixel correction is applied, at a cost
-     * of reducing frame rate relative to sensor raw output.</p>
+     * of possibly reduced frame rate relative to sensor raw output.</p>
      * <p>The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
      *
      * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
@@ -1894,8 +1894,8 @@
     public static final int NOISE_REDUCTION_MODE_FAST = 1;
 
     /**
-     * <p>High-quality noise reduction is applied, at the cost of reducing frame rate
-     * relative to sensor output.</p>
+     * <p>High-quality noise reduction is applied, at the cost of possibly reduced frame
+     * rate relative to sensor output.</p>
      * @see CaptureRequest#NOISE_REDUCTION_MODE
      */
     public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2;
@@ -2032,7 +2032,7 @@
 
     /**
      * <p>Apply high-quality lens shading correction, at the
-     * cost of reduced frame rate.</p>
+     * cost of possibly reduced frame rate.</p>
      * @see CaptureRequest#SHADING_MODE
      */
     public static final int SHADING_MODE_HIGH_QUALITY = 2;
@@ -2105,7 +2105,7 @@
 
     /**
      * <p>High-quality gamma mapping and color enhancement will be applied, at
-     * the cost of reduced frame rate compared to raw sensor output.</p>
+     * the cost of possibly reduced frame rate compared to raw sensor output.</p>
      * @see CaptureRequest#TONEMAP_MODE
      */
     public static final int TONEMAP_MODE_HIGH_QUALITY = 2;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 7569ea5..b8fb8e7 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1541,7 +1541,8 @@
      * to the camera, that the JPEG picture needs to be rotated by, to be viewed
      * upright.</p>
      * <p>Camera devices may either encode this value into the JPEG EXIF header, or
-     * rotate the image data to match this orientation.</p>
+     * rotate the image data to match this orientation. When the image data is rotated,
+     * the thumbnail data will also be rotated.</p>
      * <p>Note that this orientation is relative to the orientation of the camera sensor, given
      * by {@link CameraCharacteristics#SENSOR_ORIENTATION android.sensor.orientation}.</p>
      * <p>To translate from the device orientation given by the Android sensor APIs, the following
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index b84dc2e..e346dc2 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2230,7 +2230,8 @@
      * to the camera, that the JPEG picture needs to be rotated by, to be viewed
      * upright.</p>
      * <p>Camera devices may either encode this value into the JPEG EXIF header, or
-     * rotate the image data to match this orientation.</p>
+     * rotate the image data to match this orientation. When the image data is rotated,
+     * the thumbnail data will also be rotated.</p>
      * <p>Note that this orientation is relative to the orientation of the camera sensor, given
      * by {@link CameraCharacteristics#SENSOR_ORIENTATION android.sensor.orientation}.</p>
      * <p>To translate from the device orientation given by the Android sensor APIs, the following
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index f47ce79..e926a98 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -830,11 +830,19 @@
                 CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
         StreamConfigurationDuration[] stallDurations = getBase(
                 CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS);
+        StreamConfiguration[] depthConfigurations = getBase(
+                CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
+        StreamConfigurationDuration[] depthMinFrameDurations = getBase(
+                CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS);
+        StreamConfigurationDuration[] depthStallDurations = getBase(
+                CameraCharacteristics.DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS);
         HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase(
                 CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
 
         return new StreamConfigurationMap(
-                configurations, minFrameDurations, stallDurations, highSpeedVideoConfigurations);
+                configurations, minFrameDurations, stallDurations,
+                depthConfigurations, depthMinFrameDurations, depthStallDurations,
+                highSpeedVideoConfigurations);
     }
 
     private <T> Integer getMaxRegions(Key<T> key) {
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 0a4ed39..7aa9787 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -18,6 +18,7 @@
 package android.hardware.camera2.params;
 
 import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.utils.HashCodeHelpers;
 import android.util.Log;
 import android.view.Surface;
 import android.os.Parcel;
@@ -159,6 +160,35 @@
         mSurface.writeToParcel(dest, flags);
     }
 
+    /**
+     * Check if this {@link OutputConfiguration} is equal to another {@link OutputConfiguration}.
+     *
+     * <p>Two output configurations are only equal if and only if the underlying surface and
+     * all other configuration parameters are equal. </p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        } else if (this == obj) {
+            return true;
+        } else if (obj instanceof OutputConfiguration) {
+            final OutputConfiguration other = (OutputConfiguration) obj;
+            return (mSurface == other.mSurface && mRotation == other.mRotation);
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return HashCodeHelpers.hashCode(mSurface.hashCode(), mRotation);
+    }
+
     private static final String TAG = "OutputConfiguration";
     private final Surface mSurface;
     private final int mRotation;
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index f5304f8..b418971 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -89,11 +89,28 @@
             StreamConfiguration[] configurations,
             StreamConfigurationDuration[] minFrameDurations,
             StreamConfigurationDuration[] stallDurations,
+            StreamConfiguration[] depthConfigurations,
+            StreamConfigurationDuration[] depthMinFrameDurations,
+            StreamConfigurationDuration[] depthStallDurations,
             HighSpeedVideoConfiguration[] highSpeedVideoConfigurations) {
 
         mConfigurations = checkArrayElementsNotNull(configurations, "configurations");
         mMinFrameDurations = checkArrayElementsNotNull(minFrameDurations, "minFrameDurations");
         mStallDurations = checkArrayElementsNotNull(stallDurations, "stallDurations");
+
+        if (depthConfigurations == null) {
+            mDepthConfigurations = new StreamConfiguration[0];
+            mDepthMinFrameDurations = new StreamConfigurationDuration[0];
+            mDepthStallDurations = new StreamConfigurationDuration[0];
+        } else {
+            mDepthConfigurations = checkArrayElementsNotNull(depthConfigurations,
+                    "depthConfigurations");
+            mDepthMinFrameDurations = checkArrayElementsNotNull(depthMinFrameDurations,
+                    "depthMinFrameDurations");
+            mDepthStallDurations = checkArrayElementsNotNull(depthStallDurations,
+                    "depthStallDurations");
+        }
+
         if (highSpeedVideoConfigurations == null) {
             mHighSpeedVideoConfigurations = new HighSpeedVideoConfiguration[0];
         } else {
@@ -110,9 +127,24 @@
             if (count == null) {
                 count = 0;
             }
-            count = count + 1;
 
-            map.put(config.getFormat(), count);
+            map.put(config.getFormat(), count + 1);
+        }
+
+        // For each depth format, track how many sizes there are available to configure
+        for (StreamConfiguration config : mDepthConfigurations) {
+            if (!config.isOutput()) {
+                // Ignoring input depth configs
+                continue;
+            }
+
+            Integer count = mDepthOutputFormats.get(config.getFormat());
+
+            if (count == null) {
+                count = 0;
+            }
+
+            mDepthOutputFormats.put(config.getFormat(), count + 1);
         }
 
         if (!mOutputFormats.containsKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)) {
@@ -214,8 +246,13 @@
     public boolean isOutputSupportedFor(int format) {
         checkArgumentFormat(format);
 
-        format = imageFormatToInternal(format);
-        return getFormatsMap(/*output*/true).containsKey(format);
+        int internalFormat = imageFormatToInternal(format);
+        int dataspace = imageFormatToDataspace(format);
+        if (dataspace == HAL_DATASPACE_DEPTH) {
+            return mDepthOutputFormats.containsKey(internalFormat);
+        } else {
+            return getFormatsMap(/*output*/true).containsKey(internalFormat);
+        }
     }
 
     /**
@@ -386,7 +423,8 @@
             return null;
         }
 
-        return getInternalFormatSizes(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, /*output*/true);
+        return getInternalFormatSizes(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+                HAL_DATASPACE_UNKNOWN,/*output*/true);
     }
 
     /**
@@ -599,7 +637,10 @@
         checkNotNull(size, "size must not be null");
         checkArgumentFormatSupported(format, /*output*/true);
 
-        return getInternalFormatDuration(imageFormatToInternal(format), size, DURATION_MIN_FRAME);
+        return getInternalFormatDuration(imageFormatToInternal(format),
+                imageFormatToDataspace(format),
+                size,
+                DURATION_MIN_FRAME);
     }
 
     /**
@@ -652,6 +693,7 @@
         }
 
         return getInternalFormatDuration(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+                HAL_DATASPACE_UNKNOWN,
                 size, DURATION_MIN_FRAME);
     }
 
@@ -741,7 +783,9 @@
         checkArgumentFormatSupported(format, /*output*/true);
 
         return getInternalFormatDuration(imageFormatToInternal(format),
-                size, DURATION_STALL);
+                imageFormatToDataspace(format),
+                size,
+                DURATION_STALL);
     }
 
     /**
@@ -778,7 +822,7 @@
         }
 
         return getInternalFormatDuration(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
-                size, DURATION_STALL);
+                HAL_DATASPACE_UNKNOWN, size, DURATION_STALL);
     }
 
     /**
@@ -857,6 +901,7 @@
             case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
             case HAL_PIXEL_FORMAT_BLOB:
             case HAL_PIXEL_FORMAT_RAW_OPAQUE:
+            case HAL_PIXEL_FORMAT_Y16:
                 return format;
             case ImageFormat.JPEG:
                 throw new IllegalArgumentException(
@@ -896,8 +941,8 @@
     }
 
     /**
-     * Convert a public-visible {@code ImageFormat} into an internal format
-     * compatible with {@code graphics.h}.
+     * Convert an internal format compatible with {@code graphics.h} into public-visible
+     * {@code ImageFormat}. This assumes the dataspace of the format is not HAL_DATASPACE_DEPTH.
      *
      * <p>In particular these formats are converted:
      * <ul>
@@ -911,7 +956,8 @@
      *
      * <p>All other formats are returned as-is, no further invalid check is performed.</p>
      *
-     * <p>This function is the dual of {@link #imageFormatToInternal}.</p>
+     * <p>This function is the dual of {@link #imageFormatToInternal} for dataspaces other than
+     * HAL_DATASPACE_DEPTH.</p>
      *
      * @param format image format from {@link ImageFormat} or {@link PixelFormat}
      * @return the converted image formats
@@ -940,6 +986,55 @@
     }
 
     /**
+     * Convert an internal format compatible with {@code graphics.h} into public-visible
+     * {@code ImageFormat}. This assumes the dataspace of the format is HAL_DATASPACE_DEPTH.
+     *
+     * <p>In particular these formats are converted:
+     * <ul>
+     * <li>HAL_PIXEL_FORMAT_BLOB => ImageFormat.DEPTH_POINT_CLOUD
+     * <li>HAL_PIXEL_FORMAT_Y16 => ImageFormat.DEPTH16
+     * </ul>
+     * </p>
+     *
+     * <p>Passing in an implementation-defined format which has no public equivalent will fail;
+     * as will passing in a public format which has a different internal format equivalent.
+     * See {@link #checkArgumentFormat} for more details about a legal public format.</p>
+     *
+     * <p>All other formats are returned as-is, no further invalid check is performed.</p>
+     *
+     * <p>This function is the dual of {@link #imageFormatToInternal} for formats associated with
+     * HAL_DATASPACE_DEPTH.</p>
+     *
+     * @param format image format from {@link ImageFormat} or {@link PixelFormat}
+     * @return the converted image formats
+     *
+     * @throws IllegalArgumentException
+     *          if {@code format} is {@code HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED} or
+     *          {@link ImageFormat#JPEG}
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     * @see #checkArgumentFormat
+     */
+    static int depthFormatToPublic(int format) {
+        switch (format) {
+            case HAL_PIXEL_FORMAT_BLOB:
+                return ImageFormat.DEPTH_POINT_CLOUD;
+            case HAL_PIXEL_FORMAT_Y16:
+                return ImageFormat.DEPTH16;
+            case ImageFormat.JPEG:
+                throw new IllegalArgumentException(
+                        "ImageFormat.JPEG is an unknown internal format");
+            case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+                throw new IllegalArgumentException(
+                        "IMPLEMENTATION_DEFINED must not leak to public API");
+            default:
+                throw new IllegalArgumentException(
+                        "Unknown DATASPACE_DEPTH format " + format);
+        }
+    }
+
+    /**
      * Convert image formats from internal to public formats (in-place).
      *
      * @param formats an array of image formats
@@ -966,6 +1061,8 @@
      * <p>In particular these formats are converted:
      * <ul>
      * <li>ImageFormat.JPEG => HAL_PIXEL_FORMAT_BLOB
+     * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_PIXEL_FORMAT_BLOB
+     * <li>ImageFormat.DEPTH16 => HAL_PIXEL_FORMAT_Y16
      * </ul>
      * </p>
      *
@@ -989,7 +1086,10 @@
     static int imageFormatToInternal(int format) {
         switch (format) {
             case ImageFormat.JPEG:
+            case ImageFormat.DEPTH_POINT_CLOUD:
                 return HAL_PIXEL_FORMAT_BLOB;
+            case ImageFormat.DEPTH16:
+                return HAL_PIXEL_FORMAT_Y16;
             case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
                 throw new IllegalArgumentException(
                         "IMPLEMENTATION_DEFINED is not allowed via public API");
@@ -999,6 +1099,48 @@
     }
 
     /**
+     * Convert a public format compatible with {@code ImageFormat} to an internal dataspace
+     * from {@code graphics.h}.
+     *
+     * <p>In particular these formats are converted:
+     * <ul>
+     * <li>ImageFormat.JPEG => HAL_DATASPACE_JFIF
+     * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_DATASPACE_DEPTH
+     * <li>ImageFormat.DEPTH16 => HAL_DATASPACE_DEPTH
+     * <li>others => HAL_DATASPACE_UNKNOWN
+     * </ul>
+     * </p>
+     *
+     * <p>Passing in an implementation-defined format here will fail (it's not a public format);
+     * as will passing in an internal format which has a different public format equivalent.
+     * See {@link #checkArgumentFormat} for more details about a legal public format.</p>
+     *
+     * <p>All other formats are returned as-is, no invalid check is performed.</p>
+     *
+     * <p>This function is the dual of {@link #imageFormatToPublic}.</p>
+     *
+     * @param format public image format from {@link ImageFormat} or {@link PixelFormat}
+     * @return the converted image formats
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     *
+     * @throws IllegalArgumentException
+     *              if {@code format} was {@code HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}
+     */
+    static int imageFormatToDataspace(int format) {
+        switch (format) {
+            case ImageFormat.JPEG:
+                return HAL_DATASPACE_JFIF;
+            case ImageFormat.DEPTH_POINT_CLOUD:
+            case ImageFormat.DEPTH16:
+                return HAL_DATASPACE_DEPTH;
+            default:
+                return HAL_DATASPACE_UNKNOWN;
+        }
+    }
+
+    /**
      * Convert image formats from public to internal formats (in-place).
      *
      * @param formats an array of image formats
@@ -1027,13 +1169,16 @@
             return null;
         }
 
-        format = imageFormatToInternal(format);
+        int internalFormat = imageFormatToInternal(format);
+        int dataspace = imageFormatToDataspace(format);
 
-        return getInternalFormatSizes(format, output);
+        return getInternalFormatSizes(internalFormat, dataspace, output);
     }
 
-    private Size[] getInternalFormatSizes(int format, boolean output) {
-        HashMap<Integer, Integer> formatsMap = getFormatsMap(output);
+    private Size[] getInternalFormatSizes(int format, int dataspace, boolean output) {
+
+        HashMap<Integer, Integer> formatsMap =
+                (dataspace == HAL_DATASPACE_DEPTH) ? mDepthOutputFormats : getFormatsMap(output);
 
         Integer sizesCount = formatsMap.get(format);
         if (sizesCount == null) {
@@ -1044,7 +1189,11 @@
         Size[] sizes = new Size[len];
         int sizeIndex = 0;
 
-        for (StreamConfiguration config : mConfigurations) {
+        StreamConfiguration[] configurations =
+                (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations;
+
+
+        for (StreamConfiguration config : configurations) {
             if (config.getFormat() == format && config.isOutput() == output) {
                 sizes[sizeIndex++] = config.getSize();
             }
@@ -1067,15 +1216,19 @@
         for (int format : getFormatsMap(output).keySet()) {
             if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
                 format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
-                formats[i++] = format;
+                formats[i++] = imageFormatToPublic(format);
             }
         }
-
+        if (output) {
+            for (int format : mDepthOutputFormats.keySet()) {
+                formats[i++] = depthFormatToPublic(format);
+            }
+        }
         if (formats.length != i) {
             throw new AssertionError("Too few formats " + i + ", expected " + formats.length);
         }
 
-        return imageFormatToPublic(formats);
+        return formats;
     }
 
     /** Get the format -> size count map for either output or input formats */
@@ -1083,14 +1236,14 @@
         return output ? mOutputFormats : mInputFormats;
     }
 
-    private long getInternalFormatDuration(int format, Size size, int duration) {
+    private long getInternalFormatDuration(int format, int dataspace, Size size, int duration) {
         // assume format is already checked, since its internal
 
-        if (!arrayContains(getInternalFormatSizes(format, /*output*/true), size)) {
+        if (!arrayContains(getInternalFormatSizes(format, dataspace, /*output*/true), size)) {
             throw new IllegalArgumentException("size was not supported");
         }
 
-        StreamConfigurationDuration[] durations = getDurations(duration);
+        StreamConfigurationDuration[] durations = getDurations(duration, dataspace);
 
         for (StreamConfigurationDuration configurationDuration : durations) {
             if (configurationDuration.getFormat() == format &&
@@ -1109,12 +1262,14 @@
      * @see #DURATION_MIN_FRAME
      * @see #DURATION_STALL
      * */
-    private StreamConfigurationDuration[] getDurations(int duration) {
+    private StreamConfigurationDuration[] getDurations(int duration, int dataspace) {
         switch (duration) {
             case DURATION_MIN_FRAME:
-                return mMinFrameDurations;
+                return (dataspace == HAL_DATASPACE_DEPTH) ?
+                        mDepthMinFrameDurations : mMinFrameDurations;
             case DURATION_STALL:
-                return mStallDurations;
+                return (dataspace == HAL_DATASPACE_DEPTH) ?
+                        mDepthStallDurations : mStallDurations;
             default:
                 throw new IllegalArgumentException("duration was invalid");
         }
@@ -1131,6 +1286,9 @@
         if (formatsMap.containsKey(HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
             size -= 1;
         }
+        if (output) {
+            size += mDepthOutputFormats.size();
+        }
 
         return size;
     }
@@ -1153,10 +1311,14 @@
     private static final int HAL_PIXEL_FORMAT_BLOB = 0x21;
     private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
     private static final int HAL_PIXEL_FORMAT_RAW_OPAQUE = 0x24;
+    private static final int HAL_PIXEL_FORMAT_Y16 = 0x20363159;
+
+    private static final int HAL_DATASPACE_UNKNOWN = 0x0;
+    private static final int HAL_DATASPACE_JFIF = 0x101;
+    private static final int HAL_DATASPACE_DEPTH = 0x1000;
 
     /**
-     * @see #getDurations(int)
-     * @see #getDurationDefault(int)
+     * @see #getDurations(int, int)
      */
     private static final int DURATION_MIN_FRAME = 0;
     private static final int DURATION_STALL = 1;
@@ -1164,6 +1326,11 @@
     private final StreamConfiguration[] mConfigurations;
     private final StreamConfigurationDuration[] mMinFrameDurations;
     private final StreamConfigurationDuration[] mStallDurations;
+
+    private final StreamConfiguration[] mDepthConfigurations;
+    private final StreamConfigurationDuration[] mDepthMinFrameDurations;
+    private final StreamConfigurationDuration[] mDepthStallDurations;
+
     private final HighSpeedVideoConfiguration[] mHighSpeedVideoConfigurations;
 
     /** ImageFormat -> num output sizes mapping */
@@ -1172,6 +1339,9 @@
     /** ImageFormat -> num input sizes mapping */
     private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mInputFormats =
             new HashMap<Integer, Integer>();
+    /** ImageFormat -> num depth output sizes mapping */
+    private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mDepthOutputFormats =
+            new HashMap<Integer, Integer>();
     /** High speed video Size -> FPS range count mapping*/
     private final HashMap</*HighSpeedVideoSize*/Size, /*Count*/Integer> mHighSpeedVideoSizeMap =
             new HashMap<Size, Integer>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/core/java/android/hardware/fingerprint/Fingerprint.aidl
similarity index 75%
rename from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
rename to core/java/android/hardware/fingerprint/Fingerprint.aidl
index 272c321..4743354 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/core/java/android/hardware/fingerprint/Fingerprint.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
@@ -13,9 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package android.hardware.fingerprint;
 
-package com.android.systemui.statusbar;
-
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
-}
+// @hide
+parcelable Fingerprint;
diff --git a/core/java/android/hardware/fingerprint/Fingerprint.java b/core/java/android/hardware/fingerprint/Fingerprint.java
new file mode 100644
index 0000000..c307634
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/Fingerprint.java
@@ -0,0 +1,93 @@
+/*
+ * 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.hardware.fingerprint;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Container for fingerprint metadata.
+ * @hide
+ */
+public final class Fingerprint implements Parcelable {
+    private CharSequence mName;
+    private int mGroupId;
+    private int mFingerId;
+    private long mDeviceId; // physical device this is associated with
+
+    public Fingerprint(CharSequence name, int groupId, int fingerId, long deviceId) {
+        mName = name;
+        mGroupId = groupId;
+        mFingerId = fingerId;
+        mDeviceId = deviceId;
+    }
+
+    private Fingerprint(Parcel in) {
+        mName = in.readString();
+        mGroupId = in.readInt();
+        mFingerId = in.readInt();
+        mDeviceId = in.readLong();
+    }
+
+    /**
+     * Gets the human-readable name for the given fingerprint.
+     * @return name given to finger
+     */
+    public CharSequence getName() { return mName; }
+
+    /**
+     * Gets the device-specific finger id.  Used by Settings to map a name to a specific
+     * fingerprint template.
+     * @return device-specific id for this finger
+     * @hide
+     */
+    public int getFingerId() { return mFingerId; }
+
+    /**
+     * Gets the group id specified when the fingerprint was enrolled.
+     * @return group id for the set of fingerprints this one belongs to.
+     * @hide
+     */
+    public int getGroupId() { return mGroupId; }
+
+    /**
+     * Device this fingerprint belongs to.
+     * @hide
+     */
+    public long getDeviceId() { return mDeviceId; }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mName.toString());
+        out.writeInt(mGroupId);
+        out.writeInt(mFingerId);
+        out.writeLong(mDeviceId);
+    }
+
+    public static final Parcelable.Creator<Fingerprint> CREATOR
+            = new Parcelable.Creator<Fingerprint>() {
+        public Fingerprint createFromParcel(Parcel in) {
+            return new Fingerprint(in);
+        }
+
+        public Fingerprint[] newArray(int size) {
+            return new Fingerprint[size];
+        }
+    };
+};
\ No newline at end of file
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
new file mode 100644
index 0000000..e3572a2
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -0,0 +1,563 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fingerprint;
+
+import android.app.ActivityManagerNative;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.Binder;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
+import android.util.Log;
+import android.util.Slog;
+
+import java.security.Signature;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.crypto.Cipher;
+
+/**
+ * A class that coordinates access to the fingerprint hardware.
+ * @hide
+ */
+
+public class FingerprintManager {
+    private static final String TAG = "FingerprintManager";
+    private static final boolean DEBUG = true;
+    private static final int MSG_ENROLL_RESULT = 100;
+    private static final int MSG_ACQUIRED = 101;
+    private static final int MSG_PROCESSED = 102;
+    private static final int MSG_ERROR = 103;
+    private static final int MSG_REMOVED = 104;
+
+    // Message types.  Must agree with HAL (fingerprint.h)
+    public static final int FINGERPRINT_ERROR = -1;
+    public static final int FINGERPRINT_ACQUIRED = 1;
+    public static final int FINGERPRINT_PROCESSED = 2;
+    public static final int FINGERPRINT_TEMPLATE_ENROLLING = 3;
+    public static final int FINGERPRINT_TEMPLATE_REMOVED = 4;
+
+    // Error messages. Must agree with HAL (fingerprint.h)
+    public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
+    public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2;
+    public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
+    public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
+    public static final int FINGERPRINT_ERROR_CANCELED = 5;
+    public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000;
+
+    // Image acquisition messages.  Must agree with HAL (fingerprint.h)
+    public static final int FINGERPRINT_ACQUIRED_GOOD = 0;
+    public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1;
+    public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2;
+    public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3;
+    public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4;
+    public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5;
+    public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
+
+    private IFingerprintService mService;
+    private Context mContext;
+    private IBinder mToken = new Binder();
+    private AuthenticationCallback mAuthenticationCallback;
+    private EnrollmentCallback mEnrollmentCallback;
+    private RemovalCallback mRemovalCallback;
+    private CryptoObject mCryptoObject;
+    private Fingerprint mRemovalFingerprint;
+    private boolean mListening;
+
+    /**
+     * A wrapper class for a limited number of crypto objects supported by FingerprintManager.
+     */
+    public static class CryptoObject {
+        CryptoObject(Signature signature) { mSignature = signature; }
+        CryptoObject(Cipher cipher) { mCipher = cipher; }
+        private Signature mSignature;
+        private Cipher mCipher;
+    };
+
+    /**
+     * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
+     *     AuthenticationCallback, CancellationSignal, int)}
+     */
+    public static final class AuthenticationResult {
+        private Fingerprint mFingerprint;
+        private CryptoObject mCryptoObject;
+
+        public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) {
+            mCryptoObject = crypto;
+            mFingerprint = fingerprint;
+        }
+
+        /**
+         * Obtain the crypto object associated with this transaction
+         * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
+         *     AuthenticationCallback, CancellationSignal, int)}
+         */
+        public CryptoObject getCryptoObject() { return mCryptoObject; }
+
+        /**
+         * Obtain the Fingerprint associated with this operation.  Applications are discouraged
+         * from associating specific fingers with specific applications or operations.  Hence this
+         * is not public.
+         * @hide
+         */
+        public Fingerprint getFingerprint() { return mFingerprint; }
+    };
+
+    /**
+     * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
+     * AuthenticationCallback, CancellationSignal, int)}. Users of {@link #FingerprintManager()}
+     * must provide an implementation of this to {@link FingerprintManager#authenticate(
+     * CryptoObject, AuthenticationCallback, CancellationSignal, int) for listening to fingerprint
+     * events.
+     */
+    public static abstract class AuthenticationCallback {
+        /**
+         * Called when an unrecoverable error has been encountered and the operation is complete.
+         * No further callbacks will be made on this object.
+         * @param errMsgId an integer identifying the error message.
+         * @param errString a human-readible error string that can be shown in UI.
+         */
+        public abstract void onAuthenticationError(int errMsgId, CharSequence errString);
+
+        /**
+         * Called when a recoverable error has been encountered during authentication.  The help
+         * string is provided to give the user guidance for what went wrong, such as
+         * "Sensor dirty, please clean it."
+         * @param helpMsgId an integer identifying the error message.
+         * @param helpString a human-readible string that can be shown in UI.
+         */
+        public abstract void onAuthenticationHelp(int helpMsgId, CharSequence helpString);
+
+        /**
+         * Called when a fingerprint is recognized.
+         * @param result an object containing authentication-related data.
+         */
+        public abstract void onAuthenticationSucceeded(AuthenticationResult result);
+    };
+
+    /**
+     * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback,
+     * CancellationSignal, int). Users of {@link #FingerprintManager()}
+     * must provide an implementation of this to {@link FingerprintManager#enroll(long,
+     * EnrollmentCallback, CancellationSignal, int) for listening to fingerprint events.
+     */
+    public static abstract class EnrollmentCallback {
+        /**
+         * Called when an unrecoverable error has been encountered and the operation is complete.
+         * No further callbacks will be made on this object.
+         * @param errMsgId an integer identifying the error message.
+         * @param errString a human-readible error string that can be shown in UI.
+         */
+        public abstract void onEnrollmentError(int errMsgId, CharSequence errString);
+
+        /**
+         * Called when a recoverable error has been encountered during enrollment.  The help
+         * string is provided to give the user guidance for what went wrong, such as
+         * "Sensor dirty, please clean it" or what they need to do next, such as
+         * "Touch sensor again."
+         * @param helpMsgId an integer identifying the error message.
+         * @param helpString a human-readible string that can be shown in UI.
+         */
+        public abstract void onEnrollmentHelp(int helpMsgId, CharSequence helpString);
+
+        /**
+         * Called as each enrollment step progresses. Enrollment is considered complete when
+         * remaining reaches 0.  This function will not be called if enrollment fails. See
+         * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
+         * @param remaining the number of remaining steps.
+         */
+        public abstract void onEnrollmentProgress(int remaining);
+    };
+
+    /**
+     * Callback structure provided to {@link FingerprintManager#remove(int). Users of
+     * {@link #FingerprintManager()} may optionally provide an implementation of this to
+     * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to
+     * fingerprint template removal events.
+     */
+    public static abstract class RemovalCallback {
+        /**
+         * Called when the given fingerprint can't be removed.
+         * @param fp the fingerprint that the call attempted to remove.
+         * @param errMsgId an associated error message id.
+         * @param errString an error message indicating why the fingerprint id can't be removed.
+         */
+        public abstract void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString);
+
+        /**
+         * Called when a given fingerprint is successfully removed.
+         * @param fingerprint the fingerprint template that was removed.
+         */
+        public abstract void onRemovalSucceeded(Fingerprint fingerprint);
+    };
+
+    /**
+     * Request authentication of a crypto object.  This call warms up the fingerprint hardware
+     * and starts scanning for a fingerprint.  It terminates when
+     * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
+     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at
+     * which point the object is no longer valid. The operation can be canceled by using the
+     * provided cancel object.
+     *
+     * @param crypto object associated with the call or null if none required.
+     * @param callback an object to receive authentication events
+     * @param cancel an object that can be used to cancel authentication
+     * @param flags optional flags
+     */
+    public void authenticate(CryptoObject crypto, AuthenticationCallback callback,
+            CancellationSignal cancel, int flags) {
+        if (callback == null) {
+            throw new IllegalArgumentException("Must supply an authentication callback");
+        }
+
+        // TODO: handle cancel
+
+        if (mService != null) try {
+            mAuthenticationCallback = callback;
+            mCryptoObject = crypto;
+            long sessionId = 0; // TODO: get from crypto object
+            startListening();
+            mService.authenticate(mToken, sessionId, getCurrentUserId(), flags);
+        } catch (RemoteException e) {
+            Log.v(TAG, "Remote exception while authenticating: ", e);
+            stopListening();
+        }
+    }
+
+    /**
+     * Request fingerprint enrollment. This call warms up the fingerprint hardware
+     * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
+     * {@link EnrollmentCallback} object. It terminates when
+     * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or
+     * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at
+     * which point the object is no longer valid. The operation can be canceled by using the
+     * provided cancel object.
+     * @param challenge a unique id provided by a recent verification of device credentials
+     *     (e.g. pin, pattern or password).
+     * @param callback an object to receive enrollment events
+     * @param cancel an object that can be used to cancel enrollment
+     * @param flags optional flags
+     */
+    public void enroll(long challenge, EnrollmentCallback callback,
+            CancellationSignal cancel, int flags) {
+        if (callback == null) {
+            throw new IllegalArgumentException("Must supply an enrollment callback");
+        }
+
+        // TODO: handle cancel
+
+        if (mService != null) try {
+            mEnrollmentCallback = callback;
+            startListening();
+            mService.enroll(mToken, getCurrentUserId(), flags);
+        } catch (RemoteException e) {
+            Log.v(TAG, "Remote exception in enroll: ", e);
+            stopListening();
+        }
+    }
+
+    /**
+     * Remove given fingerprint template from fingerprint hardware and/or protected storage.
+     * @param fp the fingerprint item to remove
+     * @param callback an optional callback to verify that fingerprint templates have been
+     * successfully removed.  May be null of no callback is required.
+     * @hide
+     */
+    public void remove(Fingerprint fp, RemovalCallback callback) {
+        if (mService != null) try {
+            mRemovalCallback = callback;
+            mRemovalFingerprint = fp;
+            startListening();
+            mService.remove(mToken, fp.getFingerId(), getCurrentUserId());
+        } catch (RemoteException e) {
+            Log.v(TAG, "Remote in remove: ", e);
+            stopListening();
+        }
+    }
+
+    /**
+     * Renames the given fingerprint template
+     * @param fpId the fingerprint id
+     * @param newName the new name
+     * @hide
+     */
+    public void rename(int fpId, String newName) {
+        // Renames the given fpId
+        if (mService != null) {
+            try {
+                mService.rename(fpId, getCurrentUserId(), newName);
+            } catch (RemoteException e) {
+                Log.v(TAG, "Remote exception in rename(): ", e);
+            }
+        } else {
+            Log.w(TAG, "rename(): Service not connected!");
+        }
+    }
+
+    /**
+     * Obtain the list of enrolled fingerprints templates.
+     * @return list of current fingerprint items
+     */
+    public List<Fingerprint> getEnrolledFingerprints() {
+        if (mService != null) try {
+            return mService.getEnrolledFingerprints(getCurrentUserId());
+        } catch (RemoteException e) {
+            Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
+        }
+        return null;
+    }
+
+    /**
+     * Determine if fingerprint hardware is present and functional.
+     * @return true if hardware is present and functional, false otherwise.
+     * @hide
+     */
+    public boolean isHardwareDetected() {
+        if (mService != null) {
+            try {
+                long deviceId = 0; /* TODO: plumb hardware id to FPMS */
+                return mService.isHardwareDetected(deviceId);
+            } catch (RemoteException e) {
+                Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e);
+            }
+        } else {
+            Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
+        }
+        return false;
+    }
+
+    private Handler mHandler = new Handler() {
+        public void handleMessage(android.os.Message msg) {
+            switch(msg.what) {
+                case MSG_ENROLL_RESULT:
+                    sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
+                    break;
+                case MSG_ACQUIRED:
+                    sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */);
+                    break;
+                case MSG_PROCESSED:
+                    sendProcessedResult((Fingerprint) msg.obj);
+                    break;
+                case MSG_ERROR:
+                    sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */);
+                    break;
+                case MSG_REMOVED:
+                    sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
+                            msg.arg2 /* groupId */);
+            }
+        }
+
+        private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
+            if (mRemovalCallback != null) {
+                int reqFingerId = mRemovalFingerprint.getFingerId();
+                int reqGroupId = mRemovalFingerprint.getGroupId();
+                if (fingerId != reqFingerId) {
+                    Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
+                }
+                if (fingerId != reqFingerId) {
+                    Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
+                }
+                mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint);
+            }
+        }
+
+        private void sendErrorResult(long deviceId, int errMsgId) {
+            if (mEnrollmentCallback != null) {
+                mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId));
+            } else if (mAuthenticationCallback != null) {
+                mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId));
+            } else if (mRemovalCallback != null) {
+                mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId,
+                        getErrorString(errMsgId));
+            }
+        }
+
+        private void sendEnrollResult(Fingerprint fp, int remaining) {
+            if (mEnrollmentCallback != null) {
+                mEnrollmentCallback.onEnrollmentProgress(remaining);
+            }
+        }
+
+        private void sendProcessedResult(Fingerprint fp) {
+            if (mAuthenticationCallback != null) {
+                AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
+                mAuthenticationCallback.onAuthenticationSucceeded(result);
+            }
+        }
+
+        private void sendAcquiredResult(long deviceId, int acquireInfo) {
+            final String msg = getAcquiredString(acquireInfo);
+            if (msg == null) return;
+
+            if (mEnrollmentCallback != null) {
+                mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg);
+            } else if (mAuthenticationCallback != null) {
+                mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg);
+            }
+        }
+
+        private String getErrorString(int errMsg) {
+            switch (errMsg) {
+                case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
+                    return mContext.getString(
+                        com.android.internal.R.string.fingerprint_error_unable_to_process);
+                case FINGERPRINT_ERROR_HW_UNAVAILABLE:
+                    return mContext.getString(
+                        com.android.internal.R.string.fingerprint_error_hw_not_available);
+                case FINGERPRINT_ERROR_NO_SPACE:
+                    return mContext.getString(
+                        com.android.internal.R.string.fingerprint_error_no_space);
+                case FINGERPRINT_ERROR_TIMEOUT:
+                    return mContext.getString(
+                        com.android.internal.R.string.fingerprint_error_timeout);
+                default:
+                    if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) {
+                        int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE;
+                        String[] msgArray = mContext.getResources().getStringArray(
+                                com.android.internal.R.array.fingerprint_error_vendor);
+                        if (msgNumber < msgArray.length) {
+                            return msgArray[msgNumber];
+                        }
+                    }
+                    return null;
+            }
+        }
+
+        private String getAcquiredString(int acquireInfo) {
+            switch (acquireInfo) {
+                case FINGERPRINT_ACQUIRED_GOOD:
+                    return null;
+                case FINGERPRINT_ACQUIRED_PARTIAL:
+                    return mContext.getString(
+                        com.android.internal.R.string.fingerprint_acquired_partial);
+                case FINGERPRINT_ACQUIRED_INSUFFICIENT:
+                    return mContext.getString(
+                        com.android.internal.R.string.fingerprint_acquired_insufficient);
+                case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
+                    return mContext.getString(
+                        com.android.internal.R.string.fingerprint_acquired_imager_dirty);
+                case FINGERPRINT_ACQUIRED_TOO_SLOW:
+                    return mContext.getString(
+                        com.android.internal.R.string.fingerprint_acquired_too_slow);
+                case FINGERPRINT_ACQUIRED_TOO_FAST:
+                    return mContext.getString(
+                        com.android.internal.R.string.fingerprint_acquired_too_fast);
+                default:
+                    if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) {
+                        int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE;
+                        String[] msgArray = mContext.getResources().getStringArray(
+                                com.android.internal.R.array.fingerprint_acquired_vendor);
+                        if (msgNumber < msgArray.length) {
+                            return msgArray[msgNumber];
+                        }
+                    }
+                    return null;
+            }
+        }
+    };
+
+    /**
+     * @hide
+     */
+    public FingerprintManager(Context context, IFingerprintService service) {
+        mContext = context;
+        mService = service;
+        if (mService == null) {
+            Slog.v(TAG, "FingerprintManagerService was null");
+        }
+    }
+
+    private int getCurrentUserId() {
+        try {
+            return ActivityManagerNative.getDefault().getCurrentUser().id;
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to get current user id\n");
+            return UserHandle.USER_NULL;
+        }
+    }
+
+    /**
+     * Stops the client from listening to fingerprint events.
+     */
+    private void stopListening() {
+        if (mService != null) {
+            try {
+                if (mListening) {
+                    mService.removeListener(mToken, mServiceReceiver);
+                    mListening = false;
+                }
+            } catch (RemoteException e) {
+                Log.v(TAG, "Remote exception in stopListening(): ", e);
+            }
+        } else {
+            Log.w(TAG, "stopListening(): Service not connected!");
+        }
+    }
+
+    /**
+     * Starts listening for fingerprint events for this client.
+     */
+    private void startListening() {
+        if (mService != null) {
+            try {
+                if (!mListening) {
+                    mService.addListener(mToken, mServiceReceiver, getCurrentUserId());
+                    mListening = true;
+                }
+            } catch (RemoteException e) {
+                Log.v(TAG, "Remote exception in startListening(): ", e);
+            }
+        } else {
+            Log.w(TAG, "startListening(): Service not connected!");
+        }
+    }
+
+    private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
+
+        public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
+            mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
+                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
+        }
+
+        public void onAcquired(long deviceId, int acquireInfo) {
+            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
+        }
+
+        public void onProcessed(long deviceId, int fingerId, int groupId) {
+            mHandler.obtainMessage(MSG_PROCESSED,
+                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
+        }
+
+        public void onError(long deviceId, int error) {
+            mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
+        }
+
+        public void onRemoved(long deviceId, int fingerId, int groupId) {
+            mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
+        }
+    };
+
+}
\ No newline at end of file
diff --git a/core/java/android/service/fingerprint/FingerprintUtils.java b/core/java/android/hardware/fingerprint/FingerprintUtils.java
similarity index 96%
rename from core/java/android/service/fingerprint/FingerprintUtils.java
rename to core/java/android/hardware/fingerprint/FingerprintUtils.java
index cc17b99..ae3d4a4 100644
--- a/core/java/android/service/fingerprint/FingerprintUtils.java
+++ b/core/java/android/hardware/fingerprint/FingerprintUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.service.fingerprint;
+package android.hardware.fingerprint;
 
 import android.content.ContentResolver;
 import android.provider.Settings;
@@ -67,7 +67,7 @@
         return toIntArray(tmp);
     }
 
-    public static void addFingerprintIdForUser(int fingerId, ContentResolver res, int userId) {
+    public static void addFingerprintIdForUser(ContentResolver res, int fingerId, int userId) {
         // FingerId 0 has special meaning.
         if (fingerId == 0) {
             Log.w(TAG, "Tried to add fingerId 0");
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
new file mode 100644
index 0000000..c5a45e2
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.fingerprint;
+
+import android.os.Bundle;
+import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import android.hardware.fingerprint.Fingerprint;
+import java.util.List;
+
+/**
+ * Communication channel from client to the fingerprint service.
+ * @hide
+ */
+interface IFingerprintService {
+    // Authenticate the given sessionId with a fingerprint
+    void authenticate(IBinder token, long sessionId, int groupId, int flags);
+
+    // Start fingerprint enrollment
+    void enroll(IBinder token, int groupId, int flags);
+
+    // Any errors resulting from this call will be returned to the listener
+    void remove(IBinder token, int fingerId, int groupId);
+
+    // Rename the fingerprint specified by fingerId and groupId to the given name
+    void rename(int fingerId, int groupId, String name);
+
+    // Get a list of enrolled fingerprints in the given group.
+    List<Fingerprint> getEnrolledFingerprints(int groupId);
+
+    // Register listener for an instance of FingerprintManager
+    void addListener(IBinder token, IFingerprintServiceReceiver receiver, int userId);
+
+    // Unregister listener for an instance of FingerprintManager
+    void removeListener(IBinder token, IFingerprintServiceReceiver receiver);
+
+    // Determine if HAL is loaded and ready
+    boolean isHardwareDetected(long deviceId);
+
+    // Gets the number of hardware devices
+    // int getHardwareDeviceCount();
+
+    // Gets the unique device id for hardware enumerated at i
+    // long getHardwareDevice(int i);
+
+}
diff --git a/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
similarity index 70%
rename from core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl
rename to core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
index af4128f..e82395f 100644
--- a/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.fingerprint;
+package android.hardware.fingerprint;
 
 import android.os.Bundle;
 import android.os.UserHandle;
@@ -23,9 +23,9 @@
  * @hide
  */
 oneway interface IFingerprintServiceReceiver {
-    void onEnrollResult(int fingerprintId,  int remaining);
-    void onAcquired(int acquiredInfo);
-    void onProcessed(int fingerprintId);
-    void onError(int error);
-    void onRemoved(int fingerprintId);
+    void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining);
+    void onAcquired(long deviceId, int acquiredInfo);
+    void onProcessed(long deviceId, int fingerId, int groupId);
+    void onError(long deviceId, int error);
+    void onRemoved(long deviceId, int fingerId, int groupId);
 }
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
index a94c1da..a336e5c 100644
--- a/core/java/android/hardware/hdmi/HdmiTvClient.java
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -168,7 +168,22 @@
     }
 
     /**
-     * Sets system audio volume
+     * Sets system audio mode.
+     *
+     * @param enabled set to {@code true} to enable the mode; otherwise {@code false}
+     * @param callback callback to get the result with
+     * @throws {@link IllegalArgumentException} if the {@code callback} is null
+     */
+    public void setSystemAudioMode(boolean enabled, SelectCallback callback) {
+        try {
+            mService.setSystemAudioMode(enabled, getCallbackWrapper(callback));
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to set system audio mode:", e);
+        }
+    }
+
+    /**
+     * Sets system audio volume.
      *
      * @param oldIndex current volume index
      * @param newIndex volume index to be set
@@ -183,7 +198,7 @@
     }
 
     /**
-     * Sets system audio mute status
+     * Sets system audio mute status.
      *
      * @param mute {@code true} if muted; otherwise, {@code false}
      */
@@ -196,7 +211,7 @@
     }
 
     /**
-     * Sets record listener
+     * Sets record listener.
      *
      * @param listener
      */
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 34a0727..3abccbc 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -40,6 +40,7 @@
 import android.util.ArrayMap;
 import android.util.Log;
 
+import com.android.internal.net.VpnConfig;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.Protocol;
@@ -2337,7 +2338,7 @@
      * successfully finding a network for the applications request.  Retrieve it with
      * {@link android.content.Intent#getParcelableExtra(String)}.
      * <p>
-     * Note that if you intend to invoke (@link #setProcessDefaultNetwork(Network)) or
+     * Note that if you intend to invoke {@link #setProcessDefaultNetwork} or
      * {@link Network#openConnection(java.net.URL)} then you must get a
      * ConnectivityManager instance before doing so.
      */
@@ -2447,6 +2448,38 @@
     }
 
     /**
+     * Resets all connectivity manager settings back to factory defaults.
+     * @hide
+     */
+    public void factoryReset() {
+        // Turn airplane mode off
+        setAirplaneMode(false);
+
+        // Untether
+        for (String tether : getTetheredIfaces()) {
+            untether(tether);
+        }
+
+        // Turn VPN off
+        try {
+            VpnConfig vpnConfig = mService.getVpnConfig();
+            if (vpnConfig != null) {
+                if (vpnConfig.legacy) {
+                    mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN);
+                } else {
+                    // Prevent this app from initiating VPN connections in the future without
+                    // user intervention.
+                    mService.setVpnPackageAuthorization(false);
+
+                    mService.prepareVpn(vpnConfig.user, VpnConfig.LEGACY_VPN);
+                }
+            }
+        } catch (RemoteException e) {
+            // Well, we tried
+        }
+    }
+
+    /**
      * Binds the current process to {@code network}.  All Sockets created in the future
      * (and not explicitly bound via a bound SocketFactory from
      * {@link Network#getSocketFactory() Network.getSocketFactory()}) will be bound to
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 2c3881c..6436e42 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -27,6 +27,14 @@
     /** Start a statistics query session. */
     INetworkStatsSession openSession();
 
+    /** Start a statistics query session. If calling package is profile or device owner then it is
+     *  granted automatic access if apiLevel is NetworkStatsManager.API_LEVEL_DPC_ALLOWED. If
+     *  apiLevel is at least NetworkStatsManager.API_LEVEL_REQUIRES_PACKAGE_USAGE_STATS then
+     *  PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted
+     *  READ_NETWORK_USAGE_STATS is checked for.
+     */
+    INetworkStatsSession openSessionForUsageStats(String callingPackage);
+
     /** Return network layer usage total for traffic that matches template. */
     long getNetworkTotalBytes(in NetworkTemplate template, long start, long end);
 
diff --git a/core/java/android/net/INetworkStatsSession.aidl b/core/java/android/net/INetworkStatsSession.aidl
index 1596fa2..7bcb043 100644
--- a/core/java/android/net/INetworkStatsSession.aidl
+++ b/core/java/android/net/INetworkStatsSession.aidl
@@ -23,6 +23,9 @@
 /** {@hide} */
 interface INetworkStatsSession {
 
+    /** Return device aggregated network layer usage summary for traffic that matches template. */
+    NetworkStats getDeviceSummaryForNetwork(in NetworkTemplate template, long start, long end);
+
     /** Return network layer usage summary for traffic that matches template. */
     NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
     /** Return historical network layer stats for traffic that matches template. */
@@ -33,6 +36,9 @@
     /** Return historical network layer stats for specific UID traffic that matches template. */
     NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
 
+    /** Return array of uids that have stats and are accessible to the calling user */
+    int[] getRelevantUids();
+
     void close();
 
 }
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index a7f9c5b..8c8bfab 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -148,9 +148,9 @@
      */
     public static final int NET_CAPABILITY_TRUSTED        = 14;
 
-    /*
+    /**
      * Indicates that this network is not a VPN.  This capability is set by default and should be
-     * explicitly cleared when creating VPN networks.
+     * explicitly cleared for VPN networks.
      */
     public static final int NET_CAPABILITY_NOT_VPN        = 15;
 
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index a8e7757..a7ffee9 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -180,6 +180,33 @@
     }
 
     /**
+     * Resets network policy settings back to factory defaults.
+     *
+     * @hide
+     */
+    public void factoryReset(String subscriber) {
+        // Turn mobile data limit off
+        NetworkPolicy[] policies = getNetworkPolicies();
+        NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriber);
+        for (NetworkPolicy policy : policies) {
+            if (policy.template.equals(template)) {
+                policy.limitBytes = NetworkPolicy.LIMIT_DISABLED;
+                policy.inferred = false;
+                policy.clearSnooze();
+            }
+        }
+        setNetworkPolicies(policies);
+
+        // Turn restrict background data off
+        setRestrictBackground(false);
+
+        // Remove app's "restrict background data" flag
+        for (int uid : getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) {
+            setUidPolicy(uid, NetworkPolicyManager.POLICY_NONE);
+        }
+    }
+
+    /**
      * Compute the last cycle boundary for the given {@link NetworkPolicy}. For
      * example, if cycle day is 20th, and today is June 15th, it will return May
      * 20th. When cycle day doesn't exist in current month, it snaps to the 1st
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 0766253..77d7e0c 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -50,12 +50,19 @@
     public static final int UID_ALL = -1;
     /** {@link #tag} value matching any tag. */
     public static final int TAG_ALL = -1;
-    /** {@link #set} value when all sets combined. */
+    /** {@link #set} value when all sets combined, not including debug sets. */
     public static final int SET_ALL = -1;
     /** {@link #set} value where background data is accounted. */
     public static final int SET_DEFAULT = 0;
     /** {@link #set} value where foreground data is accounted. */
     public static final int SET_FOREGROUND = 1;
+    /** All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values. */
+    public static final int SET_DEBUG_START = 1000;
+    /** Debug {@link #set} value when the VPN stats are moved in. */
+    public static final int SET_DBG_VPN_IN = 1001;
+    /** Debug {@link #set} value when the VPN stats are moved out of a vpn UID. */
+    public static final int SET_DBG_VPN_OUT = 1002;
+
     /** {@link #tag} value for total data across all tags. */
     public static final int TAG_NONE = 0;
 
@@ -729,6 +736,10 @@
                 return "DEFAULT";
             case SET_FOREGROUND:
                 return "FOREGROUND";
+            case SET_DBG_VPN_IN:
+                return "DBG_VPN_IN";
+            case SET_DBG_VPN_OUT:
+                return "DBG_VPN_OUT";
             default:
                 return "UNKNOWN";
         }
@@ -745,12 +756,27 @@
                 return "def";
             case SET_FOREGROUND:
                 return "fg";
+            case SET_DBG_VPN_IN:
+                return "vpnin";
+            case SET_DBG_VPN_OUT:
+                return "vpnout";
             default:
                 return "unk";
         }
     }
 
     /**
+     * @return true if the querySet matches the dataSet.
+     */
+    public static boolean setMatches(int querySet, int dataSet) {
+        if (querySet == dataSet) {
+            return true;
+        }
+        // SET_ALL matches all non-debugging sets.
+        return querySet == SET_ALL && dataSet < SET_DEBUG_START;
+    }
+
+    /**
      * Return text description of {@link #tag} value.
      */
     public static String tagToString(int tag) {
@@ -843,6 +869,9 @@
             if (recycle.uid == UID_ALL) {
                 throw new IllegalStateException(
                         "Cannot adjust VPN accounting on an iface aggregated NetworkStats.");
+            } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
+                throw new IllegalStateException(
+                        "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*");
             }
 
             if (recycle.uid == tunUid && recycle.tag == TAG_NONE
@@ -906,6 +935,9 @@
                 combineValues(tmpEntry);
                 if (tag[i] == TAG_NONE) {
                     moved.add(tmpEntry);
+                    // Add debug info
+                    tmpEntry.set = SET_DBG_VPN_IN;
+                    combineValues(tmpEntry);
                 }
             }
         }
@@ -913,6 +945,13 @@
     }
 
     private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) {
+        // Add debug info
+        moved.uid = tunUid;
+        moved.set = SET_DBG_VPN_OUT;
+        moved.tag = TAG_NONE;
+        moved.iface = underlyingIface;
+        combineValues(moved);
+
         // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
         // the TAG_NONE traffic.
         int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE);
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 3f18519..ff3de2b 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -51,6 +51,8 @@
     public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
     /** @hide */
     public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
+    /** @hide */
+    public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
 
     /**
      * Special UID value used when collecting {@link NetworkStatsHistory} for
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index bf3d9aa..f305b2a 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -366,7 +366,6 @@
     public String toSafeString() {
         String scheme = getScheme();
         String ssp = getSchemeSpecificPart();
-        String authority = null;
         if (scheme != null) {
             if (scheme.equalsIgnoreCase("tel") || scheme.equalsIgnoreCase("sip")
                     || scheme.equalsIgnoreCase("sms") || scheme.equalsIgnoreCase("smsto")
@@ -385,9 +384,11 @@
                     }
                 }
                 return builder.toString();
-            } else if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) {
-                ssp = null;
-                authority = "//" + getAuthority() + "/...";
+            } else if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")
+                    || scheme.equalsIgnoreCase("ftp")) {
+                ssp = "//" + ((getHost() != null) ? getHost() : "")
+                        + ((getPort() != -1) ? (":" + getPort()) : "")
+                        + "/...";
             }
         }
         // Not a sensitive scheme, but let's still be conservative about
@@ -401,9 +402,6 @@
         if (ssp != null) {
             builder.append(ssp);
         }
-        if (authority != null) {
-            builder.append(authority);
-        }
         return builder.toString();
     }
 
diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java
index 71df2f9..99de99e 100644
--- a/core/java/android/net/WifiKey.java
+++ b/core/java/android/net/WifiKey.java
@@ -33,7 +33,8 @@
 public class WifiKey implements Parcelable {
 
     // Patterns used for validation.
-    private static final Pattern SSID_PATTERN = Pattern.compile("(\".*\")|(0x[\\p{XDigit}]+)");
+    private static final Pattern SSID_PATTERN = Pattern.compile("(\".*\")|(0x[\\p{XDigit}]+)",
+            Pattern.DOTALL);
     private static final Pattern BSSID_PATTERN =
             Pattern.compile("([\\p{XDigit}]{2}:){5}[\\p{XDigit}]{2}");
 
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index cab03da..508fdee 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -29,6 +29,7 @@
 import android.content.pm.ApplicationInfo;
 import android.telephony.SignalStrength;
 import android.text.format.DateFormat;
+import android.util.ArrayMap;
 import android.util.Printer;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
@@ -283,21 +284,21 @@
          *
          * @return a Map from Strings to Uid.Wakelock objects.
          */
-        public abstract Map<String, ? extends Wakelock> getWakelockStats();
+        public abstract ArrayMap<String, ? extends Wakelock> getWakelockStats();
 
         /**
          * Returns a mapping containing sync statistics.
          *
          * @return a Map from Strings to Timer objects.
          */
-        public abstract Map<String, ? extends Timer> getSyncStats();
+        public abstract ArrayMap<String, ? extends Timer> getSyncStats();
 
         /**
          * Returns a mapping containing scheduled job statistics.
          *
          * @return a Map from Strings to Timer objects.
          */
-        public abstract Map<String, ? extends Timer> getJobStats();
+        public abstract ArrayMap<String, ? extends Timer> getJobStats();
 
         /**
          * The statistics associated with a particular wake lock.
@@ -323,14 +324,14 @@
          *
          * @return a Map from Strings to Uid.Proc objects.
          */
-        public abstract Map<String, ? extends Proc> getProcessStats();
+        public abstract ArrayMap<String, ? extends Proc> getProcessStats();
 
         /**
          * Returns a mapping containing package statistics.
          *
          * @return a Map from Strings to Uid.Pkg objects.
          */
-        public abstract Map<String, ? extends Pkg> getPackageStats();
+        public abstract ArrayMap<String, ? extends Pkg> getPackageStats();
         
         /**
          * {@hide}
@@ -501,17 +502,16 @@
         public static abstract class Pkg {
 
             /**
-             * Returns the number of times this package has done something that could wake up the
-             * device from sleep.
-             *
-             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
+             * Returns information about all wakeup alarms that have been triggered for this
+             * package.  The mapping keys are tag names for the alarms, the counter contains
+             * the number of times the alarm was triggered while on battery.
              */
-            public abstract int getWakeups(int which);
+            public abstract ArrayMap<String, ? extends Counter> getWakeupAlarmStats();
 
             /**
              * Returns a mapping containing service statistics.
              */
-            public abstract Map<String, ? extends Serv> getServiceStats();
+            public abstract ArrayMap<String, ? extends Serv> getServiceStats();
 
             /**
              * The statistics associated with a particular service.
@@ -613,6 +613,9 @@
             if ((initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0) {
                 out.append('p');
             }
+            if ((initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0) {
+                out.append('i');
+            }
             switch ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
                 case Display.STATE_OFF: out.append('F'); break;
                 case Display.STATE_ON: out.append('O'); break;
@@ -622,6 +625,9 @@
             if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) != 0) {
                 out.append('P');
             }
+            if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0) {
+                out.append('I');
+            }
             out.append('-');
             appendHex(level, 4, out);
             out.append('-');
@@ -648,6 +654,9 @@
                     case 'p': out |= (((long)STEP_LEVEL_MODE_POWER_SAVE)
                             << STEP_LEVEL_INITIAL_MODE_SHIFT);
                         break;
+                    case 'i': out |= (((long)STEP_LEVEL_MODE_DEVICE_IDLE)
+                            << STEP_LEVEL_INITIAL_MODE_SHIFT);
+                        break;
                     case 'F': out |= (((long)Display.STATE_OFF-1)<<STEP_LEVEL_MODIFIED_MODE_SHIFT);
                         break;
                     case 'O': out |= (((long)Display.STATE_ON-1)<<STEP_LEVEL_MODIFIED_MODE_SHIFT);
@@ -660,6 +669,9 @@
                     case 'P': out |= (((long)STEP_LEVEL_MODE_POWER_SAVE)
                             << STEP_LEVEL_MODIFIED_MODE_SHIFT);
                         break;
+                    case 'I': out |= (((long)STEP_LEVEL_MODE_DEVICE_IDLE)
+                            << STEP_LEVEL_MODIFIED_MODE_SHIFT);
+                        break;
                 }
             }
             i++;
@@ -820,11 +832,18 @@
         }
     }
 
+    public static final class PackageChange {
+        public String mPackageName;
+        public boolean mUpdate;
+        public int mVersionCode;
+    }
+
     public static final class DailyItem {
         public long mStartTime;
         public long mEndTime;
         public LevelStepTracker mDischargeSteps;
         public LevelStepTracker mChargeSteps;
+        public ArrayList<PackageChange> mPackageChanges;
     }
 
     public abstract DailyItem getDailyItemLocked(int daysAgo);
@@ -1333,7 +1352,7 @@
                 int idx = code&HistoryItem.EVENT_TYPE_MASK;
                 HashMap<String, SparseIntArray> active = mActiveEvents[idx];
                 if (active == null) {
-                    active = new HashMap<String, SparseIntArray>();
+                    active = new HashMap<>();
                     mActiveEvents[idx] = active;
                 }
                 SparseIntArray uids = active.get(name);
@@ -1524,6 +1543,23 @@
     public abstract int getDeviceIdleModeEnabledCount(int which);
 
     /**
+     * Returns the time in microseconds that device has been in idling while on
+     * battery.  This is broader than {@link #getDeviceIdleModeEnabledTime} -- it
+     * counts all of the time that we consider the device to be idle, whether or not
+     * it is currently in the actual device idle mode.
+     *
+     * {@hide}
+     */
+    public abstract long getDeviceIdlingTime(long elapsedRealtimeUs, int which);
+
+    /**
+     * Returns the number of times that the devie has started idling.
+     *
+     * {@hide}
+     */
+    public abstract int getDeviceIdlingCount(int which);
+
+    /**
      * Returns the number of times that connectivity state changed.
      *
      * {@hide}
@@ -2069,45 +2105,44 @@
     // Step duration mode: power save is on.
     public static final int STEP_LEVEL_MODE_POWER_SAVE = 0x04;
 
+    // Step duration mode: device is currently in idle mode.
+    public static final int STEP_LEVEL_MODE_DEVICE_IDLE = 0x08;
+
     public static final int[] STEP_LEVEL_MODES_OF_INTEREST = new int[] {
             STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE|STEP_LEVEL_MODE_DEVICE_IDLE,
+            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_DEVICE_IDLE,
             STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
             STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
             STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
             STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
             STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
-            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
-            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE|STEP_LEVEL_MODE_DEVICE_IDLE,
+            STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_DEVICE_IDLE,
     };
     public static final int[] STEP_LEVEL_MODE_VALUES = new int[] {
             (Display.STATE_OFF-1),
             (Display.STATE_OFF-1)|STEP_LEVEL_MODE_POWER_SAVE,
+            (Display.STATE_OFF-1)|STEP_LEVEL_MODE_DEVICE_IDLE,
             (Display.STATE_ON-1),
             (Display.STATE_ON-1)|STEP_LEVEL_MODE_POWER_SAVE,
             (Display.STATE_DOZE-1),
             (Display.STATE_DOZE-1)|STEP_LEVEL_MODE_POWER_SAVE,
             (Display.STATE_DOZE_SUSPEND-1),
             (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_POWER_SAVE,
+            (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_DEVICE_IDLE,
     };
     public static final String[] STEP_LEVEL_MODE_LABELS = new String[] {
             "screen off",
             "screen off power save",
+            "screen off device idle",
             "screen on",
             "screen on power save",
             "screen doze",
             "screen doze power save",
             "screen doze-suspend",
             "screen doze-suspend power save",
-    };
-    public static final String[] STEP_LEVEL_MODE_TAGS = new String[] {
-            "off",
-            "off-save",
-            "on",
-            "on-save",
-            "doze",
-            "doze-save",
-            "susp",
-            "susp-save",
+            "screen doze-suspend device idle",
     };
 
     /**
@@ -2140,6 +2175,8 @@
      */
     public abstract LevelStepTracker getDailyChargeLevelStepTracker();
 
+    public abstract ArrayList<PackageChange> getDailyPackageChanges();
+
     public abstract Map<String, ? extends Timer> getWakeupReasonStats();
 
     public abstract Map<String, ? extends Timer> getKernelWakelockStats();
@@ -2338,18 +2375,19 @@
         final long interactiveTime = getInteractiveTime(rawRealtime, which);
         final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
         final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
+        final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
         final int connChanges = getNumConnectivityChange(which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
         final long wifiOnTime = getWifiOnTime(rawRealtime, which);
         final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
         final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
 
-        StringBuilder sb = new StringBuilder(128);
+        final StringBuilder sb = new StringBuilder(128);
         
-        SparseArray<? extends Uid> uidStats = getUidStats();
+        final SparseArray<? extends Uid> uidStats = getUidStats();
         final int NU = uidStats.size();
         
-        String category = STAT_NAMES[which];
+        final String category = STAT_NAMES[which];
 
         // Dump "battery" stat
         dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, 
@@ -2364,37 +2402,35 @@
         long partialWakeLockTimeTotal = 0;
         
         for (int iu = 0; iu < NU; iu++) {
-            Uid u = uidStats.valueAt(iu);
+            final Uid u = uidStats.valueAt(iu);
 
-            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
-            if (wakelocks.size() > 0) {
-                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent 
-                        : wakelocks.entrySet()) {
-                    Uid.Wakelock wl = ent.getValue();
-                    
-                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
-                    if (fullWakeTimer != null) {
-                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime,
-                                which);
-                    }
+            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
+                    = u.getWakelockStats();
+            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
+                final Uid.Wakelock wl = wakelocks.valueAt(iw);
 
-                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
-                    if (partialWakeTimer != null) {
-                        partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
-                            rawRealtime, which);
-                    }
+                final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
+                if (fullWakeTimer != null) {
+                    fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime,
+                            which);
+                }
+
+                final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
+                if (partialWakeTimer != null) {
+                    partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
+                        rawRealtime, which);
                 }
             }
         }
         
-        long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
-        long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
-        long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
-        long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
-        long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
-        long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
-        long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
-        long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
+        final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
+        final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
+        final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
+        final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
+        final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
+        final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
+        final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
+        final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
 
         // Dump network stats
         dumpLine(pw, 0 /* uid */, category, GLOBAL_NETWORK_DATA,
@@ -2410,7 +2446,8 @@
                 0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which) / 1000,
                 getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000,
                 powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeEnabledTime / 1000,
-                getDeviceIdleModeEnabledCount(which));
+                getDeviceIdleModeEnabledCount(which), deviceIdlingTime / 1000,
+                getDeviceIdlingCount(which));
         
         // Dump screen brightness stats
         Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
@@ -2505,7 +2542,7 @@
         }
         
         if (reqUid < 0) {
-            Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
+            final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
             if (kernelWakelocks.size() > 0) {
                 for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
                     sb.setLength(0);
@@ -2514,7 +2551,7 @@
                             sb.toString());
                 }
             }
-            Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
+            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
             if (wakeupReasons.size() > 0) {
                 for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
                     // Not doing the regular wake lock formatting to remain compatible
@@ -2527,10 +2564,10 @@
             }
         }
         
-        BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
+        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
         helper.create(this);
         helper.refreshStats(which, UserHandle.USER_ALL);
-        List<BatterySipper> sippers = helper.getUsageList();
+        final List<BatterySipper> sippers = helper.getUsageList();
         if (sippers != null && sippers.size() > 0) {
             dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA,
                     BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()),
@@ -2538,7 +2575,7 @@
                     BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
                     BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
             for (int i=0; i<sippers.size(); i++) {
-                BatterySipper bs = sippers.get(i);
+                final BatterySipper bs = sippers.get(i);
                 int uid = 0;
                 String label;
                 switch (bs.drainType) {
@@ -2590,22 +2627,22 @@
             if (reqUid >= 0 && uid != reqUid) {
                 continue;
             }
-            Uid u = uidStats.valueAt(iu);
+            final Uid u = uidStats.valueAt(iu);
             // Dump Network stats per uid, if any
-            long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
-            long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
-            long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
-            long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
-            long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
-            long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
-            long mobileActiveTime = u.getMobileRadioActiveTime(which);
-            int mobileActiveCount = u.getMobileRadioActiveCount(which);
-            long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
-            long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
-            long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
-            long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
-            int wifiScanCount = u.getWifiScanCount(which);
-            long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
+            final long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
+            final long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
+            final long wifiBytesRx = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
+            final long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
+            final long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
+            final long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
+            final long mobileActiveTime = u.getMobileRadioActiveTime(which);
+            final int mobileActiveCount = u.getMobileRadioActiveCount(which);
+            final long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
+            final long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
+            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
+            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
+            final int wifiScanCount = u.getWifiScanCount(which);
+            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
 
             if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
                     || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
@@ -2636,93 +2673,90 @@
                 }
             }
             
-            Map<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
-            if (wakelocks.size() > 0) {
-                for (Map.Entry<String, ? extends Uid.Wakelock> ent : wakelocks.entrySet()) {
-                    Uid.Wakelock wl = ent.getValue();
-                    String linePrefix = "";
-                    sb.setLength(0);
-                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), 
-                            rawRealtime, "f", which, linePrefix);
-                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), 
-                            rawRealtime, "p", which, linePrefix);
-                    linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), 
-                            rawRealtime, "w", which, linePrefix);
-                    
-                    // Only log if we had at lease one wakelock...
-                    if (sb.length() > 0) {
-                        String name = ent.getKey();
-                        if (name.indexOf(',') >= 0) {
-                            name = name.replace(',', '_');
-                        }
-                        dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
+            final ArrayMap<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
+            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
+                final Uid.Wakelock wl = wakelocks.valueAt(iw);
+                String linePrefix = "";
+                sb.setLength(0);
+                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
+                        rawRealtime, "f", which, linePrefix);
+                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
+                        rawRealtime, "p", which, linePrefix);
+                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
+                        rawRealtime, "w", which, linePrefix);
+
+                // Only log if we had at lease one wakelock...
+                if (sb.length() > 0) {
+                    String name = wakelocks.keyAt(iw);
+                    if (name.indexOf(',') >= 0) {
+                        name = name.replace(',', '_');
                     }
+                    dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
                 }
             }
 
-            Map<String, ? extends Timer> syncs = u.getSyncStats();
-            if (syncs.size() > 0) {
-                for (Map.Entry<String, ? extends Timer> ent : syncs.entrySet()) {
-                    Timer timer = ent.getValue();
-                    // Convert from microseconds to milliseconds with rounding
-                    long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
-                    int count = timer.getCountLocked(which);
-                    if (totalTime != 0) {
-                        dumpLine(pw, uid, category, SYNC_DATA, ent.getKey(), totalTime, count);
-                    }
+            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
+            for (int isy=syncs.size()-1; isy>=0; isy--) {
+                final Timer timer = syncs.valueAt(isy);
+                // Convert from microseconds to milliseconds with rounding
+                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                final int count = timer.getCountLocked(which);
+                if (totalTime != 0) {
+                    dumpLine(pw, uid, category, SYNC_DATA, syncs.keyAt(isy), totalTime, count);
                 }
             }
 
-            Map<String, ? extends Timer> jobs = u.getJobStats();
-            if (jobs.size() > 0) {
-                for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) {
-                    Timer timer = ent.getValue();
-                    // Convert from microseconds to milliseconds with rounding
-                    long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
-                    int count = timer.getCountLocked(which);
-                    if (totalTime != 0) {
-                        dumpLine(pw, uid, category, JOB_DATA, ent.getKey(), totalTime, count);
-                    }
+            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
+            for (int ij=jobs.size()-1; ij>=0; ij--) {
+                final Timer timer = jobs.valueAt(ij);
+                // Convert from microseconds to milliseconds with rounding
+                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                final int count = timer.getCountLocked(which);
+                if (totalTime != 0) {
+                    dumpLine(pw, uid, category, JOB_DATA, jobs.keyAt(ij), totalTime, count);
                 }
             }
 
-            SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
-            int NSE = sensors.size();
+            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
+            final int NSE = sensors.size();
             for (int ise=0; ise<NSE; ise++) {
-                Uid.Sensor se = sensors.valueAt(ise);
-                int sensorNumber = sensors.keyAt(ise);
-                Timer timer = se.getSensorTime();
+                final Uid.Sensor se = sensors.valueAt(ise);
+                final int sensorNumber = sensors.keyAt(ise);
+                final Timer timer = se.getSensorTime();
                 if (timer != null) {
                     // Convert from microseconds to milliseconds with rounding
-                    long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
-                    int count = timer.getCountLocked(which);
+                    final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
+                            / 1000;
+                    final int count = timer.getCountLocked(which);
                     if (totalTime != 0) {
                         dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
                     }
                 }
             }
 
-            Timer vibTimer = u.getVibratorOnTimer();
+            final Timer vibTimer = u.getVibratorOnTimer();
             if (vibTimer != null) {
                 // Convert from microseconds to milliseconds with rounding
-                long totalTime = (vibTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
-                int count = vibTimer.getCountLocked(which);
+                final long totalTime = (vibTimer.getTotalTimeLocked(rawRealtime, which) + 500)
+                        / 1000;
+                final int count = vibTimer.getCountLocked(which);
                 if (totalTime != 0) {
                     dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count);
                 }
             }
 
-            Timer fgTimer = u.getForegroundActivityTimer();
+            final Timer fgTimer = u.getForegroundActivityTimer();
             if (fgTimer != null) {
                 // Convert from microseconds to milliseconds with rounding
-                long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
-                int count = fgTimer.getCountLocked(which);
+                final long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500)
+                        / 1000;
+                final int count = fgTimer.getCountLocked(which);
                 if (totalTime != 0) {
                     dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count);
                 }
             }
 
-            Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE];
+            final Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE];
             long totalStateTime = 0;
             for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
                 totalStateTime += u.getProcessStateTime(ips, rawRealtime, which);
@@ -2732,50 +2766,48 @@
                 dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes);
             }
 
-            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
-            if (processStats.size() > 0) {
-                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
-                        : processStats.entrySet()) {
-                    Uid.Proc ps = ent.getValue();
+            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
+                    = u.getProcessStats();
+            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
+                final Uid.Proc ps = processStats.valueAt(ipr);
 
-                    final long userMillis = ps.getUserTime(which);
-                    final long systemMillis = ps.getSystemTime(which);
-                    final long foregroundMillis = ps.getForegroundTime(which);
-                    final int starts = ps.getStarts(which);
-                    final int numCrashes = ps.getNumCrashes(which);
-                    final int numAnrs = ps.getNumAnrs(which);
+                final long userMillis = ps.getUserTime(which);
+                final long systemMillis = ps.getSystemTime(which);
+                final long foregroundMillis = ps.getForegroundTime(which);
+                final int starts = ps.getStarts(which);
+                final int numCrashes = ps.getNumCrashes(which);
+                final int numAnrs = ps.getNumAnrs(which);
 
-                    if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
-                            || starts != 0 || numAnrs != 0 || numCrashes != 0) {
-                        dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis,
-                                systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
-                    }
+                if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0
+                        || starts != 0 || numAnrs != 0 || numCrashes != 0) {
+                    dumpLine(pw, uid, category, PROCESS_DATA, processStats.keyAt(ipr), userMillis,
+                            systemMillis, foregroundMillis, starts, numAnrs, numCrashes);
                 }
             }
 
-            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
-            if (packageStats.size() > 0) {
-                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
-                        : packageStats.entrySet()) {
-              
-                    Uid.Pkg ps = ent.getValue();
-                    int wakeups = ps.getWakeups(which);
-                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
-                    for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
-                            : serviceStats.entrySet()) {
-                        BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
-                        long startTime = ss.getStartTime(batteryUptime, which);
-                        int starts = ss.getStarts(which);
-                        int launches = ss.getLaunches(which);
-                        if (startTime != 0 || starts != 0 || launches != 0) {
-                            dumpLine(pw, uid, category, APK_DATA, 
-                                    wakeups, // wakeup alarms
-                                    ent.getKey(), // Apk
-                                    sent.getKey(), // service
-                                    startTime / 1000, // time spent started, in ms
-                                    starts,
-                                    launches);
-                        }
+            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
+                    = u.getPackageStats();
+            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
+                final Uid.Pkg ps = packageStats.valueAt(ipkg);
+                int wakeups = 0;
+                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
+                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
+                    wakeups += alarms.valueAt(iwa).getCountLocked(which);
+                }
+                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
+                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
+                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
+                    final long startTime = ss.getStartTime(batteryUptime, which);
+                    final int starts = ss.getStarts(which);
+                    final int launches = ss.getLaunches(which);
+                    if (startTime != 0 || starts != 0 || launches != 0) {
+                        dumpLine(pw, uid, category, APK_DATA,
+                                wakeups, // wakeup alarms
+                                packageStats.keyAt(ipkg), // Apk
+                                serviceStats.keyAt(isvc), // service
+                                startTime / 1000, // time spent started, in ms
+                                starts,
+                                launches);
                     }
                 }
             }
@@ -2824,9 +2856,9 @@
         final long batteryTimeRemaining = computeBatteryTimeRemaining(rawRealtime);
         final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime);
 
-        StringBuilder sb = new StringBuilder(128);
+        final StringBuilder sb = new StringBuilder(128);
         
-        SparseArray<? extends Uid> uidStats = getUidStats();
+        final SparseArray<? extends Uid> uidStats = getUidStats();
         final int NU = uidStats.size();
 
         sb.setLength(0);
@@ -2879,6 +2911,7 @@
         final long interactiveTime = getInteractiveTime(rawRealtime, which);
         final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
         final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
+        final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
         final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
         final long wifiOnTime = getWifiOnTime(rawRealtime, which);
@@ -2923,10 +2956,21 @@
                     sb.append(")");
             pw.println(sb.toString());
         }
-        if (deviceIdleModeEnabledTime != 0) {
+        if (deviceIdlingTime != 0) {
             sb.setLength(0);
             sb.append(prefix);
                     sb.append("  Device idling: ");
+                    formatTimeMs(sb, deviceIdlingTime / 1000);
+                    sb.append("(");
+                    sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
+                    sb.append(") "); sb.append(getDeviceIdlingCount(which));
+                    sb.append("x");
+            pw.println(sb.toString());
+        }
+        if (deviceIdleModeEnabledTime != 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("  Idle mode time: ");
                     formatTimeMs(sb, deviceIdleModeEnabledTime / 1000);
                     sb.append("(");
                     sb.append(formatRatioLocked(deviceIdleModeEnabledTime, whichBatteryRealtime));
@@ -2941,7 +2985,7 @@
                     sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
                     sb.append(") "); sb.append(getPhoneOnCount(which)); sb.append("x");
         }
-        int connChanges = getNumConnectivityChange(which);
+        final int connChanges = getNumConnectivityChange(which);
         if (connChanges != 0) {
             pw.print(prefix);
             pw.print("  Connectivity changes: "); pw.println(connChanges);
@@ -2951,50 +2995,48 @@
         long fullWakeLockTimeTotalMicros = 0;
         long partialWakeLockTimeTotalMicros = 0;
 
-        final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
+        final ArrayList<TimerEntry> timers = new ArrayList<>();
 
         for (int iu = 0; iu < NU; iu++) {
-            Uid u = uidStats.valueAt(iu);
+            final Uid u = uidStats.valueAt(iu);
 
-            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
-            if (wakelocks.size() > 0) {
-                for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent 
-                        : wakelocks.entrySet()) {
-                    Uid.Wakelock wl = ent.getValue();
-                    
-                    Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
-                    if (fullWakeTimer != null) {
-                        fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
-                                rawRealtime, which);
-                    }
+            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
+                    = u.getWakelockStats();
+            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
+                final Uid.Wakelock wl = wakelocks.valueAt(iw);
 
-                    Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
-                    if (partialWakeTimer != null) {
-                        long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
-                                rawRealtime, which);
-                        if (totalTimeMicros > 0) {
-                            if (reqUid < 0) {
-                                // Only show the ordered list of all wake
-                                // locks if the caller is not asking for data
-                                // about a specific uid.
-                                timers.add(new TimerEntry(ent.getKey(), u.getUid(),
-                                        partialWakeTimer, totalTimeMicros));
-                            }
-                            partialWakeLockTimeTotalMicros += totalTimeMicros;
+                final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
+                if (fullWakeTimer != null) {
+                    fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
+                            rawRealtime, which);
+                }
+
+                final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
+                if (partialWakeTimer != null) {
+                    final long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
+                            rawRealtime, which);
+                    if (totalTimeMicros > 0) {
+                        if (reqUid < 0) {
+                            // Only show the ordered list of all wake
+                            // locks if the caller is not asking for data
+                            // about a specific uid.
+                            timers.add(new TimerEntry(wakelocks.keyAt(iw), u.getUid(),
+                                    partialWakeTimer, totalTimeMicros));
                         }
+                        partialWakeLockTimeTotalMicros += totalTimeMicros;
                     }
                 }
             }
         }
         
-        long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
-        long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
-        long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
-        long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
-        long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
-        long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
-        long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
-        long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
+        final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
+        final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
+        final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
+        final long wifiTxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
+        final long mobileRxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
+        final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
+        final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
+        final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
 
         if (fullWakeLockTimeTotalMicros != 0) {
             sb.setLength(0);
@@ -3191,9 +3233,9 @@
         if (!didOne) sb.append(" (no activity)");
         pw.println(sb.toString());
 
-        final long wifiIdleTimeMs = getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
-        final long wifiRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
-        final long wifiTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
+        final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
+        final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
+        final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
         final long wifiTotalTimeMs = wifiIdleTimeMs + wifiRxTimeMs + wifiTxTimeMs;
 
         sb.setLength(0);
@@ -3316,7 +3358,7 @@
             pw.println();
         }
 
-        BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
+        final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
         helper.create(this);
         helper.refreshStats(which, UserHandle.USER_ALL);
         List<BatterySipper> sippers = helper.getUsageList();
@@ -3331,7 +3373,7 @@
                     }
                     pw.println();
             for (int i=0; i<sippers.size(); i++) {
-                BatterySipper bs = sippers.get(i);
+                final BatterySipper bs = sippers.get(i);
                 switch (bs.drainType) {
                     case IDLE:
                         pw.print(prefix); pw.print("    Idle: "); printmAh(pw, bs.value);
@@ -3388,7 +3430,7 @@
             pw.print(prefix); pw.println("  Per-app mobile ms per packet:");
             long totalTime = 0;
             for (int i=0; i<sippers.size(); i++) {
-                BatterySipper bs = sippers.get(i);
+                final BatterySipper bs = sippers.get(i);
                 sb.setLength(0);
                 sb.append(prefix); sb.append("    Uid ");
                 UserHandle.formatUid(sb, bs.uidObj.getUid());
@@ -3425,12 +3467,14 @@
         };
 
         if (reqUid < 0) {
-            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
+            final Map<String, ? extends BatteryStats.Timer> kernelWakelocks
+                    = getKernelWakelockStats();
             if (kernelWakelocks.size() > 0) {
-                final ArrayList<TimerEntry> ktimers = new ArrayList<TimerEntry>();
-                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
-                    BatteryStats.Timer timer = ent.getValue();
-                    long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
+                final ArrayList<TimerEntry> ktimers = new ArrayList<>();
+                for (Map.Entry<String, ? extends BatteryStats.Timer> ent
+                        : kernelWakelocks.entrySet()) {
+                    final BatteryStats.Timer timer = ent.getValue();
+                    final long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
                     if (totalTimeMillis > 0) {
                         ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
                     }
@@ -3439,7 +3483,7 @@
                     Collections.sort(ktimers, timerComparator);
                     pw.print(prefix); pw.println("  All kernel wake locks:");
                     for (int i=0; i<ktimers.size(); i++) {
-                        TimerEntry timer = ktimers.get(i);
+                        final TimerEntry timer = ktimers.get(i);
                         String linePrefix = ": ";
                         sb.setLength(0);
                         sb.append(prefix);
@@ -3475,12 +3519,12 @@
                 pw.println();
             }
 
-            Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
+            final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
             if (wakeupReasons.size() > 0) {
                 pw.print(prefix); pw.println("  All wakeup reasons:");
-                final ArrayList<TimerEntry> reasons = new ArrayList<TimerEntry>();
+                final ArrayList<TimerEntry> reasons = new ArrayList<>();
                 for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
-                    Timer timer = ent.getValue();
+                    final Timer timer = ent.getValue();
                     reasons.add(new TimerEntry(ent.getKey(), 0, timer,
                             timer.getCountLocked(which)));
                 }
@@ -3506,7 +3550,7 @@
                 continue;
             }
             
-            Uid u = uidStats.valueAt(iu);
+            final Uid u = uidStats.valueAt(iu);
 
             pw.print(prefix);
             pw.print("  ");
@@ -3514,20 +3558,20 @@
             pw.println(":");
             boolean uidActivity = false;
 
-            long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
-            long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
-            long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
-            long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
-            long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
-            long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
-            long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
-            int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
-            long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
-            long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
-            long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
-            long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
-            int wifiScanCount = u.getWifiScanCount(which);
-            long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
+            final long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
+            final long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
+            final long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
+            final long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
+            final long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
+            final long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
+            final long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
+            final int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
+            final long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
+            final long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
+            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
+            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
+            final int wifiScanCount = u.getWifiScanCount(which);
+            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
 
             if (mobileRxBytes > 0 || mobileTxBytes > 0
                     || mobileRxPackets > 0 || mobileTxPackets > 0) {
@@ -3585,7 +3629,7 @@
             if (u.hasUserActivity()) {
                 boolean hasData = false;
                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
-                    int val = u.getUserActivityCount(i, which);
+                    final int val = u.getUserActivityCount(i, which);
                     if (val != 0) {
                         if (!hasData) {
                             sb.setLength(0);
@@ -3604,125 +3648,121 @@
                 }
             }
 
-            Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
-            if (wakelocks.size() > 0) {
-                long totalFull = 0, totalPartial = 0, totalWindow = 0;
-                int count = 0;
-                for (Map.Entry<String, ? extends Uid.Wakelock> ent : wakelocks.entrySet()) {
-                    Uid.Wakelock wl = ent.getValue();
-                    String linePrefix = ": ";
-                    sb.setLength(0);
-                    sb.append(prefix);
-                    sb.append("    Wake lock ");
-                    sb.append(ent.getKey());
-                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
-                            "full", which, linePrefix);
-                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
-                            "partial", which, linePrefix);
-                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
-                            "window", which, linePrefix);
-                    if (true || !linePrefix.equals(": ")) {
-                        sb.append(" realtime");
-                        // Only print out wake locks that were held
-                        pw.println(sb.toString());
-                        uidActivity = true;
-                        count++;
-                    }
-                    totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
-                            rawRealtime, which);
-                    totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
-                            rawRealtime, which);
-                    totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
-                            rawRealtime, which);
-                }
-                if (count > 1) {
-                    if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
-                        sb.setLength(0);
-                        sb.append(prefix);
-                        sb.append("    TOTAL wake: ");
-                        boolean needComma = false;
-                        if (totalFull != 0) {
-                            needComma = true;
-                            formatTimeMs(sb, totalFull);
-                            sb.append("full");
-                        }
-                        if (totalPartial != 0) {
-                            if (needComma) {
-                                sb.append(", ");
-                            }
-                            needComma = true;
-                            formatTimeMs(sb, totalPartial);
-                            sb.append("partial");
-                        }
-                        if (totalWindow != 0) {
-                            if (needComma) {
-                                sb.append(", ");
-                            }
-                            needComma = true;
-                            formatTimeMs(sb, totalWindow);
-                            sb.append("window");
-                        }
-                        sb.append(" realtime");
-                        pw.println(sb.toString());
-                    }
-                }
-            }
-
-            Map<String, ? extends Timer> syncs = u.getSyncStats();
-            if (syncs.size() > 0) {
-                for (Map.Entry<String, ? extends Timer> ent : syncs.entrySet()) {
-                    Timer timer = ent.getValue();
-                    // Convert from microseconds to milliseconds with rounding
-                    long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
-                    int count = timer.getCountLocked(which);
-                    sb.setLength(0);
-                    sb.append(prefix);
-                    sb.append("    Sync ");
-                    sb.append(ent.getKey());
-                    sb.append(": ");
-                    if (totalTime != 0) {
-                        formatTimeMs(sb, totalTime);
-                        sb.append("realtime (");
-                        sb.append(count);
-                        sb.append(" times)");
-                    } else {
-                        sb.append("(not used)");
-                    }
+            final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks
+                    = u.getWakelockStats();
+            long totalFullWakelock = 0, totalPartialWakelock = 0, totalWindowWakelock = 0;
+            int countWakelock = 0;
+            for (int iw=wakelocks.size()-1; iw>=0; iw--) {
+                final Uid.Wakelock wl = wakelocks.valueAt(iw);
+                String linePrefix = ": ";
+                sb.setLength(0);
+                sb.append(prefix);
+                sb.append("    Wake lock ");
+                sb.append(wakelocks.keyAt(iw));
+                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
+                        "full", which, linePrefix);
+                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
+                        "partial", which, linePrefix);
+                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
+                        "window", which, linePrefix);
+                if (true || !linePrefix.equals(": ")) {
+                    sb.append(" realtime");
+                    // Only print out wake locks that were held
                     pw.println(sb.toString());
                     uidActivity = true;
+                    countWakelock++;
                 }
+                totalFullWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
+                        rawRealtime, which);
+                totalPartialWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
+                        rawRealtime, which);
+                totalWindowWakelock += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
+                        rawRealtime, which);
             }
-
-            Map<String, ? extends Timer> jobs = u.getJobStats();
-            if (jobs.size() > 0) {
-                for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) {
-                    Timer timer = ent.getValue();
-                    // Convert from microseconds to milliseconds with rounding
-                    long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
-                    int count = timer.getCountLocked(which);
+            if (countWakelock > 1) {
+                if (totalFullWakelock != 0 || totalPartialWakelock != 0
+                        || totalWindowWakelock != 0) {
                     sb.setLength(0);
                     sb.append(prefix);
-                    sb.append("    Job ");
-                    sb.append(ent.getKey());
-                    sb.append(": ");
-                    if (totalTime != 0) {
-                        formatTimeMs(sb, totalTime);
-                        sb.append("realtime (");
-                        sb.append(count);
-                        sb.append(" times)");
-                    } else {
-                        sb.append("(not used)");
+                    sb.append("    TOTAL wake: ");
+                    boolean needComma = false;
+                    if (totalFullWakelock != 0) {
+                        needComma = true;
+                        formatTimeMs(sb, totalFullWakelock);
+                        sb.append("full");
                     }
+                    if (totalPartialWakelock != 0) {
+                        if (needComma) {
+                            sb.append(", ");
+                        }
+                        needComma = true;
+                        formatTimeMs(sb, totalPartialWakelock);
+                        sb.append("partial");
+                    }
+                    if (totalWindowWakelock != 0) {
+                        if (needComma) {
+                            sb.append(", ");
+                        }
+                        needComma = true;
+                        formatTimeMs(sb, totalWindowWakelock);
+                        sb.append("window");
+                    }
+                    sb.append(" realtime");
                     pw.println(sb.toString());
-                    uidActivity = true;
                 }
             }
 
-            SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
-            int NSE = sensors.size();
+            final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
+            for (int isy=syncs.size()-1; isy>=0; isy--) {
+                final Timer timer = syncs.valueAt(isy);
+                // Convert from microseconds to milliseconds with rounding
+                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                final int count = timer.getCountLocked(which);
+                sb.setLength(0);
+                sb.append(prefix);
+                sb.append("    Sync ");
+                sb.append(syncs.keyAt(isy));
+                sb.append(": ");
+                if (totalTime != 0) {
+                    formatTimeMs(sb, totalTime);
+                    sb.append("realtime (");
+                    sb.append(count);
+                    sb.append(" times)");
+                } else {
+                    sb.append("(not used)");
+                }
+                pw.println(sb.toString());
+                uidActivity = true;
+            }
+
+            final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
+            for (int ij=jobs.size()-1; ij>=0; ij--) {
+                final Timer timer = jobs.valueAt(ij);
+                // Convert from microseconds to milliseconds with rounding
+                final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                final int count = timer.getCountLocked(which);
+                sb.setLength(0);
+                sb.append(prefix);
+                sb.append("    Job ");
+                sb.append(jobs.keyAt(ij));
+                sb.append(": ");
+                if (totalTime != 0) {
+                    formatTimeMs(sb, totalTime);
+                    sb.append("realtime (");
+                    sb.append(count);
+                    sb.append(" times)");
+                } else {
+                    sb.append("(not used)");
+                }
+                pw.println(sb.toString());
+                uidActivity = true;
+            }
+
+            final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
+            final int NSE = sensors.size();
             for (int ise=0; ise<NSE; ise++) {
-                Uid.Sensor se = sensors.valueAt(ise);
-                int sensorNumber = sensors.keyAt(ise);
+                final Uid.Sensor se = sensors.valueAt(ise);
+                final int sensorNumber = sensors.keyAt(ise);
                 sb.setLength(0);
                 sb.append(prefix);
                 sb.append("    Sensor ");
@@ -3734,12 +3774,12 @@
                 }
                 sb.append(": ");
 
-                Timer timer = se.getSensorTime();
+                final Timer timer = se.getSensorTime();
                 if (timer != null) {
                     // Convert from microseconds to milliseconds with rounding
-                    long totalTime = (timer.getTotalTimeLocked(
+                    final long totalTime = (timer.getTotalTimeLocked(
                             rawRealtime, which) + 500) / 1000;
-                    int count = timer.getCountLocked(which);
+                    final int count = timer.getCountLocked(which);
                     //timer.logState();
                     if (totalTime != 0) {
                         formatTimeMs(sb, totalTime);
@@ -3757,12 +3797,12 @@
                 uidActivity = true;
             }
 
-            Timer vibTimer = u.getVibratorOnTimer();
+            final Timer vibTimer = u.getVibratorOnTimer();
             if (vibTimer != null) {
                 // Convert from microseconds to milliseconds with rounding
-                long totalTime = (vibTimer.getTotalTimeLocked(
+                final long totalTime = (vibTimer.getTotalTimeLocked(
                         rawRealtime, which) + 500) / 1000;
-                int count = vibTimer.getCountLocked(which);
+                final int count = vibTimer.getCountLocked(which);
                 //timer.logState();
                 if (totalTime != 0) {
                     sb.setLength(0);
@@ -3777,11 +3817,12 @@
                 }
             }
 
-            Timer fgTimer = u.getForegroundActivityTimer();
+            final Timer fgTimer = u.getForegroundActivityTimer();
             if (fgTimer != null) {
                 // Convert from microseconds to milliseconds with rounding
-                long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
-                int count = fgTimer.getCountLocked(which);
+                final long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500)
+                        / 1000;
+                final int count = fgTimer.getCountLocked(which);
                 if (totalTime != 0) {
                     sb.setLength(0);
                     sb.append(prefix);
@@ -3811,126 +3852,122 @@
                 }
             }
 
-            Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
-            if (processStats.size() > 0) {
-                for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
-                    : processStats.entrySet()) {
-                    Uid.Proc ps = ent.getValue();
-                    long userTime;
-                    long systemTime;
-                    long foregroundTime;
-                    int starts;
-                    int numExcessive;
+            final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
+                    = u.getProcessStats();
+            for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
+                final Uid.Proc ps = processStats.valueAt(ipr);
+                long userTime;
+                long systemTime;
+                long foregroundTime;
+                int starts;
+                int numExcessive;
 
-                    userTime = ps.getUserTime(which);
-                    systemTime = ps.getSystemTime(which);
-                    foregroundTime = ps.getForegroundTime(which);
-                    starts = ps.getStarts(which);
-                    final int numCrashes = ps.getNumCrashes(which);
-                    final int numAnrs = ps.getNumAnrs(which);
-                    numExcessive = which == STATS_SINCE_CHARGED
-                            ? ps.countExcessivePowers() : 0;
+                userTime = ps.getUserTime(which);
+                systemTime = ps.getSystemTime(which);
+                foregroundTime = ps.getForegroundTime(which);
+                starts = ps.getStarts(which);
+                final int numCrashes = ps.getNumCrashes(which);
+                final int numAnrs = ps.getNumAnrs(which);
+                numExcessive = which == STATS_SINCE_CHARGED
+                        ? ps.countExcessivePowers() : 0;
 
-                    if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
-                            || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) {
-                        sb.setLength(0);
-                        sb.append(prefix); sb.append("    Proc ");
-                                sb.append(ent.getKey()); sb.append(":\n");
-                        sb.append(prefix); sb.append("      CPU: ");
-                                formatTimeMs(sb, userTime); sb.append("usr + ");
-                                formatTimeMs(sb, systemTime); sb.append("krn ; ");
-                                formatTimeMs(sb, foregroundTime); sb.append("fg");
-                        if (starts != 0 || numCrashes != 0 || numAnrs != 0) {
-                            sb.append("\n"); sb.append(prefix); sb.append("      ");
-                            boolean hasOne = false;
-                            if (starts != 0) {
-                                hasOne = true;
-                                sb.append(starts); sb.append(" starts");
-                            }
-                            if (numCrashes != 0) {
-                                if (hasOne) {
-                                    sb.append(", ");
-                                }
-                                hasOne = true;
-                                sb.append(numCrashes); sb.append(" crashes");
-                            }
-                            if (numAnrs != 0) {
-                                if (hasOne) {
-                                    sb.append(", ");
-                                }
-                                sb.append(numAnrs); sb.append(" anrs");
-                            }
+                if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0
+                        || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) {
+                    sb.setLength(0);
+                    sb.append(prefix); sb.append("    Proc ");
+                            sb.append(processStats.keyAt(ipr)); sb.append(":\n");
+                    sb.append(prefix); sb.append("      CPU: ");
+                            formatTimeMs(sb, userTime); sb.append("usr + ");
+                            formatTimeMs(sb, systemTime); sb.append("krn ; ");
+                            formatTimeMs(sb, foregroundTime); sb.append("fg");
+                    if (starts != 0 || numCrashes != 0 || numAnrs != 0) {
+                        sb.append("\n"); sb.append(prefix); sb.append("      ");
+                        boolean hasOne = false;
+                        if (starts != 0) {
+                            hasOne = true;
+                            sb.append(starts); sb.append(" starts");
                         }
-                        pw.println(sb.toString());
-                        for (int e=0; e<numExcessive; e++) {
-                            Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
-                            if (ew != null) {
-                                pw.print(prefix); pw.print("      * Killed for ");
-                                        if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
-                                            pw.print("wake lock");
-                                        } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
-                                            pw.print("cpu");
-                                        } else {
-                                            pw.print("unknown");
-                                        }
-                                        pw.print(" use: ");
-                                        TimeUtils.formatDuration(ew.usedTime, pw);
-                                        pw.print(" over ");
-                                        TimeUtils.formatDuration(ew.overTime, pw);
-                                        if (ew.overTime != 0) {
-                                            pw.print(" (");
-                                            pw.print((ew.usedTime*100)/ew.overTime);
-                                            pw.println("%)");
-                                        }
+                        if (numCrashes != 0) {
+                            if (hasOne) {
+                                sb.append(", ");
                             }
+                            hasOne = true;
+                            sb.append(numCrashes); sb.append(" crashes");
                         }
-                        uidActivity = true;
-                    }
-                }
-            }
-
-            Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
-            if (packageStats.size() > 0) {
-                for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
-                    : packageStats.entrySet()) {
-                    pw.print(prefix); pw.print("    Apk "); pw.print(ent.getKey()); pw.println(":");
-                    boolean apkActivity = false;
-                    Uid.Pkg ps = ent.getValue();
-                    int wakeups = ps.getWakeups(which);
-                    if (wakeups != 0) {
-                        pw.print(prefix); pw.print("      ");
-                                pw.print(wakeups); pw.println(" wakeup alarms");
-                        apkActivity = true;
-                    }
-                    Map<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
-                    if (serviceStats.size() > 0) {
-                        for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
-                                : serviceStats.entrySet()) {
-                            BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
-                            long startTime = ss.getStartTime(batteryUptime, which);
-                            int starts = ss.getStarts(which);
-                            int launches = ss.getLaunches(which);
-                            if (startTime != 0 || starts != 0 || launches != 0) {
-                                sb.setLength(0);
-                                sb.append(prefix); sb.append("      Service ");
-                                        sb.append(sent.getKey()); sb.append(":\n");
-                                sb.append(prefix); sb.append("        Created for: ");
-                                        formatTimeMs(sb, startTime / 1000);
-                                        sb.append("uptime\n");
-                                sb.append(prefix); sb.append("        Starts: ");
-                                        sb.append(starts);
-                                        sb.append(", launches: "); sb.append(launches);
-                                pw.println(sb.toString());
-                                apkActivity = true;
+                        if (numAnrs != 0) {
+                            if (hasOne) {
+                                sb.append(", ");
                             }
+                            sb.append(numAnrs); sb.append(" anrs");
                         }
                     }
-                    if (!apkActivity) {
-                        pw.print(prefix); pw.println("      (nothing executed)");
+                    pw.println(sb.toString());
+                    for (int e=0; e<numExcessive; e++) {
+                        Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
+                        if (ew != null) {
+                            pw.print(prefix); pw.print("      * Killed for ");
+                                    if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
+                                        pw.print("wake lock");
+                                    } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
+                                        pw.print("cpu");
+                                    } else {
+                                        pw.print("unknown");
+                                    }
+                                    pw.print(" use: ");
+                                    TimeUtils.formatDuration(ew.usedTime, pw);
+                                    pw.print(" over ");
+                                    TimeUtils.formatDuration(ew.overTime, pw);
+                                    if (ew.overTime != 0) {
+                                        pw.print(" (");
+                                        pw.print((ew.usedTime*100)/ew.overTime);
+                                        pw.println("%)");
+                                    }
+                        }
                     }
                     uidActivity = true;
                 }
             }
+
+            final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats
+                    = u.getPackageStats();
+            for (int ipkg=packageStats.size()-1; ipkg>=0; ipkg--) {
+                pw.print(prefix); pw.print("    Apk "); pw.print(packageStats.keyAt(ipkg));
+                pw.println(":");
+                boolean apkActivity = false;
+                final Uid.Pkg ps = packageStats.valueAt(ipkg);
+                final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
+                for (int iwa=alarms.size()-1; iwa>=0; iwa--) {
+                    pw.print(prefix); pw.print("      Wakeup alarm ");
+                            pw.print(alarms.keyAt(iwa)); pw.print(": ");
+                            pw.print(alarms.valueAt(iwa).getCountLocked(which));
+                            pw.println(" times");
+                    apkActivity = true;
+                }
+                final ArrayMap<String, ? extends  Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
+                for (int isvc=serviceStats.size()-1; isvc>=0; isvc--) {
+                    final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
+                    final long startTime = ss.getStartTime(batteryUptime, which);
+                    final int starts = ss.getStarts(which);
+                    final int launches = ss.getLaunches(which);
+                    if (startTime != 0 || starts != 0 || launches != 0) {
+                        sb.setLength(0);
+                        sb.append(prefix); sb.append("      Service ");
+                                sb.append(serviceStats.keyAt(isvc)); sb.append(":\n");
+                        sb.append(prefix); sb.append("        Created for: ");
+                                formatTimeMs(sb, startTime / 1000);
+                                sb.append("uptime\n");
+                        sb.append(prefix); sb.append("        Starts: ");
+                                sb.append(starts);
+                                sb.append(", launches: "); sb.append(launches);
+                        pw.println(sb.toString());
+                        apkActivity = true;
+                    }
+                }
+                if (!apkActivity) {
+                    pw.print(prefix); pw.println("      (nothing executed)");
+                }
+                uidActivity = true;
+            }
             if (!uidActivity) {
                 pw.print(prefix); pw.println("    (nothing executed)");
             }
@@ -4378,7 +4415,7 @@
         if (!checkin) {
             pw.println(header);
         }
-        String[] lineArgs = new String[4];
+        String[] lineArgs = new String[5];
         for (int i=0; i<count; i++) {
             long duration = steps.getDurationAt(i);
             int level = steps.getLevelAt(i);
@@ -4393,7 +4430,7 @@
                         case Display.STATE_ON: lineArgs[2] = "s+"; break;
                         case Display.STATE_DOZE: lineArgs[2] = "sd"; break;
                         case Display.STATE_DOZE_SUSPEND: lineArgs[2] = "sds"; break;
-                        default: lineArgs[1] = "?"; break;
+                        default: lineArgs[2] = "?"; break;
                     }
                 } else {
                     lineArgs[2] = "";
@@ -4403,6 +4440,11 @@
                 } else {
                     lineArgs[3] = "";
                 }
+                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
+                    lineArgs[4] = (initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0 ? "i+" : "i-";
+                } else {
+                    lineArgs[4] = "";
+                }
                 dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs);
             } else {
                 pw.print(prefix);
@@ -4417,7 +4459,7 @@
                         case Display.STATE_ON: pw.print("screen-on"); break;
                         case Display.STATE_DOZE: pw.print("screen-doze"); break;
                         case Display.STATE_DOZE_SUSPEND: pw.print("screen-doze-suspend"); break;
-                        default: lineArgs[1] = "screen-?"; break;
+                        default: pw.print("screen-?"); break;
                     }
                     haveModes = true;
                 }
@@ -4427,6 +4469,12 @@
                             ? "power-save-on" : "power-save-off");
                     haveModes = true;
                 }
+                if ((modMode&STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
+                    pw.print(haveModes ? ", " : " (");
+                    pw.print((initMode&STEP_LEVEL_MODE_DEVICE_IDLE) != 0
+                            ? "device-idle-on" : "device-idle-off");
+                    haveModes = true;
+                }
                 if (haveModes) {
                     pw.print(")");
                 }
@@ -4436,7 +4484,6 @@
         return true;
     }
 
-    public static final int DUMP_UNPLUGGED_ONLY = 1<<0;
     public static final int DUMP_CHARGED_ONLY = 1<<1;
     public static final int DUMP_DAILY_ONLY = 1<<2;
     public static final int DUMP_HISTORY_ONLY = 1<<3;
@@ -4558,6 +4605,23 @@
         }
     }
 
+    private void dumpDailyPackageChanges(PrintWriter pw, String prefix,
+            ArrayList<PackageChange> changes) {
+        if (changes == null) {
+            return;
+        }
+        pw.print(prefix); pw.println("Package changes:");
+        for (int i=0; i<changes.size(); i++) {
+            PackageChange pc = changes.get(i);
+            if (pc.mUpdate) {
+                pw.print(prefix); pw.print("  Update "); pw.print(pc.mPackageName);
+                pw.print(" vers="); pw.println(pc.mVersionCode);
+            } else {
+                pw.print(prefix); pw.print("  Uninstall "); pw.println(pc.mPackageName);
+            }
+        }
+    }
+
     /**
      * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
      *
@@ -4568,7 +4632,7 @@
         prepareForDumpLocked();
 
         final boolean filtering = (flags
-                & (DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
+                & (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
 
         if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
             final long historyTotalSize = getHistoryTotalSize();
@@ -4612,7 +4676,7 @@
             }
         }
 
-        if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
+        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
             return;
         }
 
@@ -4688,8 +4752,9 @@
             int[] outInt = new int[1];
             LevelStepTracker dsteps = getDailyDischargeLevelStepTracker();
             LevelStepTracker csteps = getDailyChargeLevelStepTracker();
-            if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0) {
-                if ((flags&DUMP_DAILY_ONLY) != 0) {
+            ArrayList<PackageChange> pkgc = getDailyPackageChanges();
+            if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0 || pkgc != null) {
+                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
                     if (dumpDurationSteps(pw, "    ", "  Current daily discharge step durations:",
                             dsteps, false)) {
                         dumpDailyLevelStepSummary(pw, "      ", "Discharge", dsteps,
@@ -4700,6 +4765,7 @@
                         dumpDailyLevelStepSummary(pw, "      ", "Charge", csteps,
                                 sb, outInt);
                     }
+                    dumpDailyPackageChanges(pw, "    ", pkgc);
                 } else {
                     pw.println("  Current daily steps:");
                     dumpDailyLevelStepSummary(pw, "    ", "Discharge", dsteps,
@@ -4720,7 +4786,7 @@
                 pw.print(" to ");
                 pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mEndTime).toString());
                 pw.println(":");
-                if ((flags&DUMP_DAILY_ONLY) != 0) {
+                if ((flags&DUMP_DAILY_ONLY) != 0 || !filtering) {
                     if (dumpDurationSteps(pw, "      ",
                             "    Discharge step durations:", dit.mDischargeSteps, false)) {
                         dumpDailyLevelStepSummary(pw, "        ", "Discharge", dit.mDischargeSteps,
@@ -4731,6 +4797,7 @@
                         dumpDailyLevelStepSummary(pw, "        ", "Charge", dit.mChargeSteps,
                                 sb, outInt);
                     }
+                    dumpDailyPackageChanges(pw, "    ", dit.mPackageChanges);
                 } else {
                     dumpDailyLevelStepSummary(pw, "    ", "Discharge", dit.mDischargeSteps,
                             sb, outInt);
@@ -4748,11 +4815,6 @@
                     (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
             pw.println();
         }
-        if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
-            pw.println("Statistics since last unplugged:");
-            dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid,
-                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
-        }
     }
     
     @SuppressWarnings("unused")
@@ -4766,7 +4828,7 @@
         long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
 
         final boolean filtering = (flags &
-                (DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
+                (DUMP_HISTORY_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
 
         if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
             if (startIteratingHistoryLocked()) {
@@ -4792,7 +4854,7 @@
             }
         }
 
-        if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
+        if (filtering && (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
             return;
         }
 
@@ -4842,9 +4904,5 @@
             dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1,
                     (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
         }
-        if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
-            dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1,
-                    (flags&DUMP_DEVICE_WIFI_ONLY) != 0);
-        }
     }
 }
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 975bfc2..2eb97f1 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -18,16 +18,11 @@
 
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
-import android.os.storage.IMountService;
+import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
-import android.text.TextUtils;
 import android.util.Log;
 
-import com.google.android.collect.Lists;
-
 import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
 
 /**
  * Provides access to environment variables.
@@ -36,11 +31,9 @@
     private static final String TAG = "Environment";
 
     private static final String ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE";
-    private static final String ENV_EMULATED_STORAGE_SOURCE = "EMULATED_STORAGE_SOURCE";
-    private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET";
-    private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE";
-    private static final String ENV_SECONDARY_STORAGE = "SECONDARY_STORAGE";
     private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
+    private static final String ENV_ANDROID_DATA = "ANDROID_DATA";
+    private static final String ENV_ANDROID_STORAGE = "ANDROID_STORAGE";
     private static final String ENV_OEM_ROOT = "OEM_ROOT";
     private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
 
@@ -57,12 +50,10 @@
     public static final String DIRECTORY_ANDROID = DIR_ANDROID;
 
     private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
+    private static final File DIR_ANDROID_DATA = getDirectory(ENV_ANDROID_DATA, "/data");
+    private static final File DIR_ANDROID_STORAGE = getDirectory(ENV_ANDROID_STORAGE, "/storage");
     private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
     private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
-    private static final File DIR_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media");
-
-    private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull(
-            ENV_EMULATED_STORAGE_TARGET);
 
     private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
 
@@ -81,73 +72,24 @@
 
     /** {@hide} */
     public static class UserEnvironment {
-        // TODO: generalize further to create package-specific environment
-
-        /** External storage dirs, as visible to vold */
-        private final File[] mExternalDirsForVold;
-        /** External storage dirs, as visible to apps */
-        private final File[] mExternalDirsForApp;
-        /** Primary emulated storage dir for direct access */
-        private final File mEmulatedDirForDirect;
+        private final int mUserId;
 
         public UserEnvironment(int userId) {
-            // See storage config details at http://source.android.com/tech/storage/
-            String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE);
-            String rawEmulatedSource = System.getenv(ENV_EMULATED_STORAGE_SOURCE);
-            String rawEmulatedTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET);
+            mUserId = userId;
+        }
 
-            String rawMediaStorage = System.getenv(ENV_MEDIA_STORAGE);
-            if (TextUtils.isEmpty(rawMediaStorage)) {
-                rawMediaStorage = "/data/media";
+        public File[] getExternalDirs() {
+            final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId);
+            final File[] files = new File[volumes.length];
+            for (int i = 0; i < volumes.length; i++) {
+                files[i] = volumes[i].getPathFile();
             }
-
-            ArrayList<File> externalForVold = Lists.newArrayList();
-            ArrayList<File> externalForApp = Lists.newArrayList();
-
-            if (!TextUtils.isEmpty(rawEmulatedTarget)) {
-                // Device has emulated storage; external storage paths should have
-                // userId burned into them.
-                final String rawUserId = Integer.toString(userId);
-                final File emulatedSourceBase = new File(rawEmulatedSource);
-                final File emulatedTargetBase = new File(rawEmulatedTarget);
-                final File mediaBase = new File(rawMediaStorage);
-
-                // /storage/emulated/0
-                externalForVold.add(buildPath(emulatedSourceBase, rawUserId));
-                externalForApp.add(buildPath(emulatedTargetBase, rawUserId));
-                // /data/media/0
-                mEmulatedDirForDirect = buildPath(mediaBase, rawUserId);
-
-            } else {
-                // Device has physical external storage; use plain paths.
-                if (TextUtils.isEmpty(rawExternalStorage)) {
-                    Log.w(TAG, "EXTERNAL_STORAGE undefined; falling back to default");
-                    rawExternalStorage = "/storage/sdcard0";
-                }
-
-                // /storage/sdcard0
-                externalForVold.add(new File(rawExternalStorage));
-                externalForApp.add(new File(rawExternalStorage));
-                // /data/media
-                mEmulatedDirForDirect = new File(rawMediaStorage);
-            }
-
-            // Splice in any secondary storage paths, but only for owner
-            final String rawSecondaryStorage = System.getenv(ENV_SECONDARY_STORAGE);
-            if (!TextUtils.isEmpty(rawSecondaryStorage) && userId == UserHandle.USER_OWNER) {
-                for (String secondaryPath : rawSecondaryStorage.split(":")) {
-                    externalForVold.add(new File(secondaryPath));
-                    externalForApp.add(new File(secondaryPath));
-                }
-            }
-
-            mExternalDirsForVold = externalForVold.toArray(new File[externalForVold.size()]);
-            mExternalDirsForApp = externalForApp.toArray(new File[externalForApp.size()]);
+            return files;
         }
 
         @Deprecated
         public File getExternalStorageDirectory() {
-            return mExternalDirsForApp[0];
+            return getExternalDirs()[0];
         }
 
         @Deprecated
@@ -155,60 +97,36 @@
             return buildExternalStoragePublicDirs(type)[0];
         }
 
-        public File[] getExternalDirsForVold() {
-            return mExternalDirsForVold;
-        }
-
-        public File[] getExternalDirsForApp() {
-            return mExternalDirsForApp;
-        }
-
-        public File getMediaDir() {
-            return mEmulatedDirForDirect;
-        }
-
         public File[] buildExternalStoragePublicDirs(String type) {
-            return buildPaths(mExternalDirsForApp, type);
+            return buildPaths(getExternalDirs(), type);
         }
 
         public File[] buildExternalStorageAndroidDataDirs() {
-            return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA);
+            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA);
         }
 
         public File[] buildExternalStorageAndroidObbDirs() {
-            return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB);
+            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_OBB);
         }
 
         public File[] buildExternalStorageAppDataDirs(String packageName) {
-            return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName);
-        }
-
-        public File[] buildExternalStorageAppDataDirsForVold(String packageName) {
-            return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_DATA, packageName);
+            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName);
         }
 
         public File[] buildExternalStorageAppMediaDirs(String packageName) {
-            return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_MEDIA, packageName);
-        }
-
-        public File[] buildExternalStorageAppMediaDirsForVold(String packageName) {
-            return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_MEDIA, packageName);
+            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_MEDIA, packageName);
         }
 
         public File[] buildExternalStorageAppObbDirs(String packageName) {
-            return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB, packageName);
-        }
-
-        public File[] buildExternalStorageAppObbDirsForVold(String packageName) {
-            return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_OBB, packageName);
+            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_OBB, packageName);
         }
 
         public File[] buildExternalStorageAppFilesDirs(String packageName) {
-            return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_FILES);
+            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName, DIR_FILES);
         }
 
         public File[] buildExternalStorageAppCacheDirs(String packageName) {
-            return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE);
+            return buildPaths(getExternalDirs(), DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE);
         }
     }
 
@@ -220,6 +138,11 @@
         return DIR_ANDROID_ROOT;
     }
 
+    /** {@hide} */
+    public static File getStorageDirectory() {
+        return DIR_ANDROID_STORAGE;
+    }
+
     /**
      * Return root directory of the "oem" partition holding OEM customizations,
      * if any. If present, the partition is mounted read-only.
@@ -270,17 +193,6 @@
     }
 
     /**
-     * Return directory used for internal media storage, which is protected by
-     * {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}.
-     *
-     * @hide
-     */
-    public static File getMediaStorageDirectory() {
-        throwIfUserRequired();
-        return sCurrentUser.getMediaDir();
-    }
-
-    /**
      * Return the system directory for a user. This is for use by system services to store
      * files relating to the user. This directory will be automatically deleted when the user
      * is removed.
@@ -389,7 +301,7 @@
      */
     public static File getExternalStorageDirectory() {
         throwIfUserRequired();
-        return sCurrentUser.getExternalDirsForApp()[0];
+        return sCurrentUser.getExternalDirs()[0];
     }
 
     /** {@hide} */
@@ -402,18 +314,6 @@
         return buildPath(getLegacyExternalStorageDirectory(), DIR_ANDROID, DIR_OBB);
     }
 
-    /** {@hide} */
-    public static File getEmulatedStorageSource(int userId) {
-        // /mnt/shell/emulated/0
-        return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), String.valueOf(userId));
-    }
-
-    /** {@hide} */
-    public static File getEmulatedStorageObbSource() {
-        // /mnt/shell/emulated/obb
-        return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), DIR_OBB);
-    }
-
     /**
      * Standard directory in which to place any audio files that should be
      * in the regular list of music for the user.
@@ -683,6 +583,13 @@
     public static final String MEDIA_UNMOUNTABLE = "unmountable";
 
     /**
+     * Storage state if the media is in the process of being ejected.
+     *
+     * @see #getExternalStorageState(File)
+     */
+    public static final String MEDIA_EJECTING = "ejecting";
+
+    /**
      * Returns the current state of the primary "external" storage device.
      * 
      * @see #getExternalStorageDirectory()
@@ -693,7 +600,7 @@
      *         {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
      */
     public static String getExternalStorageState() {
-        final File externalDir = sCurrentUser.getExternalDirsForApp()[0];
+        final File externalDir = sCurrentUser.getExternalDirs()[0];
         return getExternalStorageState(externalDir);
     }
 
@@ -716,17 +623,12 @@
      *         {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
      */
     public static String getExternalStorageState(File path) {
-        final StorageVolume volume = getStorageVolume(path);
+        final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
         if (volume != null) {
-            final IMountService mountService = IMountService.Stub.asInterface(
-                    ServiceManager.getService("mount"));
-            try {
-                return mountService.getVolumeState(volume.getPath());
-            } catch (RemoteException e) {
-            }
+            return volume.getState();
+        } else {
+            return MEDIA_UNKNOWN;
         }
-
-        return Environment.MEDIA_UNKNOWN;
     }
 
     /**
@@ -738,7 +640,7 @@
      */
     public static boolean isExternalStorageRemovable() {
         if (isStorageDisabled()) return false;
-        final File externalDir = sCurrentUser.getExternalDirsForApp()[0];
+        final File externalDir = sCurrentUser.getExternalDirs()[0];
         return isExternalStorageRemovable(externalDir);
     }
 
@@ -753,7 +655,7 @@
      *             device.
      */
     public static boolean isExternalStorageRemovable(File path) {
-        final StorageVolume volume = getStorageVolume(path);
+        final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
         if (volume != null) {
             return volume.isRemovable();
         } else {
@@ -771,7 +673,7 @@
      */
     public static boolean isExternalStorageEmulated() {
         if (isStorageDisabled()) return false;
-        final File externalDir = sCurrentUser.getExternalDirsForApp()[0];
+        final File externalDir = sCurrentUser.getExternalDirs()[0];
         return isExternalStorageEmulated(externalDir);
     }
 
@@ -784,7 +686,7 @@
      *             device.
      */
     public static boolean isExternalStorageEmulated(File path) {
-        final StorageVolume volume = getStorageVolume(path);
+        final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
         if (volume != null) {
             return volume.isEmulated();
         } else {
@@ -797,19 +699,6 @@
         return path == null ? new File(defaultPath) : new File(path);
     }
 
-    private static String getCanonicalPathOrNull(String variableName) {
-        String path = System.getenv(variableName);
-        if (path == null) {
-            return null;
-        }
-        try {
-            return new File(path).getCanonicalPath();
-        } catch (IOException e) {
-            Log.w(TAG, "Unable to resolve canonical path for " + path);
-            return null;
-        }
-    }
-
     /** {@hide} */
     public static void setUserRequired(boolean userRequired) {
         sUserRequired = userRequired;
@@ -856,28 +745,6 @@
         return SystemProperties.getBoolean("config.disable_storage", false);
     }
 
-    private static StorageVolume getStorageVolume(File path) {
-        try {
-            path = path.getCanonicalFile();
-        } catch (IOException e) {
-            return null;
-        }
-
-        try {
-            final IMountService mountService = IMountService.Stub.asInterface(
-                    ServiceManager.getService("mount"));
-            final StorageVolume[] volumes = mountService.getVolumeList();
-            for (StorageVolume volume : volumes) {
-                if (FileUtils.contains(volume.getPathFile(), path)) {
-                    return volume;
-                }
-            }
-        } catch (RemoteException e) {
-        }
-
-        return null;
-    }
-
     /**
      * If the given path exists on emulated external storage, return the
      * translated backing path hosted on internal storage. This bypasses any
@@ -891,26 +758,7 @@
      * @hide
      */
     public static File maybeTranslateEmulatedPathToInternal(File path) {
-        // Fast return if not emulated, or missing variables
-        if (!Environment.isExternalStorageEmulated()
-                || CANONCIAL_EMULATED_STORAGE_TARGET == null) {
-            return path;
-        }
-
-        try {
-            final String rawPath = path.getCanonicalPath();
-            if (rawPath.startsWith(CANONCIAL_EMULATED_STORAGE_TARGET)) {
-                final File internalPath = new File(DIR_MEDIA_STORAGE,
-                        rawPath.substring(CANONCIAL_EMULATED_STORAGE_TARGET.length()));
-                if (internalPath.exists()) {
-                    return internalPath;
-                }
-            }
-        } catch (IOException e) {
-            Log.w(TAG, "Failed to resolve canonical path for " + path);
-        }
-
-        // Unable to translate to internal path; use original
+        // TODO: bring back this optimization
         return path;
     }
 }
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 0a724a1..b302f95 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -369,6 +369,23 @@
      * {@link File#getCanonicalFile()} to avoid symlink or path traversal
      * attacks.
      */
+    public static boolean contains(File[] dirs, File file) {
+        for (File dir : dirs) {
+            if (contains(dir, file)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Test if a file lives under the given directory, either as a direct child
+     * or a distant grandchild.
+     * <p>
+     * Both files <em>must</em> have been resolved using
+     * {@link File#getCanonicalFile()} to avoid symlink or path traversal
+     * attacks.
+     */
     public static boolean contains(File dir, File file) {
         if (file == null) return false;
 
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 16dac7d..804d3d0 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -43,6 +43,7 @@
     boolean isInteractive();
     boolean isPowerSaveMode();
     boolean setPowerSaveMode(boolean mode);
+    boolean isDeviceIdleMode();
 
     void reboot(boolean confirm, String reason, boolean wait);
     void shutdown(boolean confirm, boolean wait);
@@ -50,6 +51,7 @@
 
     void setStayOnSetting(int val);
     void boostScreenBrightness(long time);
+    boolean isScreenBrightnessBoosted();
 
     // temporarily overrides the screen brightness settings to allow the user to
     // see the effect of a settings change without applying it immediately
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index de970cb..01c9a21 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -712,6 +712,22 @@
     }
 
     /**
+     * Returns whether the screen brightness is currently boosted to maximum, caused by a call
+     * to {@link #boostScreenBrightness(long)}.
+     * @return {@code True} if the screen brightness is currently boosted. {@code False} otherwise.
+     *
+     * @hide
+     */
+    @SystemApi
+    public boolean isScreenBrightnessBoosted() {
+        try {
+            return mService.isScreenBrightnessBoosted();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Sets the brightness of the backlights (screen, keyboard, button).
      * <p>
      * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
@@ -856,6 +872,23 @@
     }
 
     /**
+     * Returns true if the device is currently in idle mode.  This happens when a device
+     * has been sitting unused and unmoving for a sufficiently long period of time, so that
+     * it decides to go into a lower power-use state.  This may involve things like turning
+     * off network access to apps.  You can monitor for changes to this state with
+     * {@link #ACTION_DEVICE_IDLE_MODE_CHANGED}.
+     *
+     * @return Returns true if currently in low power mode, else false.
+     */
+    public boolean isDeviceIdleMode() {
+        try {
+            return mService.isDeviceIdleMode();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Turn off the device.
      *
      * @param confirm If true, shows a shutdown confirmation dialog.
@@ -879,6 +912,14 @@
             = "android.os.action.POWER_SAVE_MODE_CHANGED";
 
     /**
+     * Intent that is broadcast when the state of {@link #isDeviceIdleMode()} changes.
+     * This broadcast is only sent to registered receivers.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_DEVICE_IDLE_MODE_CHANGED
+            = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
+
+    /**
      * Intent that is broadcast when the state of {@link #isPowerSaveMode()} is about to change.
      * This broadcast is only sent to registered receivers.
      *
@@ -892,6 +933,16 @@
     public static final String EXTRA_POWER_SAVE_MODE = "mode";
 
     /**
+     * Intent that is broadcast when the state of {@link #isScreenBrightnessBoosted()} has changed.
+     * This broadcast is only sent to registered receivers.
+     *
+     * @hide
+     **/
+    @SystemApi
+    public static final String ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED
+            = "android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED";
+
+    /**
      * A wake lock is a mechanism to indicate that your application needs
      * to have the device stay on.
      * <p>
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index 6f31768..00ab262 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -117,7 +117,7 @@
     /**
      * Used by the dream manager to override certain properties while dozing.
      *
-     * @param screenState The overridden screen state, or {@link Display.STATE_UNKNOWN}
+     * @param screenState The overridden screen state, or {@link Display#STATE_UNKNOWN}
      * to disable the override.
      * @param screenBrightness The overridden screen brightness, or
      * {@link PowerManager#BRIGHTNESS_DEFAULT} to disable the override.
@@ -132,4 +132,6 @@
     public interface LowPowerModeListener {
         public void onLowPowerModeChanged(boolean enabled);
     }
+
+    public abstract void setDeviceIdleMode(boolean enabled);
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 0de9c70..355ec8c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -637,10 +637,8 @@
             if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
                 argsForZygote.add("--enable-assert");
             }
-            if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
-                argsForZygote.add("--mount-external-multiuser");
-            } else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
-                argsForZygote.add("--mount-external-multiuser-all");
+            if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
+                argsForZygote.add("--mount-external-default");
             }
             argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/core/java/android/os/storage/DiskInfo.aidl
similarity index 75%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to core/java/android/os/storage/DiskInfo.aidl
index 272c321..5126c19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/core/java/android/os/storage/DiskInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+package android.os.storage;
 
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
-}
+parcelable DiskInfo;
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
new file mode 100644
index 0000000..56c55f1
--- /dev/null
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -0,0 +1,127 @@
+/*
+ * 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.os.storage;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.DebugUtils;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
+
+import java.io.CharArrayWriter;
+
+/**
+ * Information about a physical disk which may contain one or more
+ * {@link VolumeInfo}.
+ *
+ * @hide
+ */
+public class DiskInfo implements Parcelable {
+    public static final int FLAG_ADOPTABLE = 1 << 0;
+    public static final int FLAG_DEFAULT_PRIMARY = 1 << 1;
+    public static final int FLAG_SD = 1 << 2;
+    public static final int FLAG_USB = 1 << 3;
+
+    public final String id;
+    public final int flags;
+    public long size;
+    public String label;
+    public String[] volumes;
+
+    public DiskInfo(String id, int flags) {
+        this.id = Preconditions.checkNotNull(id);
+        this.flags = flags;
+    }
+
+    public DiskInfo(Parcel parcel) {
+        id = parcel.readString();
+        flags = parcel.readInt();
+        size = parcel.readLong();
+        label = parcel.readString();
+        volumes = parcel.readStringArray();
+    }
+
+    public String getDescription(Context context) {
+        // TODO: splice vendor label into these strings
+        if ((flags & FLAG_SD) != 0) {
+            return context.getString(com.android.internal.R.string.storage_sd_card);
+        } else if ((flags & FLAG_USB) != 0) {
+            return context.getString(com.android.internal.R.string.storage_usb);
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public String toString() {
+        final CharArrayWriter writer = new CharArrayWriter();
+        dump(new IndentingPrintWriter(writer, "    ", 80));
+        return writer.toString();
+    }
+
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("DiskInfo:");
+        pw.increaseIndent();
+        pw.printPair("id", id);
+        pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags));
+        pw.printPair("size", size);
+        pw.printPair("label", label);
+        pw.printPair("volumes", volumes);
+        pw.decreaseIndent();
+        pw.println();
+    }
+
+    @Override
+    public DiskInfo clone() {
+        final Parcel temp = Parcel.obtain();
+        try {
+            writeToParcel(temp, 0);
+            temp.setDataPosition(0);
+            return CREATOR.createFromParcel(temp);
+        } finally {
+            temp.recycle();
+        }
+    }
+
+    public static final Creator<DiskInfo> CREATOR = new Creator<DiskInfo>() {
+        @Override
+        public DiskInfo createFromParcel(Parcel in) {
+            return new DiskInfo(in);
+        }
+
+        @Override
+        public DiskInfo[] newArray(int size) {
+            return new DiskInfo[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(id);
+        parcel.writeInt(flags);
+        parcel.writeLong(size);
+        parcel.writeString(label);
+        parcel.writeStringArray(volumes);
+    }
+}
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 6209c2a..10ffd48 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -757,12 +757,13 @@
                 return _result;
             }
 
-            public StorageVolume[] getVolumeList() throws RemoteException {
+            public StorageVolume[] getVolumeList(int userId) throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
                 StorageVolume[] _result;
                 try {
                     _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeInt(userId);
                     mRemote.transact(Stub.TRANSACTION_getVolumeList, _data, _reply, 0);
                     _reply.readException();
                     _result = _reply.createTypedArray(StorageVolume.CREATOR);
@@ -903,6 +904,131 @@
                 }
                 return;
             }
+
+            @Override
+            public DiskInfo[] getDisks() throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                DiskInfo[] _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    mRemote.transact(Stub.TRANSACTION_getDisks, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.createTypedArray(DiskInfo.CREATOR);
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+            }
+
+            @Override
+            public VolumeInfo[] getVolumes() throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                VolumeInfo[] _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    mRemote.transact(Stub.TRANSACTION_getVolumes, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.createTypedArray(VolumeInfo.CREATOR);
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+            }
+
+            @Override
+            public void mount(String volId) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(volId);
+                    mRemote.transact(Stub.TRANSACTION_mount, _data, _reply, 0);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            @Override
+            public void unmount(String volId) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(volId);
+                    mRemote.transact(Stub.TRANSACTION_unmount, _data, _reply, 0);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            @Override
+            public void format(String volId) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(volId);
+                    mRemote.transact(Stub.TRANSACTION_format, _data, _reply, 0);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            @Override
+            public void partitionPublic(String diskId) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(diskId);
+                    mRemote.transact(Stub.TRANSACTION_partitionPublic, _data, _reply, 0);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            @Override
+            public void partitionPrivate(String diskId) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(diskId);
+                    mRemote.transact(Stub.TRANSACTION_partitionPrivate, _data, _reply, 0);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            @Override
+            public void partitionMixed(String diskId, int ratio) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(diskId);
+                    _data.writeInt(ratio);
+                    mRemote.transact(Stub.TRANSACTION_partitionMixed, _data, _reply, 0);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
         }
 
         private static final String DESCRIPTOR = "IMountService";
@@ -995,6 +1121,17 @@
 
         static final int TRANSACTION_waitForAsecScan = IBinder.FIRST_CALL_TRANSACTION + 43;
 
+        static final int TRANSACTION_getDisks = IBinder.FIRST_CALL_TRANSACTION + 44;
+        static final int TRANSACTION_getVolumes = IBinder.FIRST_CALL_TRANSACTION + 45;
+
+        static final int TRANSACTION_mount = IBinder.FIRST_CALL_TRANSACTION + 46;
+        static final int TRANSACTION_unmount = IBinder.FIRST_CALL_TRANSACTION + 47;
+        static final int TRANSACTION_format = IBinder.FIRST_CALL_TRANSACTION + 48;
+
+        static final int TRANSACTION_partitionPublic = IBinder.FIRST_CALL_TRANSACTION + 49;
+        static final int TRANSACTION_partitionPrivate = IBinder.FIRST_CALL_TRANSACTION + 50;
+        static final int TRANSACTION_partitionMixed = IBinder.FIRST_CALL_TRANSACTION + 51;
+
         /**
          * Cast an IBinder object into an IMountService interface, generating a
          * proxy if needed.
@@ -1308,7 +1445,8 @@
                 }
                 case TRANSACTION_getVolumeList: {
                     data.enforceInterface(DESCRIPTOR);
-                    StorageVolume[] result = getVolumeList();
+                    int userId = data.readInt();
+                    StorageVolume[] result = getVolumeList(userId);
                     reply.writeNoException();
                     reply.writeTypedArray(result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                     return true;
@@ -1419,6 +1557,63 @@
                     reply.writeNoException();
                     return true;
                 }
+                case TRANSACTION_getDisks: {
+                    data.enforceInterface(DESCRIPTOR);
+                    DiskInfo[] disks = getDisks();
+                    reply.writeNoException();
+                    reply.writeTypedArray(disks, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+                    return true;
+                }
+                case TRANSACTION_getVolumes: {
+                    data.enforceInterface(DESCRIPTOR);
+                    VolumeInfo[] volumes = getVolumes();
+                    reply.writeNoException();
+                    reply.writeTypedArray(volumes, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+                    return true;
+                }
+                case TRANSACTION_mount: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String volId = data.readString();
+                    mount(volId);
+                    reply.writeNoException();
+                    return true;
+                }
+                case TRANSACTION_unmount: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String volId = data.readString();
+                    unmount(volId);
+                    reply.writeNoException();
+                    return true;
+                }
+                case TRANSACTION_format: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String volId = data.readString();
+                    format(volId);
+                    reply.writeNoException();
+                    return true;
+                }
+                case TRANSACTION_partitionPublic: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String diskId = data.readString();
+                    partitionPublic(diskId);
+                    reply.writeNoException();
+                    return true;
+                }
+                case TRANSACTION_partitionPrivate: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String diskId = data.readString();
+                    partitionPrivate(diskId);
+                    reply.writeNoException();
+                    return true;
+                }
+                case TRANSACTION_partitionMixed: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String diskId = data.readString();
+                    int ratio = data.readInt();
+                    partitionMixed(diskId, ratio);
+                    reply.writeNoException();
+                    return true;
+                }
             }
             return super.onTransact(code, data, reply, flags);
         }
@@ -1630,7 +1825,7 @@
     /**
      * Returns list of all mountable volumes.
      */
-    public StorageVolume[] getVolumeList() throws RemoteException;
+    public StorageVolume[] getVolumeList(int userId) throws RemoteException;
 
     /**
      * Gets the path on the filesystem for the ASEC container itself.
@@ -1705,4 +1900,15 @@
     public void runMaintenance() throws RemoteException;
 
     public void waitForAsecScan() throws RemoteException;
+
+    public DiskInfo[] getDisks() throws RemoteException;
+    public VolumeInfo[] getVolumes() throws RemoteException;
+
+    public void mount(String volId) throws RemoteException;
+    public void unmount(String volId) throws RemoteException;
+    public void format(String volId) throws RemoteException;
+
+    public void partitionPublic(String diskId) throws RemoteException;
+    public void partitionPrivate(String diskId) throws RemoteException;
+    public void partitionMixed(String diskId, int ratio) throws RemoteException;
 }
diff --git a/core/java/android/os/storage/IMountServiceListener.java b/core/java/android/os/storage/IMountServiceListener.java
index d5c5fa5..3965f9d 100644
--- a/core/java/android/os/storage/IMountServiceListener.java
+++ b/core/java/android/os/storage/IMountServiceListener.java
@@ -75,16 +75,22 @@
                 }
                 case TRANSACTION_onStorageStateChanged: {
                     data.enforceInterface(DESCRIPTOR);
-                    String path;
-                    path = data.readString();
-                    String oldState;
-                    oldState = data.readString();
-                    String newState;
-                    newState = data.readString();
+                    final String path = data.readString();
+                    final String oldState = data.readString();
+                    final String newState = data.readString();
                     this.onStorageStateChanged(path, oldState, newState);
                     reply.writeNoException();
                     return true;
                 }
+                case TRANSACTION_onVolumeStateChanged: {
+                    data.enforceInterface(DESCRIPTOR);
+                    final VolumeInfo vol = (VolumeInfo) data.readParcelable(null);
+                    final int oldState = data.readInt();
+                    final int newState = data.readInt();
+                    onVolumeStateChanged(vol, oldState, newState);
+                    reply.writeNoException();
+                    return true;
+                }
             }
             return super.onTransact(code, data, reply, flags);
         }
@@ -116,7 +122,7 @@
                     _data.writeInterfaceToken(DESCRIPTOR);
                     _data.writeInt(((connected) ? (1) : (0)));
                     mRemote.transact(Stub.TRANSACTION_onUsbMassStorageConnectionChanged, _data,
-                            _reply, 0);
+                            _reply, android.os.IBinder.FLAG_ONEWAY);
                     _reply.readException();
                 } finally {
                     _reply.recycle();
@@ -142,7 +148,27 @@
                     _data.writeString(path);
                     _data.writeString(oldState);
                     _data.writeString(newState);
-                    mRemote.transact(Stub.TRANSACTION_onStorageStateChanged, _data, _reply, 0);
+                    mRemote.transact(Stub.TRANSACTION_onStorageStateChanged, _data, _reply,
+                            android.os.IBinder.FLAG_ONEWAY);
+                    _reply.readException();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+            }
+
+            @Override
+            public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState)
+                    throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeParcelable(vol, 0);
+                    _data.writeInt(oldState);
+                    _data.writeInt(newState);
+                    mRemote.transact(Stub.TRANSACTION_onVolumeStateChanged, _data, _reply,
+                            android.os.IBinder.FLAG_ONEWAY);
                     _reply.readException();
                 } finally {
                     _reply.recycle();
@@ -154,6 +180,8 @@
         static final int TRANSACTION_onUsbMassStorageConnectionChanged = (IBinder.FIRST_CALL_TRANSACTION + 0);
 
         static final int TRANSACTION_onStorageStateChanged = (IBinder.FIRST_CALL_TRANSACTION + 1);
+
+        static final int TRANSACTION_onVolumeStateChanged = (IBinder.FIRST_CALL_TRANSACTION + 2);
     }
 
     /**
@@ -173,4 +201,7 @@
      */
     public void onStorageStateChanged(String path, String oldState, String newState)
             throws RemoteException;
+
+    public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState)
+            throws RemoteException;
 }
diff --git a/core/java/android/os/storage/StorageEventListener.java b/core/java/android/os/storage/StorageEventListener.java
index 6c73d04..29d5494 100644
--- a/core/java/android/os/storage/StorageEventListener.java
+++ b/core/java/android/os/storage/StorageEventListener.java
@@ -21,7 +21,7 @@
  * 
  * @hide
  */
-public abstract class StorageEventListener {
+public class StorageEventListener {
     /**
      * Called when the detection state of a USB Mass Storage host has changed.
      * @param connected true if the USB mass storage is connected.
@@ -37,4 +37,7 @@
      */
     public void onStorageStateChanged(String path, String oldState, String newState) {
     }
+
+    public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
+    }
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 2785ee8..5a5d8b7 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -18,26 +18,32 @@
 
 import static android.net.TrafficStats.MB_IN_BYTES;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.os.Environment;
+import android.os.FileUtils;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.internal.os.SomeArgs;
 import com.android.internal.util.Preconditions;
 
 import java.io.File;
 import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -60,46 +66,70 @@
 public class StorageManager {
     private static final String TAG = "StorageManager";
 
+    /** {@hide} */
+    public static final String PROP_PRIMARY_PHYSICAL = "ro.vold.primary_physical";
+
+    private final Context mContext;
     private final ContentResolver mResolver;
 
-    /*
-     * Our internal MountService binder reference
-     */
     private final IMountService mMountService;
+    private final Looper mLooper;
+    private final AtomicInteger mNextNonce = new AtomicInteger(0);
 
-    /*
-     * The looper target for callbacks
-     */
-    private final Looper mTgtLooper;
+    private final ArrayList<StorageEventListenerDelegate> mDelegates = new ArrayList<>();
 
-    /*
-     * Target listener for binder callbacks
-     */
-    private MountServiceBinderListener mBinderListener;
+    private static class StorageEventListenerDelegate extends IMountServiceListener.Stub implements
+            Handler.Callback {
+        private static final int MSG_STORAGE_STATE_CHANGED = 1;
+        private static final int MSG_VOLUME_STATE_CHANGED = 2;
 
-    /*
-     * List of our listeners
-     */
-    private List<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>();
+        final StorageEventListener mCallback;
+        final Handler mHandler;
 
-    /*
-     * Next available nonce
-     */
-    final private AtomicInteger mNextNonce = new AtomicInteger(0);
-
-    private class MountServiceBinderListener extends IMountServiceListener.Stub {
-        public void onUsbMassStorageConnectionChanged(boolean available) {
-            final int size = mListeners.size();
-            for (int i = 0; i < size; i++) {
-                mListeners.get(i).sendShareAvailabilityChanged(available);
-            }
+        public StorageEventListenerDelegate(StorageEventListener callback, Looper looper) {
+            mCallback = callback;
+            mHandler = new Handler(looper, this);
         }
 
-        public void onStorageStateChanged(String path, String oldState, String newState) {
-            final int size = mListeners.size();
-            for (int i = 0; i < size; i++) {
-                mListeners.get(i).sendStorageStateChanged(path, oldState, newState);
+        @Override
+        public boolean handleMessage(Message msg) {
+            final SomeArgs args = (SomeArgs) msg.obj;
+            switch (msg.what) {
+                case MSG_STORAGE_STATE_CHANGED:
+                    mCallback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
+                            (String) args.arg3);
+                    args.recycle();
+                    return true;
+                case MSG_VOLUME_STATE_CHANGED:
+                    mCallback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
+                    args.recycle();
+                    return true;
             }
+            args.recycle();
+            return false;
+        }
+
+        @Override
+        public void onUsbMassStorageConnectionChanged(boolean connected) throws RemoteException {
+            // Ignored
+        }
+
+        @Override
+        public void onStorageStateChanged(String path, String oldState, String newState) {
+            final SomeArgs args = SomeArgs.obtain();
+            args.arg1 = path;
+            args.arg2 = oldState;
+            args.arg3 = newState;
+            mHandler.obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
+        }
+
+        @Override
+        public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
+            final SomeArgs args = SomeArgs.obtain();
+            args.arg1 = vol;
+            args.argi2 = oldState;
+            args.argi3 = newState;
+            mHandler.obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
         }
     }
 
@@ -154,7 +184,7 @@
         ObbListenerDelegate(OnObbStateChangeListener listener) {
             nonce = getNextNonce();
             mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
-            mHandler = new Handler(mTgtLooper) {
+            mHandler = new Handler(mLooper) {
                 @Override
                 public void handleMessage(Message msg) {
                     final OnObbStateChangeListener changeListener = getListener();
@@ -162,14 +192,7 @@
                         return;
                     }
 
-                    StorageEvent e = (StorageEvent) msg.obj;
-
-                    if (msg.what == StorageEvent.EVENT_OBB_STATE_CHANGED) {
-                        ObbStateChangedStorageEvent ev = (ObbStateChangedStorageEvent) e;
-                        changeListener.onObbStateChange(ev.path, ev.state);
-                    } else {
-                        Log.e(TAG, "Unsupported event " + msg.what);
-                    }
+                    changeListener.onObbStateChange((String) msg.obj, msg.arg1);
                 }
             };
         }
@@ -182,115 +205,7 @@
         }
 
         void sendObbStateChanged(String path, int state) {
-            ObbStateChangedStorageEvent e = new ObbStateChangedStorageEvent(path, state);
-            mHandler.sendMessage(e.getMessage());
-        }
-    }
-
-    /**
-     * Message sent during an OBB status change event.
-     */
-    private class ObbStateChangedStorageEvent extends StorageEvent {
-        public final String path;
-
-        public final int state;
-
-        public ObbStateChangedStorageEvent(String path, int state) {
-            super(EVENT_OBB_STATE_CHANGED);
-            this.path = path;
-            this.state = state;
-        }
-    }
-
-    /**
-     * Private base class for messages sent between the callback thread
-     * and the target looper handler.
-     */
-    private class StorageEvent {
-        static final int EVENT_UMS_CONNECTION_CHANGED = 1;
-        static final int EVENT_STORAGE_STATE_CHANGED = 2;
-        static final int EVENT_OBB_STATE_CHANGED = 3;
-
-        private Message mMessage;
-
-        public StorageEvent(int what) {
-            mMessage = Message.obtain();
-            mMessage.what = what;
-            mMessage.obj = this;
-        }
-
-        public Message getMessage() {
-            return mMessage;
-        }
-    }
-
-    /**
-     * Message sent on a USB mass storage connection change.
-     */
-    private class UmsConnectionChangedStorageEvent extends StorageEvent {
-        public boolean available;
-
-        public UmsConnectionChangedStorageEvent(boolean a) {
-            super(EVENT_UMS_CONNECTION_CHANGED);
-            available = a;
-        }
-    }
-
-    /**
-     * Message sent on volume state change.
-     */
-    private class StorageStateChangedStorageEvent extends StorageEvent {
-        public String path;
-        public String oldState;
-        public String newState;
-
-        public StorageStateChangedStorageEvent(String p, String oldS, String newS) {
-            super(EVENT_STORAGE_STATE_CHANGED);
-            path = p;
-            oldState = oldS;
-            newState = newS;
-        }
-    }
-
-    /**
-     * Private class containing sender and receiver code for StorageEvents.
-     */
-    private class ListenerDelegate {
-        final StorageEventListener mStorageEventListener;
-        private final Handler mHandler;
-
-        ListenerDelegate(StorageEventListener listener) {
-            mStorageEventListener = listener;
-            mHandler = new Handler(mTgtLooper) {
-                @Override
-                public void handleMessage(Message msg) {
-                    StorageEvent e = (StorageEvent) msg.obj;
-
-                    if (msg.what == StorageEvent.EVENT_UMS_CONNECTION_CHANGED) {
-                        UmsConnectionChangedStorageEvent ev = (UmsConnectionChangedStorageEvent) e;
-                        mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available);
-                    } else if (msg.what == StorageEvent.EVENT_STORAGE_STATE_CHANGED) {
-                        StorageStateChangedStorageEvent ev = (StorageStateChangedStorageEvent) e;
-                        mStorageEventListener.onStorageStateChanged(ev.path, ev.oldState, ev.newState);
-                    } else {
-                        Log.e(TAG, "Unsupported event " + msg.what);
-                    }
-                }
-            };
-        }
-
-        StorageEventListener getListener() {
-            return mStorageEventListener;
-        }
-
-        void sendShareAvailabilityChanged(boolean available) {
-            UmsConnectionChangedStorageEvent e = new UmsConnectionChangedStorageEvent(available);
-            mHandler.sendMessage(e.getMessage());
-        }
-
-        void sendStorageStateChanged(String path, String oldState, String newState) {
-            StorageStateChangedStorageEvent e = new StorageStateChangedStorageEvent(path, oldState, newState);
-            mHandler.sendMessage(e.getMessage());
+            mHandler.obtainMessage(0, state, 0, path).sendToTarget();
         }
     }
 
@@ -311,13 +226,13 @@
      *
      * @hide
      */
-    public StorageManager(ContentResolver resolver, Looper tgtLooper) throws RemoteException {
-        mResolver = resolver;
-        mTgtLooper = tgtLooper;
+    public StorageManager(Context context, Looper looper) {
+        mContext = context;
+        mResolver = context.getContentResolver();
+        mLooper = looper;
         mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
         if (mMountService == null) {
-            Log.e(TAG, "Unable to connect to mount service! - is it running yet?");
-            return;
+            throw new IllegalStateException("Failed to find running mount service");
         }
     }
 
@@ -329,21 +244,15 @@
      * @hide
      */
     public void registerListener(StorageEventListener listener) {
-        if (listener == null) {
-            return;
-        }
-
-        synchronized (mListeners) {
-            if (mBinderListener == null ) {
-                try {
-                    mBinderListener = new MountServiceBinderListener();
-                    mMountService.registerListener(mBinderListener);
-                } catch (RemoteException rex) {
-                    Log.e(TAG, "Register mBinderListener failed");
-                    return;
-                }
+        synchronized (mDelegates) {
+            final StorageEventListenerDelegate delegate = new StorageEventListenerDelegate(listener,
+                    mLooper);
+            try {
+                mMountService.registerListener(delegate);
+            } catch (RemoteException e) {
+                throw e.rethrowAsRuntimeException();
             }
-            mListeners.add(new ListenerDelegate(listener));
+            mDelegates.add(delegate);
         }
     }
 
@@ -355,28 +264,19 @@
      * @hide
      */
     public void unregisterListener(StorageEventListener listener) {
-        if (listener == null) {
-            return;
+        synchronized (mDelegates) {
+            for (Iterator<StorageEventListenerDelegate> i = mDelegates.iterator(); i.hasNext();) {
+                final StorageEventListenerDelegate delegate = i.next();
+                if (delegate.mCallback == listener) {
+                    try {
+                        mMountService.unregisterListener(delegate);
+                    } catch (RemoteException e) {
+                        throw e.rethrowAsRuntimeException();
+                    }
+                    i.remove();
+                }
+            }
         }
-
-        synchronized (mListeners) {
-            final int size = mListeners.size();
-            for (int i=0 ; i<size ; i++) {
-                ListenerDelegate l = mListeners.get(i);
-                if (l.getListener() == listener) {
-                    mListeners.remove(i);
-                    break;
-                }
-            }
-            if (mListeners.size() == 0 && mBinderListener != null) {
-                try {
-                    mMountService.unregisterListener(mBinderListener);
-                } catch (RemoteException rex) {
-                    Log.e(TAG, "Unregister mBinderListener failed");
-                    return;
-                }
-            }
-       }
     }
 
     /**
@@ -384,12 +284,8 @@
      *
      * @hide
      */
+    @Deprecated
     public void enableUsbMassStorage() {
-        try {
-            mMountService.setUsbMassStorageEnabled(true);
-        } catch (Exception ex) {
-            Log.e(TAG, "Failed to enable UMS", ex);
-        }
     }
 
     /**
@@ -397,12 +293,8 @@
      *
      * @hide
      */
+    @Deprecated
     public void disableUsbMassStorage() {
-        try {
-            mMountService.setUsbMassStorageEnabled(false);
-        } catch (Exception ex) {
-            Log.e(TAG, "Failed to disable UMS", ex);
-        }
     }
 
     /**
@@ -411,12 +303,8 @@
      *
      * @hide
      */
+    @Deprecated
     public boolean isUsbMassStorageConnected() {
-        try {
-            return mMountService.isUsbMassStorageConnected();
-        } catch (Exception ex) {
-            Log.e(TAG, "Failed to get UMS connection state", ex);
-        }
         return false;
     }
 
@@ -426,12 +314,8 @@
      *
      * @hide
      */
+    @Deprecated
     public boolean isUsbMassStorageEnabled() {
-        try {
-            return mMountService.isUsbMassStorageEnabled();
-        } catch (RemoteException rex) {
-            Log.e(TAG, "Failed to get UMS enable state", rex);
-        }
         return false;
     }
 
@@ -548,38 +432,170 @@
         return null;
     }
 
+    /** {@hide} */
+    public @NonNull List<DiskInfo> getDisks() {
+        try {
+            return Arrays.asList(mMountService.getDisks());
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /** {@hide} */
+    public @Nullable DiskInfo findDiskById(String id) {
+        Preconditions.checkNotNull(id);
+        // TODO; go directly to service to make this faster
+        for (DiskInfo disk : getDisks()) {
+            if (Objects.equals(disk.id, id)) {
+                return disk;
+            }
+        }
+        return null;
+    }
+
+    /** {@hide} */
+    public @Nullable VolumeInfo findVolumeById(String id) {
+        Preconditions.checkNotNull(id);
+        // TODO; go directly to service to make this faster
+        for (VolumeInfo vol : getVolumes()) {
+            if (Objects.equals(vol.id, id)) {
+                return vol;
+            }
+        }
+        return null;
+    }
+
+    /** {@hide} */
+    public @Nullable VolumeInfo findVolumeByUuid(String fsUuid) {
+        Preconditions.checkNotNull(fsUuid);
+        // TODO; go directly to service to make this faster
+        for (VolumeInfo vol : getVolumes()) {
+            if (Objects.equals(vol.fsUuid, fsUuid)) {
+                return vol;
+            }
+        }
+        return null;
+    }
+
+    /** {@hide} */
+    public @NonNull List<VolumeInfo> getVolumes() {
+        try {
+            return Arrays.asList(mMountService.getVolumes());
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /** {@hide} */
+    public void mount(String volId) {
+        try {
+            mMountService.mount(volId);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /** {@hide} */
+    public void unmount(String volId) {
+        try {
+            mMountService.unmount(volId);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /** {@hide} */
+    public void format(String volId) {
+        try {
+            mMountService.format(volId);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /** {@hide} */
+    public void partitionPublic(String diskId) {
+        try {
+            mMountService.partitionPublic(diskId);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /** {@hide} */
+    public void partitionPrivate(String diskId) {
+        try {
+            mMountService.partitionPrivate(diskId);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /** {@hide} */
+    public void partitionMixed(String diskId, int ratio) {
+        try {
+            mMountService.partitionMixed(diskId, ratio);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /** {@hide} */
+    public @Nullable StorageVolume getStorageVolume(File file) {
+        return getStorageVolume(getVolumeList(), file);
+    }
+
+    /** {@hide} */
+    public static @Nullable StorageVolume getStorageVolume(File file, int userId) {
+        return getStorageVolume(getVolumeList(userId), file);
+    }
+
+    /** {@hide} */
+    private static @Nullable StorageVolume getStorageVolume(StorageVolume[] volumes, File file) {
+        File canonicalFile = null;
+        try {
+            canonicalFile = file.getCanonicalFile();
+        } catch (IOException ignored) {
+            canonicalFile = null;
+        }
+        for (StorageVolume volume : volumes) {
+            if (volume.getPathFile().equals(file)) {
+                return volume;
+            }
+            if (FileUtils.contains(volume.getPathFile(), canonicalFile)) {
+                return volume;
+            }
+        }
+        return null;
+    }
+
     /**
      * Gets the state of a volume via its mountpoint.
      * @hide
      */
-    public String getVolumeState(String mountPoint) {
-         if (mMountService == null) return Environment.MEDIA_REMOVED;
-        try {
-            return mMountService.getVolumeState(mountPoint);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get volume state", e);
-            return null;
+    @Deprecated
+    public @NonNull String getVolumeState(String mountPoint) {
+        final StorageVolume vol = getStorageVolume(new File(mountPoint));
+        if (vol != null) {
+            return vol.getState();
+        } else {
+            return Environment.MEDIA_UNKNOWN;
         }
     }
 
-    /**
-     * Returns list of all mountable volumes.
-     * @hide
-     */
-    public StorageVolume[] getVolumeList() {
-        if (mMountService == null) return new StorageVolume[0];
+    /** {@hide} */
+    public @NonNull StorageVolume[] getVolumeList() {
+        return getVolumeList(mContext.getUserId());
+    }
+
+    /** {@hide} */
+    public static @NonNull StorageVolume[] getVolumeList(int userId) {
+        final IMountService mountService = IMountService.Stub.asInterface(
+                ServiceManager.getService("mount"));
         try {
-            Parcelable[] list = mMountService.getVolumeList();
-            if (list == null) return new StorageVolume[0];
-            int length = list.length;
-            StorageVolume[] result = new StorageVolume[length];
-            for (int i = 0; i < length; i++) {
-                result[i] = (StorageVolume)list[i];
-            }
-            return result;
+            return mountService.getVolumeList(userId);
         } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get volume list", e);
-            return null;
+            throw e.rethrowAsRuntimeException();
         }
     }
 
@@ -587,9 +603,9 @@
      * Returns list of paths for all mountable volumes.
      * @hide
      */
-    public String[] getVolumePaths() {
+    @Deprecated
+    public @NonNull String[] getVolumePaths() {
         StorageVolume[] volumes = getVolumeList();
-        if (volumes == null) return null;
         int count = volumes.length;
         String[] paths = new String[count];
         for (int i = 0; i < count; i++) {
@@ -599,21 +615,21 @@
     }
 
     /** {@hide} */
-    public StorageVolume getPrimaryVolume() {
+    public @NonNull StorageVolume getPrimaryVolume() {
         return getPrimaryVolume(getVolumeList());
     }
 
     /** {@hide} */
-    public static StorageVolume getPrimaryVolume(StorageVolume[] volumes) {
+    public static @NonNull StorageVolume getPrimaryVolume(StorageVolume[] volumes) {
         for (StorageVolume volume : volumes) {
             if (volume.isPrimary()) {
                 return volume;
             }
         }
-        Log.w(TAG, "No primary storage defined");
-        return null;
+        throw new IllegalStateException("Missing primary storage");
     }
 
+    /** {@hide} */
     private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
     private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES;
     private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES;
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 06565f1..d66e228 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -17,81 +17,83 @@
 package android.os.storage;
 
 import android.content.Context;
+import android.net.TrafficStats;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
 
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
 
 import java.io.CharArrayWriter;
 import java.io.File;
 
 /**
- * Description of a storage volume and its capabilities, including the
- * filesystem path where it may be mounted.
+ * Information about a storage volume that may be mounted. This is a legacy
+ * specialization of {@link VolumeInfo} which describes the volume for a
+ * specific user.
+ * <p>
+ * This class may be deprecated in the future.
  *
  * @hide
  */
 public class StorageVolume implements Parcelable {
 
-    // TODO: switch to more durable token
-    private int mStorageId;
-
+    private final String mId;
+    private final int mStorageId;
     private final File mPath;
-    private final int mDescriptionId;
+    private final String mDescription;
     private final boolean mPrimary;
     private final boolean mRemovable;
     private final boolean mEmulated;
-    private final int mMtpReserveSpace;
+    private final long mMtpReserveSize;
     private final boolean mAllowMassStorage;
-    /** Maximum file size for the storage, or zero for no limit */
     private final long mMaxFileSize;
-    /** When set, indicates exclusive ownership of this volume */
     private final UserHandle mOwner;
-
-    private String mUuid;
-    private String mUserLabel;
-    private String mState;
+    private final String mFsUuid;
+    private final String mState;
 
     // StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
     // ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
     // ACTION_MEDIA_BAD_REMOVAL, ACTION_MEDIA_UNMOUNTABLE and ACTION_MEDIA_EJECT broadcasts.
     public static final String EXTRA_STORAGE_VOLUME = "storage_volume";
 
-    public StorageVolume(File path, int descriptionId, boolean primary, boolean removable,
-            boolean emulated, int mtpReserveSpace, boolean allowMassStorage, long maxFileSize,
-            UserHandle owner) {
-        mPath = path;
-        mDescriptionId = descriptionId;
+    public StorageVolume(String id, int storageId, File path, String description, boolean primary,
+            boolean removable, boolean emulated, long mtpReserveSize, boolean allowMassStorage,
+            long maxFileSize, UserHandle owner, String fsUuid, String state) {
+        mId = Preconditions.checkNotNull(id);
+        mStorageId = storageId;
+        mPath = Preconditions.checkNotNull(path);
+        mDescription = Preconditions.checkNotNull(description);
         mPrimary = primary;
         mRemovable = removable;
         mEmulated = emulated;
-        mMtpReserveSpace = mtpReserveSpace;
+        mMtpReserveSize = mtpReserveSize;
         mAllowMassStorage = allowMassStorage;
         mMaxFileSize = maxFileSize;
-        mOwner = owner;
+        mOwner = Preconditions.checkNotNull(owner);
+        mFsUuid = fsUuid;
+        mState = Preconditions.checkNotNull(state);
     }
 
     private StorageVolume(Parcel in) {
+        mId = in.readString();
         mStorageId = in.readInt();
         mPath = new File(in.readString());
-        mDescriptionId = in.readInt();
+        mDescription = in.readString();
         mPrimary = in.readInt() != 0;
         mRemovable = in.readInt() != 0;
         mEmulated = in.readInt() != 0;
-        mMtpReserveSpace = in.readInt();
+        mMtpReserveSize = in.readLong();
         mAllowMassStorage = in.readInt() != 0;
         mMaxFileSize = in.readLong();
         mOwner = in.readParcelable(null);
-        mUuid = in.readString();
-        mUserLabel = in.readString();
+        mFsUuid = in.readString();
         mState = in.readString();
     }
 
-    public static StorageVolume fromTemplate(StorageVolume template, File path, UserHandle owner) {
-        return new StorageVolume(path, template.mDescriptionId, template.mPrimary,
-                template.mRemovable, template.mEmulated, template.mMtpReserveSpace,
-                template.mAllowMassStorage, template.mMaxFileSize, owner);
+    public String getId() {
+        return mId;
     }
 
     /**
@@ -113,11 +115,7 @@
      * @return the volume description
      */
     public String getDescription(Context context) {
-        return context.getResources().getString(mDescriptionId);
-    }
-
-    public int getDescriptionId() {
-        return mDescriptionId;
+        return mDescription;
     }
 
     public boolean isPrimary() {
@@ -153,15 +151,6 @@
     }
 
     /**
-     * Do not call this unless you are MountService
-     */
-    public void setStorageId(int index) {
-        // storage ID is 0x00010001 for primary storage,
-        // then 0x00020001, 0x00030001, etc. for secondary storages
-        mStorageId = ((index + 1) << 16) + 1;
-    }
-
-    /**
      * Number of megabytes of space to leave unallocated by MTP.
      * MTP will subtract this value from the free space it reports back
      * to the host via GetStorageInfo, and will not allow new files to
@@ -174,7 +163,7 @@
      * @return MTP reserve space
      */
     public int getMtpReserveSpace() {
-        return mMtpReserveSpace;
+        return (int) (mMtpReserveSize / TrafficStats.MB_IN_BYTES);
     }
 
     /**
@@ -199,12 +188,8 @@
         return mOwner;
     }
 
-    public void setUuid(String uuid) {
-        mUuid = uuid;
-    }
-
     public String getUuid() {
-        return mUuid;
+        return mFsUuid;
     }
 
     /**
@@ -212,26 +197,18 @@
      * parse or UUID is unknown.
      */
     public int getFatVolumeId() {
-        if (mUuid == null || mUuid.length() != 9) {
+        if (mFsUuid == null || mFsUuid.length() != 9) {
             return -1;
         }
         try {
-            return (int)Long.parseLong(mUuid.replace("-", ""), 16);
+            return (int) Long.parseLong(mFsUuid.replace("-", ""), 16);
         } catch (NumberFormatException e) {
             return -1;
         }
     }
 
-    public void setUserLabel(String userLabel) {
-        mUserLabel = userLabel;
-    }
-
     public String getUserLabel() {
-        return mUserLabel;
-    }
-
-    public void setState(String state) {
-        mState = state;
+        return mDescription;
     }
 
     public String getState() {
@@ -262,18 +239,18 @@
     public void dump(IndentingPrintWriter pw) {
         pw.println("StorageVolume:");
         pw.increaseIndent();
+        pw.printPair("mId", mId);
         pw.printPair("mStorageId", mStorageId);
         pw.printPair("mPath", mPath);
-        pw.printPair("mDescriptionId", mDescriptionId);
+        pw.printPair("mDescription", mDescription);
         pw.printPair("mPrimary", mPrimary);
         pw.printPair("mRemovable", mRemovable);
         pw.printPair("mEmulated", mEmulated);
-        pw.printPair("mMtpReserveSpace", mMtpReserveSpace);
+        pw.printPair("mMtpReserveSize", mMtpReserveSize);
         pw.printPair("mAllowMassStorage", mAllowMassStorage);
         pw.printPair("mMaxFileSize", mMaxFileSize);
         pw.printPair("mOwner", mOwner);
-        pw.printPair("mUuid", mUuid);
-        pw.printPair("mUserLabel", mUserLabel);
+        pw.printPair("mFsUuid", mFsUuid);
         pw.printPair("mState", mState);
         pw.decreaseIndent();
     }
@@ -297,18 +274,18 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mId);
         parcel.writeInt(mStorageId);
         parcel.writeString(mPath.toString());
-        parcel.writeInt(mDescriptionId);
+        parcel.writeString(mDescription);
         parcel.writeInt(mPrimary ? 1 : 0);
         parcel.writeInt(mRemovable ? 1 : 0);
         parcel.writeInt(mEmulated ? 1 : 0);
-        parcel.writeInt(mMtpReserveSpace);
+        parcel.writeLong(mMtpReserveSize);
         parcel.writeInt(mAllowMassStorage ? 1 : 0);
         parcel.writeLong(mMaxFileSize);
         parcel.writeParcelable(mOwner, flags);
-        parcel.writeString(mUuid);
-        parcel.writeString(mUserLabel);
+        parcel.writeString(mFsUuid);
         parcel.writeString(mState);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/core/java/android/os/storage/VolumeInfo.aidl
similarity index 75%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to core/java/android/os/storage/VolumeInfo.aidl
index 272c321..32d12da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/core/java/android/os/storage/VolumeInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+package android.os.storage;
 
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
-}
+parcelable VolumeInfo;
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
new file mode 100644
index 0000000..2dc0361
--- /dev/null
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -0,0 +1,296 @@
+/*
+ * 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.os.storage;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+import android.mtp.MtpStorage;
+import android.os.Environment;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.DebugUtils;
+import android.util.SparseArray;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
+
+import java.io.CharArrayWriter;
+import java.io.File;
+
+/**
+ * Information about a storage volume that may be mounted. A volume may be a
+ * partition on a physical {@link DiskInfo}, an emulated volume above some other
+ * storage medium, or a standalone container like an ASEC or OBB.
+ *
+ * @hide
+ */
+public class VolumeInfo implements Parcelable {
+    /** Real volume representing internal emulated storage */
+    public static final String ID_EMULATED_INTERNAL = "emulated";
+
+    public static final int TYPE_PUBLIC = 0;
+    public static final int TYPE_PRIVATE = 1;
+    public static final int TYPE_EMULATED = 2;
+    public static final int TYPE_ASEC = 3;
+    public static final int TYPE_OBB = 4;
+
+    public static final int STATE_UNMOUNTED = 0;
+    public static final int STATE_MOUNTING = 1;
+    public static final int STATE_MOUNTED = 2;
+    public static final int STATE_FORMATTING = 3;
+    public static final int STATE_UNMOUNTING = 4;
+    public static final int STATE_UNMOUNTABLE = 5;
+
+    public static final int FLAG_PRIMARY = 1 << 0;
+    public static final int FLAG_VISIBLE = 1 << 1;
+
+    private static SparseArray<String> sStateToEnvironment = new SparseArray<>();
+    private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>();
+
+    static {
+        sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTED, Environment.MEDIA_UNMOUNTED);
+        sStateToEnvironment.put(VolumeInfo.STATE_MOUNTING, Environment.MEDIA_CHECKING);
+        sStateToEnvironment.put(VolumeInfo.STATE_MOUNTED, Environment.MEDIA_MOUNTED);
+        sStateToEnvironment.put(VolumeInfo.STATE_FORMATTING, Environment.MEDIA_UNMOUNTED);
+        sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTING, Environment.MEDIA_EJECTING);
+        sStateToEnvironment.put(VolumeInfo.STATE_UNMOUNTABLE, Environment.MEDIA_UNMOUNTABLE);
+
+        sEnvironmentToBroadcast.put(Environment.MEDIA_UNMOUNTED, Intent.ACTION_MEDIA_UNMOUNTED);
+        sEnvironmentToBroadcast.put(Environment.MEDIA_CHECKING, Intent.ACTION_MEDIA_CHECKING);
+        sEnvironmentToBroadcast.put(Environment.MEDIA_MOUNTED, Intent.ACTION_MEDIA_MOUNTED);
+        sEnvironmentToBroadcast.put(Environment.MEDIA_EJECTING, Intent.ACTION_MEDIA_EJECT);
+        sEnvironmentToBroadcast.put(Environment.MEDIA_UNMOUNTABLE, Intent.ACTION_MEDIA_UNMOUNTABLE);
+    }
+
+    /** vold state */
+    public final String id;
+    public final int type;
+    public int flags = 0;
+    public int userId = -1;
+    public int state = STATE_UNMOUNTED;
+    public String fsType;
+    public String fsUuid;
+    public String fsLabel;
+    public String path;
+
+    /** Framework state */
+    public final int mtpIndex;
+    public String nickname;
+
+    public DiskInfo disk;
+
+    public VolumeInfo(String id, int type, int mtpIndex) {
+        this.id = Preconditions.checkNotNull(id);
+        this.type = type;
+        this.mtpIndex = mtpIndex;
+    }
+
+    public VolumeInfo(Parcel parcel) {
+        id = parcel.readString();
+        type = parcel.readInt();
+        flags = parcel.readInt();
+        userId = parcel.readInt();
+        state = parcel.readInt();
+        fsType = parcel.readString();
+        fsUuid = parcel.readString();
+        fsLabel = parcel.readString();
+        path = parcel.readString();
+        mtpIndex = parcel.readInt();
+        nickname = parcel.readString();
+    }
+
+    public static @NonNull String getEnvironmentForState(int state) {
+        final String envState = sStateToEnvironment.get(state);
+        if (envState != null) {
+            return envState;
+        } else {
+            return Environment.MEDIA_UNKNOWN;
+        }
+    }
+
+    public static @Nullable String getBroadcastForEnvironment(String envState) {
+        return sEnvironmentToBroadcast.get(envState);
+    }
+
+    public static @Nullable String getBroadcastForState(int state) {
+        return getBroadcastForEnvironment(getEnvironmentForState(state));
+    }
+
+    public String getDescription(Context context) {
+        if (ID_EMULATED_INTERNAL.equals(id)) {
+            return context.getString(com.android.internal.R.string.storage_internal);
+        } else if (!TextUtils.isEmpty(nickname)) {
+            return nickname;
+        } else if (!TextUtils.isEmpty(fsLabel)) {
+            return fsLabel;
+        } else {
+            return null;
+        }
+    }
+
+    public boolean isPrimary() {
+        return (flags & FLAG_PRIMARY) != 0;
+    }
+
+    public boolean isVisible() {
+        return (flags & FLAG_VISIBLE) != 0;
+    }
+
+    public boolean isVisibleToUser(int userId) {
+        if (type == TYPE_PUBLIC && userId == this.userId) {
+            return isVisible();
+        } else if (type == TYPE_EMULATED) {
+            return isVisible();
+        } else {
+            return false;
+        }
+    }
+
+    public File getPathForUser(int userId) {
+        if (path == null) {
+            return null;
+        } else if (type == TYPE_PUBLIC && userId == this.userId) {
+            return new File(path);
+        } else if (type == TYPE_EMULATED) {
+            return new File(path, Integer.toString(userId));
+        } else {
+            return null;
+        }
+    }
+
+    public StorageVolume buildStorageVolume(Context context, int userId) {
+        final boolean removable;
+        final boolean emulated;
+        final boolean allowMassStorage = false;
+        final int mtpStorageId = MtpStorage.getStorageIdForIndex(mtpIndex);
+        final String envState = getEnvironmentForState(state);
+
+        File userPath = getPathForUser(userId);
+        if (userPath == null) {
+            userPath = new File("/dev/null");
+        }
+
+        String description = getDescription(context);
+        if (description == null) {
+            description = context.getString(android.R.string.unknownName);
+        }
+
+        long mtpReserveSize = 0;
+        long maxFileSize = 0;
+
+        if (type == TYPE_EMULATED) {
+            emulated = true;
+            mtpReserveSize = StorageManager.from(context).getStorageLowBytes(userPath);
+
+            if (ID_EMULATED_INTERNAL.equals(id)) {
+                removable = false;
+            } else {
+                removable = true;
+            }
+
+        } else if (type == TYPE_PUBLIC) {
+            emulated = false;
+            removable = true;
+
+            if ("vfat".equals(fsType)) {
+                maxFileSize = 4294967295L;
+            }
+
+        } else {
+            throw new IllegalStateException("Unexpected volume type " + type);
+        }
+
+        return new StorageVolume(id, mtpStorageId, userPath, description, isPrimary(), removable,
+                emulated, mtpReserveSize, allowMassStorage, maxFileSize, new UserHandle(userId),
+                fsUuid, envState);
+    }
+
+    @Override
+    public String toString() {
+        final CharArrayWriter writer = new CharArrayWriter();
+        dump(new IndentingPrintWriter(writer, "    ", 80));
+        return writer.toString();
+    }
+
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("VolumeInfo:");
+        pw.increaseIndent();
+        pw.printPair("id", id);
+        pw.printPair("type", DebugUtils.valueToString(getClass(), "TYPE_", type));
+        pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags));
+        pw.printPair("userId", userId);
+        pw.printPair("state", DebugUtils.valueToString(getClass(), "STATE_", state));
+        pw.println();
+        pw.printPair("fsType", fsType);
+        pw.printPair("fsUuid", fsUuid);
+        pw.printPair("fsLabel", fsLabel);
+        pw.println();
+        pw.printPair("path", path);
+        pw.printPair("mtpIndex", mtpIndex);
+        pw.decreaseIndent();
+        pw.println();
+    }
+
+    @Override
+    public VolumeInfo clone() {
+        final Parcel temp = Parcel.obtain();
+        try {
+            writeToParcel(temp, 0);
+            temp.setDataPosition(0);
+            return CREATOR.createFromParcel(temp);
+        } finally {
+            temp.recycle();
+        }
+    }
+
+    public static final Creator<VolumeInfo> CREATOR = new Creator<VolumeInfo>() {
+        @Override
+        public VolumeInfo createFromParcel(Parcel in) {
+            return new VolumeInfo(in);
+        }
+
+        @Override
+        public VolumeInfo[] newArray(int size) {
+            return new VolumeInfo[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(id);
+        parcel.writeInt(type);
+        parcel.writeInt(flags);
+        parcel.writeInt(userId);
+        parcel.writeInt(state);
+        parcel.writeString(fsType);
+        parcel.writeString(fsUuid);
+        parcel.writeString(fsLabel);
+        parcel.writeString(path);
+        parcel.writeInt(mtpIndex);
+        parcel.writeString(nickname);
+    }
+}
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index ccf2cfa..3b482eb 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -706,8 +706,10 @@
      * @param iconResId The icon as a resource ID.
      */
     public void setIcon(@DrawableRes int iconResId) {
-        mIconResId = iconResId;
-        setIcon(mContext.getDrawable(iconResId));
+        if (mIconResId != iconResId) {
+            mIconResId = iconResId;
+            setIcon(mContext.getDrawable(iconResId));
+        }
     }
 
     /**
@@ -1436,7 +1438,7 @@
     protected boolean persistString(String value) {
         if (shouldPersist()) {
             // Shouldn't store null
-            if (value == getPersistedString(null)) {
+            if (TextUtils.equals(value, getPersistedString(null))) {
                 // It's already there, so the same as persisting
                 return true;
             }
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index 724d76d..25a35e1 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -43,8 +43,14 @@
      * should remove this alarm after it has been dismissed. If an identical alarm exists matching
      * all parameters, the implementation may re-use it instead of creating a new one (in this case,
      * the alarm should not be removed after dismissal).
-     *
+     * </p><p>
      * This action always enables the alarm.
+     * </p><p>
+     * This activity could also be started in Voice Interaction mode. The activity should check
+     * {@link android.app.Activity#isVoiceInteraction}, and if true, the implementation should
+     * report a deeplink of the created/enabled alarm using
+     * {@link android.app.VoiceInteractor.CompleteVoiceRequest}. This allows follow-on voice actions
+     * such as {@link #ACTION_VOICE_CANCEL_ALARM} to cancel the alarm that was just enabled.
      * </p>
      * <h3>Request parameters</h3>
      * <ul>
@@ -63,6 +69,48 @@
     public static final String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
 
     /**
+     * Voice Activity Action: Cancel an alarm.
+     * Requires: The activity must check {@link android.app.Activity#isVoiceInteraction}, i.e. be
+     * started in Voice Interaction mode.
+     * <p>
+     * Cancels the specified alarm by voice. To cancel means to disable, but not delete, the alarm.
+     * See {@link #ACTION_VOICE_DELETE_ALARM} to delete an alarm by voice.
+     * </p><p>
+     * The alarm to cancel can be specified or searched for in one of the following ways:
+     * <ol>
+     * <li>The Intent's data URI specifies a deeplink to the alarm.
+     * <li>If the Intent's data URI is unspecified, then the extra {@link #EXTRA_ALARM_SEARCH_MODE} is
+     * required to determine how to search for the alarm.
+     *
+     * @see #ACTION_VOICE_DELETE_ALARM
+     * @see #EXTRA_ALARM_SEARCH_MODE
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_VOICE_CANCEL_ALARM =
+            "android.intent.action.VOICE_CANCEL_ALARM";
+
+    /**
+     * Voice Activity Action: Delete an alarm.
+     * Requires: The activity must check {@link android.app.Activity#isVoiceInteraction}, i.e. be
+     * started in Voice Interaction mode.
+     * <p>
+     * Deletes the specified alarm by voice.
+     * See {@link #ACTION_VOICE_CANCEL_ALARM} to cancel (disable) an alarm by voice.
+     * </p><p>
+     * The alarm to delete can be specified or searched for in one of the following ways:
+     * <ol>
+     * <li>The Intent's data URI specifies a deeplink to the alarm.
+     * <li>If the Intent's data URI is unspecified, then the extra {@link #EXTRA_ALARM_SEARCH_MODE} is
+     * required to determine how to search for the alarm.
+     *
+     * @see #ACTION_VOICE_CANCEL_ALARM
+     * @see #EXTRA_ALARM_SEARCH_MODE
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_VOICE_DELETE_ALARM =
+            "android.intent.action.VOICE_DELETE_ALARM";
+
+    /**
      * Activity Action: Set a timer.
      * <p>
      * Activates an existing timer or creates a new one.
@@ -99,6 +147,100 @@
      public static final String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
 
     /**
+     * Bundle extra: Specify the type of search mode to look up an alarm.
+     * <p>
+     * Used by {@link #ACTION_VOICE_CANCEL_ALARM} and {@link #ACTION_VOICE_DELETE_ALARM} to identify
+     * the alarm(s) to cancel or delete, respectively.
+     * </p><p>
+     * This extra is only required when the alarm is not already identified by a deeplink as
+     * specified in the Intent's data URI.
+     * </p><p>
+     * The value of this extra is a {@link String}, restricted to the following set of supported
+     * search modes:
+     * <ul>
+     * <li><i>Time</i> - {@link #ALARM_SEARCH_MODE_TIME}: Selects the alarm that is most
+     * closely matched by the search parameters {@link #EXTRA_HOUR}, {@link #EXTRA_MINUTES},
+     * {@link #EXTRA_IS_PM}.
+     * <li><i>Next alarm</i> - {@link #ALARM_SEARCH_MODE_NEXT}: Selects the alarm that will
+     * ring next, or the alarm that is currently ringing, if any.
+     * <li><i>All alarms</i> - {@link #ALARM_SEARCH_MODE_ALL}: Selects all alarms.
+     * <li><i>None</i> - {@link #ALARM_SEARCH_MODE_NONE}: No search mode specified. The
+     * implementation should ask the user to select a search mode using
+     * {@link android.app.VoiceInteractor.PickOptionRequest} and proceed with a voice flow to
+     * identify the alarm.
+     * </ul>
+     * </ol>
+     *
+     * @see #ALARM_SEARCH_MODE_TIME
+     * @see #ALARM_SEARCH_MODE_NEXT
+     * @see #ALARM_SEARCH_MODE_ALL
+     * @see #ALARM_SEARCH_MODE_NONE
+     * @see #ACTION_VOICE_CANCEL_ALARM
+     * @see #ACTION_VOICE_DELETE_ALARM
+     */
+    public static final String EXTRA_ALARM_SEARCH_MODE =
+        "android.intent.extra.alarm.ALARM_SEARCH_MODE";
+
+    /**
+     * Search for the alarm that is most closely matched by the search parameters
+     * {@link #EXTRA_HOUR}, {@link #EXTRA_MINUTES}, {@link #EXTRA_IS_PM}.
+     * In this search mode, at least one of these additional extras are required.
+     * <ul>
+     * <li>{@link #EXTRA_HOUR} - The hour to search for the alarm.
+     * <li>{@link #EXTRA_MINUTES} - The minute to search for the alarm.
+     * <li>{@link #EXTRA_IS_PM} - Whether the hour is AM or PM.
+     * </ul>
+     *
+     * @see #EXTRA_ALARM_SEARCH_MODE
+     */
+    public static final String ALARM_SEARCH_MODE_TIME = "time";
+
+    /**
+     * Selects the alarm that will ring next, or the alarm that is currently ringing, if any.
+     *
+     * @see #EXTRA_ALARM_SEARCH_MODE
+     */
+    public static final String ALARM_SEARCH_MODE_NEXT = "next";
+
+    /**
+     * Selects all alarms.
+     *
+     * @see #EXTRA_ALARM_SEARCH_MODE
+     */
+    public static final String ALARM_SEARCH_MODE_ALL = "all";
+
+    /**
+     * No search mode specified. The implementation should ask the user to select a search mode
+     * using {@link android.app.VoiceInteractor.PickOptionRequest} and proceed with a voice flow to
+     * identify the alarm.
+     *
+     * @see #EXTRA_ALARM_SEARCH_MODE
+     */
+    public static final String ALARM_SEARCH_MODE_NONE = "none";
+
+    /**
+     * Bundle extra: The AM/PM of the alarm.
+     * <p>
+     * Used by {@link #ACTION_VOICE_CANCEL_ALARM} and {@link #ACTION_VOICE_DELETE_ALARM}.
+     * </p><p>
+     * This extra is optional and only used when {@link #EXTRA_ALARM_SEARCH_MODE} is set to
+     * {@link #ALARM_SEARCH_MODE_TIME}. In this search mode, the {@link #EXTRA_IS_PM} is
+     * used together with {@link #EXTRA_HOUR} and {@link #EXTRA_MINUTES}. The implementation should
+     * look up the alarm that is most closely matched by these search parameters.
+     * If {@link #EXTRA_IS_PM} is missing, then the AM/PM of the specified {@link #EXTRA_HOUR} is
+     * ambiguous and the implementation should ask for clarification from the user.
+     * </p><p>
+     * The value is a {@link Boolean}, where false=AM and true=PM.
+     * </p>
+     *
+     * @see #ACTION_VOICE_CANCEL_ALARM
+     * @see #ACTION_VOICE_DELETE_ALARM
+     * @see #EXTRA_HOUR
+     * @see #EXTRA_MINUTES
+     */
+    public static final String EXTRA_IS_PM = "android.intent.extra.alarm.IS_PM";
+
+    /**
      * Bundle extra: Weekdays for repeating alarm.
      * <p>
      * Used by {@link #ACTION_SET_ALARM}.
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 6517f35..7d57233 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -454,7 +454,6 @@
                 long start, int duration, Long dataUsage, boolean addForAllUsers) {
             final ContentResolver resolver = context.getContentResolver();
             int numberPresentation = PRESENTATION_ALLOWED;
-            boolean isHidden = false;
 
             TelecomManager tm = null;
             try {
@@ -469,12 +468,6 @@
                     if (address != null) {
                         accountAddress = address.getSchemeSpecificPart();
                     }
-                } else {
-                    // We could not find the account through telecom. For call log entries that
-                    // are added with a phone account which is not registered, we automatically
-                    // mark them as hidden. They are unhidden once the account is registered.
-                    Log.i(LOG_TAG, "Marking call log entry as hidden.");
-                    isHidden = true;
                 }
             }
 
@@ -520,7 +513,6 @@
             values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString);
             values.put(PHONE_ACCOUNT_ID, accountId);
             values.put(PHONE_ACCOUNT_ADDRESS, accountAddress);
-            values.put(PHONE_ACCOUNT_HIDDEN, Integer.valueOf(isHidden ? 1 : 0));
             values.put(NEW, Integer.valueOf(1));
 
             if (callType == MISSED_TYPE) {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 74b0a1c..bf7f3cb 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -18,6 +18,7 @@
 
 import android.accounts.Account;
 import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
 import android.content.ActivityNotFoundException;
 import android.content.ContentProviderClient;
 import android.content.ContentProviderOperation;
@@ -1628,7 +1629,6 @@
          */
         public static final String CONTENT_VCARD_TYPE = "text/x-vcard";
 
-
         /**
          * Mimimal ID for corp contacts returned from
          * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
@@ -1638,6 +1638,14 @@
         public static long ENTERPRISE_CONTACT_ID_BASE = 1000000000; // slightly smaller than 2 ** 30
 
         /**
+         * Prefix for corp contacts returned from
+         * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
+         *
+         * @hide
+         */
+        public static String ENTERPRISE_CONTACT_LOOKUP_PREFIX = "c-";
+
+        /**
          * Return TRUE if a contact ID is from the contacts provider on the enterprise profile.
          *
          * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI} may return such a contact.
@@ -4809,6 +4817,14 @@
                 Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities");
 
         /**
+        * The content:// style URI for this table in corp profile
+        *
+        * @hide
+        */
+        public static final Uri CORP_CONTENT_URI =
+                Uri.withAppendedPath(AUTHORITY_URI, "raw_contact_entities_corp");
+
+        /**
          * The content:// style URI for this table, specific to the user's profile.
          */
         public static final Uri PROFILE_CONTENT_URI =
@@ -5024,9 +5040,17 @@
          *     is from the corp profile, use
          *     {@link ContactsContract.Contacts#isEnterpriseContactId(long)}.
          *     </li>
+         *     <li>
+         *     Corp contacts will get artificial {@link #LOOKUP_KEY}s too.
+         *     </li>
          * </ul>
          * <p>
-         * This URI does NOT support selection nor order-by.
+         * A contact lookup URL built by
+         * {@link ContactsContract.Contacts#getLookupUri(long, String)}
+         * with an {@link #_ID} and a {@link #LOOKUP_KEY} returned by this API can be passed to
+         * {@link ContactsContract.QuickContact#showQuickContact} even if a contact is from the
+         * corp profile.
+         * </p>
          *
          * <pre>
          * Uri lookupUri = Uri.withAppendedPath(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI,
@@ -6017,10 +6041,18 @@
             *     a contact
             *     is from the corp profile, use
             *     {@link ContactsContract.Contacts#isEnterpriseContactId(long)}.
-            *     </li>
-            * </ul>
-            * <p>
-            * This URI does NOT support selection nor order-by.
+             *     </li>
+             *     <li>
+             *     Corp contacts will get artificial {@link #LOOKUP_KEY}s too.
+             *     </li>
+             * </ul>
+             * <p>
+             * A contact lookup URL built by
+             * {@link ContactsContract.Contacts#getLookupUri(long, String)}
+             * with an {@link #_ID} and a {@link #LOOKUP_KEY} returned by this API can be passed to
+             * {@link ContactsContract.QuickContact#showQuickContact} even if a contact is from the
+             * corp profile.
+             * </p>
             *
             * <pre>
             * Uri lookupUri = Uri.withAppendedPath(Email.ENTERPRISE_CONTENT_LOOKUP_URI,
@@ -8174,6 +8206,9 @@
          */
         public static final int MODE_LARGE = 3;
 
+        /** @hide */
+        public static final int MODE_DEFAULT = MODE_LARGE;
+
         /**
          * Constructs the QuickContacts intent with a view's rect.
          * @hide
@@ -8216,6 +8251,7 @@
             // Launch pivot dialog through intent for now
             final Intent intent = new Intent(ACTION_QUICK_CONTACT).addFlags(intentFlags);
 
+            // NOTE: This logic and rebuildManagedQuickContactsIntent() must be in sync.
             intent.setData(lookupUri);
             intent.setSourceBounds(target);
             intent.putExtra(EXTRA_MODE, mode);
@@ -8224,6 +8260,30 @@
         }
 
         /**
+         * Constructs a QuickContacts intent based on an incoming intent for DevicePolicyManager
+         * to strip off anything not necessary.
+         * 
+         * @hide
+         */
+        public static Intent rebuildManagedQuickContactsIntent(String lookupKey, long contactId,
+                Intent originalIntent) {
+            final Intent intent = new Intent(ACTION_QUICK_CONTACT);
+            // Rebuild the URI from a lookup key and a contact ID.
+            intent.setData(Contacts.getLookupUri(contactId, lookupKey));
+
+            // Copy flags and always set NEW_TASK because it won't have a parent activity.
+            intent.setFlags(originalIntent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            // Copy extras.
+            intent.setSourceBounds(originalIntent.getSourceBounds());
+            intent.putExtra(EXTRA_MODE, originalIntent.getIntExtra(EXTRA_MODE, MODE_DEFAULT));
+            intent.putExtra(EXTRA_EXCLUDE_MIMES,
+                    originalIntent.getStringArrayExtra(EXTRA_EXCLUDE_MIMES));
+            return intent;
+        }
+
+
+        /**
          * Trigger a dialog that lists the various methods of interacting with
          * the requested {@link Contacts} entry. This may be based on available
          * {@link ContactsContract.Data} rows under that contact, and may also
@@ -8251,7 +8311,7 @@
             // Trigger with obtained rectangle
             Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
                     excludeMimes);
-            startActivityWithErrorToast(context, intent);
+            ContactsInternal.startQuickContactWithErrorToast(context, intent);
         }
 
         /**
@@ -8284,7 +8344,7 @@
                 String[] excludeMimes) {
             Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
                     excludeMimes);
-            startActivityWithErrorToast(context, intent);
+            ContactsInternal.startQuickContactWithErrorToast(context, intent);
         }
 
         /**
@@ -8317,10 +8377,10 @@
             // Use MODE_LARGE instead of accepting mode as a parameter. The different mode
             // values defined in ContactsContract only affect very old implementations
             // of QuickContacts.
-            Intent intent = composeQuickContactsIntent(context, target, lookupUri, MODE_LARGE,
+            Intent intent = composeQuickContactsIntent(context, target, lookupUri, MODE_DEFAULT,
                     excludeMimes);
             intent.putExtra(EXTRA_PRIORITIZED_MIMETYPE, prioritizedMimeType);
-            startActivityWithErrorToast(context, intent);
+            ContactsInternal.startQuickContactWithErrorToast(context, intent);
         }
 
         /**
@@ -8355,19 +8415,10 @@
             // Use MODE_LARGE instead of accepting mode as a parameter. The different mode
             // values defined in ContactsContract only affect very old implementations
             // of QuickContacts.
-            Intent intent = composeQuickContactsIntent(context, target, lookupUri, MODE_LARGE,
+            Intent intent = composeQuickContactsIntent(context, target, lookupUri, MODE_DEFAULT,
                     excludeMimes);
             intent.putExtra(EXTRA_PRIORITIZED_MIMETYPE, prioritizedMimeType);
-            startActivityWithErrorToast(context, intent);
-        }
-
-        private static void startActivityWithErrorToast(Context context, Intent intent) {
-            try {
-              context.startActivity(intent);
-            } catch (ActivityNotFoundException e) {
-                Toast.makeText(context, com.android.internal.R.string.quick_contacts_not_available,
-                                Toast.LENGTH_SHORT).show();
-            }
+            ContactsInternal.startQuickContactWithErrorToast(context, intent);
         }
     }
 
diff --git a/core/java/android/provider/ContactsInternal.java b/core/java/android/provider/ContactsInternal.java
new file mode 100644
index 0000000..059a603
--- /dev/null
+++ b/core/java/android/provider/ContactsInternal.java
@@ -0,0 +1,112 @@
+/*
+ * 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.provider;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ActivityNotFoundException;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.Intent;
+import android.content.UriMatcher;
+import android.net.Uri;
+import android.os.Process;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.widget.Toast;
+
+import java.util.List;
+
+/**
+ * Contacts related internal methods.
+ *
+ * @hide
+ */
+public class ContactsInternal {
+    private ContactsInternal() {
+    }
+
+    /** URI matcher used to parse contact URIs. */
+    private static final UriMatcher sContactsUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+    private static final int CONTACTS_URI_LOOKUP_ID = 1000;
+
+    static {
+        // Contacts URI matching table
+        final UriMatcher matcher = sContactsUriMatcher;
+        matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_URI_LOOKUP_ID);
+    }
+
+    /**
+     * Called by {@link ContactsContract} to star Quick Contact, possibly on the managed profile.
+     */
+    public static void startQuickContactWithErrorToast(Context context, Intent intent) {
+        final Uri uri = intent.getData();
+
+        final int match = sContactsUriMatcher.match(uri);
+        switch (match) {
+            case CONTACTS_URI_LOOKUP_ID: {
+                if (maybeStartManagedQuickContact(context, intent)) {
+                    return; // Request handled by DPM.  Just return here.
+                }
+                break;
+            }
+        }
+        // Launch on the current profile.
+        startQuickContactWithErrorToastForUser(context, intent, Process.myUserHandle());
+    }
+
+    public static void startQuickContactWithErrorToastForUser(Context context, Intent intent,
+            UserHandle user) {
+        try {
+            context.startActivityAsUser(intent, user);
+        } catch (ActivityNotFoundException e) {
+            Toast.makeText(context, com.android.internal.R.string.quick_contacts_not_available,
+                    Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    /**
+     * If the URI in {@code intent} is of a corp contact, launch quick contact on the managed
+     * profile.
+     *
+     * @return the URI in {@code intent} is of a corp contact thus launched on the managed profile.
+     */
+    private static boolean maybeStartManagedQuickContact(Context context, Intent originalIntent) {
+        final Uri uri = originalIntent.getData();
+
+        // Decompose into an ID and a lookup key.
+        final List<String> pathSegments = uri.getPathSegments();
+        final long contactId = ContentUris.parseId(uri);
+        final String lookupKey = pathSegments.get(2);
+
+        // See if it has a corp lookupkey.
+        if (TextUtils.isEmpty(lookupKey)
+                || !lookupKey.startsWith(
+                        ContactsContract.Contacts.ENTERPRISE_CONTACT_LOOKUP_PREFIX)) {
+            return false; // It's not a corp lookup key.
+        }
+
+        // Launch Quick Contact on the managed profile, if the policy allows.
+        final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+        final String actualLookupKey = lookupKey.substring(
+                ContactsContract.Contacts.ENTERPRISE_CONTACT_LOOKUP_PREFIX.length());
+        final long actualContactId =
+                (contactId - ContactsContract.Contacts.ENTERPRISE_CONTACT_ID_BASE);
+
+        dpm.startManagedQuickContact(actualLookupKey, actualContactId, originalIntent);
+        return true;
+    }
+}
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 5afbd6d..7565654b 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -226,6 +226,35 @@
     public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
 
     /**
+     * The name of the Intent action used to indicate that a camera launch might be imminent. This
+     * broadcast should be targeted to the package that is receiving
+     * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or
+     * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE}, depending on the context. If such
+     * intent would launch the resolver activity, this broadcast should not be sent at all.
+     * <p>
+     * A receiver of this broadcast should do the absolute minimum amount of work to initialize the
+     * camera in order to reduce startup time in likely case that shortly after an actual camera
+     * launch intent would be sent.
+     * <p>
+     * In case the actual intent will not be fired, the target package will receive
+     * {@link #ACTION_STILL_IMAGE_CAMERA_COOLDOWN}. However, it is recommended that the receiver
+     * also implements a timeout to close the camera after receiving this intent, as there is no
+     * guarantee that {@link #ACTION_STILL_IMAGE_CAMERA_COOLDOWN} will be delivered.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM";
+
+    /**
+     * The name of the Intent action used to indicate that an imminent camera launch has been
+     * cancelled by the user. This broadcast should be targeted to the package that has received
+     * {@link #ACTION_STILL_IMAGE_CAMERA_PREWARM}.
+     * <p>
+     * A receiver of this broadcast should close the camera immediately.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN";
+
+    /**
      * The name of the Intent action used to launch a camera in still image mode
      * for use when the device is secured (e.g. with a pin, password, pattern,
      * or face unlock). Applications responding to this intent must not expose
diff --git a/core/java/android/provider/SearchIndexableData.java b/core/java/android/provider/SearchIndexableData.java
index 7b9d1ea..5e0a76d 100644
--- a/core/java/android/provider/SearchIndexableData.java
+++ b/core/java/android/provider/SearchIndexableData.java
@@ -16,6 +16,7 @@
 
 package android.provider;
 
+import android.annotation.SystemApi;
 import android.content.Context;
 
 import java.util.Locale;
@@ -27,6 +28,7 @@
  *
  * @hide
  */
+@SystemApi
 public abstract class SearchIndexableData {
 
     /**
diff --git a/core/java/android/provider/SearchIndexableResource.java b/core/java/android/provider/SearchIndexableResource.java
index c807df2..1eb1734 100644
--- a/core/java/android/provider/SearchIndexableResource.java
+++ b/core/java/android/provider/SearchIndexableResource.java
@@ -16,6 +16,7 @@
 
 package android.provider;
 
+import android.annotation.SystemApi;
 import android.content.Context;
 
 /**
@@ -31,6 +32,7 @@
  *
  * @hide
  */
+@SystemApi
 public class SearchIndexableResource extends SearchIndexableData {
 
     /**
diff --git a/core/java/android/provider/SearchIndexablesContract.java b/core/java/android/provider/SearchIndexablesContract.java
index 1b5f72a..93ac7f6 100644
--- a/core/java/android/provider/SearchIndexablesContract.java
+++ b/core/java/android/provider/SearchIndexablesContract.java
@@ -16,6 +16,7 @@
 
 package android.provider;
 
+import android.annotation.SystemApi;
 import android.content.ContentResolver;
 
 /**
@@ -23,6 +24,7 @@
  *
  * @hide
  */
+@SystemApi
 public class SearchIndexablesContract {
 
     /**
@@ -234,7 +236,7 @@
     /**
      * The base columns.
      */
-    private static class BaseColumns {
+    public static class BaseColumns {
         private BaseColumns() {
         }
 
diff --git a/core/java/android/provider/SearchIndexablesProvider.java b/core/java/android/provider/SearchIndexablesProvider.java
index 9c8f6d0..3120e54 100644
--- a/core/java/android/provider/SearchIndexablesProvider.java
+++ b/core/java/android/provider/SearchIndexablesProvider.java
@@ -16,6 +16,7 @@
 
 package android.provider;
 
+import android.annotation.SystemApi;
 import android.content.ContentProvider;
 import android.content.ContentValues;
 import android.content.Context;
@@ -61,6 +62,7 @@
  *
  * @hide
  */
+@SystemApi
 public abstract class SearchIndexablesProvider extends ContentProvider {
     private static final String TAG = "IndexablesProvider";
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index de536bd..5ee8fb3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -138,7 +138,7 @@
             "android.settings.AIRPLANE_MODE_SETTINGS";
 
     /**
-     * Activity Action: Modify Airplane mode settings using the users voice.
+     * Activity Action: Modify Airplane mode settings using a voice command.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you safeguard against this.
      * <p>
@@ -146,15 +146,13 @@
      * {@link android.service.voice.VoiceInteractionSession#startVoiceActivity
      * startVoiceActivity}.
      * <p>
-     * To tell which state airplane mode should be set to, add the
-     * {@link #EXTRA_AIRPLANE_MODE_ENABLED} extra to this Intent with the state specified.
-     * If there is no extra in this Intent, no changes will be made.
-     * <p>
-     * The activity should verify that
+     * Note: The activity implementing this intent MUST verify that
      * {@link android.app.Activity#isVoiceInteraction isVoiceInteraction} returns true before
      * modifying the setting.
      * <p>
-     * Input: Nothing.
+     * Input: To tell which state airplane mode should be set to, add the
+     * {@link #EXTRA_AIRPLANE_MODE_ENABLED} extra to this Intent with the state specified.
+     * If the extra is not included, no changes will be made.
      * <p>
      * Output: Nothing.
      */
@@ -839,6 +837,49 @@
     public static final String ACTION_ZEN_MODE_SETTINGS = "android.settings.ZEN_MODE_SETTINGS";
 
     /**
+     * Activity Action: Show Zen Mode priority configuration settings.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_ZEN_MODE_PRIORITY_SETTINGS
+            = "android.settings.ZEN_MODE_PRIORITY_SETTINGS";
+
+    /**
+     * Activity Action: Show Zen Mode automation configuration settings.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_ZEN_MODE_AUTOMATION_SETTINGS
+            = "android.settings.ZEN_MODE_AUTOMATION_SETTINGS";
+
+    /**
+     * Activity Action: Modify do not disturb mode settings.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you safeguard against this.
+     * <p>
+     * This intent MUST be started using
+     * {@link android.service.voice.VoiceInteractionSession#startVoiceActivity
+     * startVoiceActivity}.
+     * <p>
+     * Note: The Activity implementing this intent MUST verify that
+     * {@link android.app.Activity#isVoiceInteraction isVoiceInteraction}.
+     * returns true before modifying the setting.
+     * <p>
+     * Input: The optional {@link #EXTRA_DO_NOT_DISTURB_MODE_MINUTES} extra can be used to indicate
+     * how long the user wishes to avoid interruptions for. The optional
+     * {@link #EXTRA_DO_NOT_DISTURB_MODE_ENABLED} extra can be to indicate if the user is
+     * enabling or disabling do not disturb mode. If either extra is not included, the
+     * user maybe asked to provide the value.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_VOICE_CONTROL_DO_NOT_DISTURB_MODE =
+            "android.settings.VOICE_CONTROL_DO_NOT_DISTURB_MODE";
+
+    /**
      * Activity Action: Show the regulatory information screen for the device.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you safeguard
@@ -885,6 +926,29 @@
             = "android.settings.BATTERY_SAVER_SETTINGS";
 
     /**
+     * Activity Action: Modify Battery Saver mode setting using a voice command.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you safeguard against this.
+     * <p>
+     * This intent MUST be started using
+     * {@link android.service.voice.VoiceInteractionSession#startVoiceActivity
+     * startVoiceActivity}.
+     * <p>
+     * Note: The activity implementing this intent MUST verify that
+     * {@link android.app.Activity#isVoiceInteraction isVoiceInteraction} returns true before
+     * modifying the setting.
+     * <p>
+     * Input: To tell which state batter saver mode should be set to, add the
+     * {@link #EXTRA_BATTERY_SAVER_MODE_ENABLED} extra to this Intent with the state specified.
+     * If the extra is not included, no changes will be made.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_VOICE_CONTROL_BATTERY_SAVER_MODE =
+            "android.settings.VOICE_CONTROL_BATTERY_SAVER_MODE";
+
+    /**
      * Activity Action: Show Home selection settings. If there are multiple activities
      * that can satisfy the {@link Intent#CATEGORY_HOME} intent, this screen allows you
      * to pick your preferred activity.
@@ -998,10 +1062,37 @@
      * Activity Extra: Enable or disable Airplane Mode.
      * <p>
      * This can be passed as an extra field to the {@link #ACTION_VOICE_CONTROL_AIRPLANE_MODE}
-     * intent as a boolean.
+     * intent as a boolean to indicate if it should be enabled.
      */
     public static final String EXTRA_AIRPLANE_MODE_ENABLED = "airplane_mode_enabled";
 
+    /**
+     * Activity Extra: Enable or disable Battery saver mode.
+     * <p>
+     * This can be passed as an extra field to the {@link #ACTION_VOICE_CONTROL_BATTERY_SAVER_MODE}
+     * intent as a boolean to indicate if it should be enabled.
+     */
+    public static final String EXTRA_BATTERY_SAVER_MODE_ENABLED =
+            "android.settings.extra.battery_saver_mode_enabled";
+
+    /**
+     * Activity Extra: Enable or disable Do Not Disturb mode.
+     * <p>
+     * This can be passed as an extra field to the {@link #ACTION_VOICE_CONTROL_DO_NOT_DISTURB_MODE}
+     * intent as a boolean to indicate if it should be enabled.
+     */
+    public static final String EXTRA_DO_NOT_DISTURB_MODE_ENABLED =
+            "android.settings.extra.do_not_disturb_mode_enabled";
+
+    /**
+     * Activity Extra: How many minutes to enable do not disturb mode for.
+     * <p>
+     * This can be passed as an extra field to the {@link #ACTION_VOICE_CONTROL_DO_NOT_DISTURB_MODE}
+     * intent to indicate how long do not disturb mode should be enabled for.
+     */
+    public static final String EXTRA_DO_NOT_DISTURB_MODE_MINUTES =
+            "android.settings.extra.do_not_disturb_mode_minutes";
+
     private static final String JID_RESOURCE_PREFIX = "android";
 
     public static final String AUTHORITY = "settings";
@@ -3026,7 +3117,7 @@
         };
 
         /**
-         * These are all pulbic system settings
+         * These are all public system settings
          *
          * @hide
          */
@@ -3126,7 +3217,7 @@
         }
 
         /**
-         * These are all pulbic system settings
+         * These are all public system settings
          *
          * @hide
          */
@@ -5255,6 +5346,15 @@
         public static final String SMS_DEFAULT_APPLICATION = "sms_default_application";
 
         /**
+         * Specifies the package name currently configured to be the emergency assistance application
+         *
+         * @see android.telephony.TelephonyManager#ACTION_EMERGENCY_ASSISTANCE
+         *
+         * @hide
+         */
+        public static final String EMERGENCY_ASSISTANCE_APPLICATION = "emergency_assistance_application";
+
+        /**
          * Names of the packages that the current user has explicitly allowed to
          * see all of the user's notifications, separated by ':'.
          *
@@ -5354,6 +5454,13 @@
         public static final String SLEEP_TIMEOUT = "sleep_timeout";
 
         /**
+         * Duration in milliseconds that an app should be inactive before it is considered idle.
+         * <p/>Type: Long
+         * @hide
+         */
+        public static final String APP_IDLE_DURATION = "app_idle_duration";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -5416,6 +5523,7 @@
          * since the managed profile doesn't get to change them.
          */
         private static final Set<String> CLONE_TO_MANAGED_PROFILE = new ArraySet<>();
+
         static {
             CLONE_TO_MANAGED_PROFILE.add(ACCESSIBILITY_ENABLED);
             CLONE_TO_MANAGED_PROFILE.add(ALLOW_MOCK_LOCATION);
@@ -6088,7 +6196,7 @@
        public static final String PACKAGE_VERIFIER_SETTING_VISIBLE = "verifier_setting_visible";
 
        /**
-        * Run package verificaiton on apps installed through ADB/ADT/USB
+        * Run package verification on apps installed through ADB/ADT/USB
         * 1 = perform package verification on ADB installs (default)
         * 0 = bypass package verification on ADB installs
         * @hide
@@ -6366,6 +6474,14 @@
                 "wifi_scan_always_enabled";
 
        /**
+        * Settings to allow BLE scans to be enabled even when Bluetooth is turned off for
+        * connectivity.
+        * @hide
+        */
+       public static final String BLE_SCAN_ALWAYS_AVAILABLE =
+               "ble_scan_always_enabled";
+
+       /**
         * Used to save the Wifi_ON state prior to tethering.
         * This state will be checked to restore Wifi after
         * the user turns off tethering.
@@ -7093,9 +7209,11 @@
         /** @hide */ public static final int ZEN_MODE_OFF = 0;
         /** @hide */ public static final int ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
         /** @hide */ public static final int ZEN_MODE_NO_INTERRUPTIONS = 2;
+        /** @hide */ public static final int ZEN_MODE_ALARMS = 3;
 
         /** @hide */ public static String zenModeToString(int mode) {
             if (mode == ZEN_MODE_IMPORTANT_INTERRUPTIONS) return "ZEN_MODE_IMPORTANT_INTERRUPTIONS";
+            if (mode == ZEN_MODE_ALARMS) return "ZEN_MODE_ALARMS";
             if (mode == ZEN_MODE_NO_INTERRUPTIONS) return "ZEN_MODE_NO_INTERRUPTIONS";
             return "ZEN_MODE_OFF";
         }
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 0da4fd5..efbb3b8 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -258,7 +258,7 @@
         public static Uri insert(Context context, Voicemail voicemail) {
             ContentResolver contentResolver = context.getContentResolver();
             ContentValues contentValues = getContentValues(voicemail);
-            return contentResolver.insert(Voicemails.CONTENT_URI, contentValues);
+            return contentResolver.insert(buildSourceUri(context.getPackageName()), contentValues);
         }
 
         /**
@@ -273,7 +273,7 @@
             int count = voicemails.size();
             for (int i = 0; i < count; i++) {
                 ContentValues contentValues = getContentValues(voicemails.get(i));
-                contentResolver.insert(Voicemails.CONTENT_URI, contentValues);
+                contentResolver.insert(buildSourceUri(context.getPackageName()), contentValues);
             }
             return count;
         }
diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl
index ac6bbb7..579cdbe 100644
--- a/core/java/android/security/IKeystoreService.aidl
+++ b/core/java/android/security/IKeystoreService.aidl
@@ -19,6 +19,7 @@
 import android.security.keymaster.ExportResult;
 import android.security.keymaster.KeyCharacteristics;
 import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterBlob;
 import android.security.keymaster.OperationResult;
 import android.security.KeystoreArguments;
 
@@ -59,16 +60,19 @@
 
     // Keymaster 0.4 methods
     int addRngEntropy(in byte[] data);
-    int generateKey(String alias, in KeymasterArguments arguments, int uid, int flags,
+    int generateKey(String alias, in KeymasterArguments arguments, in byte[] entropy, int uid,
+        int flags, out KeyCharacteristics characteristics);
+    int getKeyCharacteristics(String alias, in KeymasterBlob clientId, in KeymasterBlob appId,
         out KeyCharacteristics characteristics);
-    int getKeyCharacteristics(String alias, in byte[] clientId,
-        in byte[] appId, out KeyCharacteristics characteristics);
     int importKey(String alias, in KeymasterArguments arguments, int format,
         in byte[] keyData, int uid, int flags, out KeyCharacteristics characteristics);
-    ExportResult exportKey(String alias, int format, in byte[] clientId, in byte[] appId);
+    ExportResult exportKey(String alias, int format, in KeymasterBlob clientId,
+        in KeymasterBlob appId);
     OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable,
-        in KeymasterArguments params, out KeymasterArguments operationParams);
+        in KeymasterArguments params, in byte[] entropy, out KeymasterArguments operationParams);
     OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input);
     OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature);
     int abort(IBinder handle);
+    boolean isOperationAuthorized(IBinder token);
+    int addAuthToken(in byte[] authToken);
 }
diff --git a/core/java/android/security/NetworkSecurityPolicy.java b/core/java/android/security/NetworkSecurityPolicy.java
index c7274e8..0b3bf453 100644
--- a/core/java/android/security/NetworkSecurityPolicy.java
+++ b/core/java/android/security/NetworkSecurityPolicy.java
@@ -19,48 +19,57 @@
 /**
  * Network security policy.
  *
- * @hide
+ * <p>Network stacks/components should honor this policy to make it possible to centrally control
+ * the relevant aspects of network security behavior.
+ *
+ * <p>The policy currently consists of a single flag: whether cleartext network traffic is
+ * permitted. See {@link #isCleartextTrafficPermitted()}.
  */
 public class NetworkSecurityPolicy {
 
-  private static final NetworkSecurityPolicy INSTANCE = new NetworkSecurityPolicy();
+    private static final NetworkSecurityPolicy INSTANCE = new NetworkSecurityPolicy();
 
-  private boolean mCleartextTrafficPermitted = true;
+    private NetworkSecurityPolicy() {}
 
-  private NetworkSecurityPolicy() {}
-
-  /**
-   * Gets the policy.
-   */
-  public static NetworkSecurityPolicy getInstance() {
-    return INSTANCE;
-  }
-
-  /**
-   * Checks whether cleartext network traffic (e.g., HTTP, WebSockets, XMPP, IMAP, SMTP -- without
-   * TLS or STARTTLS) is permitted for this process.
-   *
-   * <p>When cleartext network traffic is not permitted, the platform's components (e.g., HTTP
-   * stacks, {@code WebView}, {@code MediaPlayer}) will refuse this process's requests to use
-   * cleartext traffic. Third-party libraries are encouraged to honor this setting as well.
-   */
-  public boolean isCleartextTrafficPermitted() {
-    synchronized (this) {
-      return mCleartextTrafficPermitted;
+    /**
+     * Gets the policy for this process.
+     *
+     * <p>It's fine to cache this reference. Any changes to the policy will be immediately visible
+     * through the reference.
+     */
+    public static NetworkSecurityPolicy getInstance() {
+        return INSTANCE;
     }
-  }
 
-  /**
-   * Sets whether cleartext network traffic is permitted for this process.
-   *
-   * <p>This method is used by the platform early on in the application's initialization to set the
-   * policy.
-   *
-   * @hide
-   */
-  public void setCleartextTrafficPermitted(boolean permitted) {
-    synchronized (this) {
-      mCleartextTrafficPermitted = permitted;
+    /**
+     * Returns whether cleartext network traffic (e.g. HTTP, FTP, WebSockets, XMPP, IMAP, SMTP --
+     * without TLS or STARTTLS) is permitted for this process.
+     *
+     * <p>When cleartext network traffic is not permitted, the platform's components (e.g. HTTP and
+     * FTP stacks, {@link android.webkit.WebView}, {@link android.media.MediaPlayer}) will refuse
+     * this process's requests to use cleartext traffic. Third-party libraries are strongly
+     * encouraged to honor this setting as well.
+     *
+     * <p>This flag is honored on a best effort basis because it's impossible to prevent all
+     * cleartext traffic from Android applications given the level of access provided to them. For
+     * example, there's no expectation that the {@link java.net.Socket} API will honor this flag
+     * because it cannot determine whether its traffic is in cleartext. However, most network
+     * traffic from applications is handled by higher-level network stacks/components which can
+     * honor this aspect of the policy.
+     */
+    public boolean isCleartextTrafficPermitted() {
+        return libcore.net.NetworkSecurityPolicy.isCleartextTrafficPermitted();
     }
-  }
+
+    /**
+     * Sets whether cleartext network traffic is permitted for this process.
+     *
+     * <p>This method is used by the platform early on in the application's initialization to set
+     * the policy.
+     *
+     * @hide
+     */
+    public void setCleartextTrafficPermitted(boolean permitted) {
+        libcore.net.NetworkSecurityPolicy.setCleartextTrafficPermitted(permitted);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/core/java/android/security/keymaster/KeymasterBlob.aidl
similarity index 68%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to core/java/android/security/keymaster/KeymasterBlob.aidl
index 272c321..8f70f7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/core/java/android/security/keymaster/KeymasterBlob.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
+/**
+ * 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
+ *     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,
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+package android.security.keymaster;
 
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
-}
+/* @hide */
+parcelable KeymasterBlob;
diff --git a/core/java/android/security/keymaster/KeymasterBlob.java b/core/java/android/security/keymaster/KeymasterBlob.java
new file mode 100644
index 0000000..cb95604
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterBlob.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+public class KeymasterBlob implements Parcelable {
+    public byte[] blob;
+
+    public KeymasterBlob(byte[] blob) {
+        this.blob = blob;
+    }
+    public static final Parcelable.Creator<KeymasterBlob> CREATOR = new
+            Parcelable.Creator<KeymasterBlob>() {
+                public KeymasterBlob createFromParcel(Parcel in) {
+                    return new KeymasterBlob(in);
+                }
+
+                public KeymasterBlob[] newArray(int length) {
+                    return new KeymasterBlob[length];
+                }
+            };
+
+    protected KeymasterBlob(Parcel in) {
+        blob = in.createByteArray();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeByteArray(blob);
+    }
+}
diff --git a/core/java/android/security/keymaster/KeymasterBlobArgument.java b/core/java/android/security/keymaster/KeymasterBlobArgument.java
index 9af4445..7d587bf 100644
--- a/core/java/android/security/keymaster/KeymasterBlobArgument.java
+++ b/core/java/android/security/keymaster/KeymasterBlobArgument.java
@@ -26,6 +26,13 @@
 
     public KeymasterBlobArgument(int tag, byte[] blob) {
         super(tag);
+        switch (KeymasterDefs.getTagType(tag)) {
+            case KeymasterDefs.KM_BIGNUM:
+            case KeymasterDefs.KM_BYTES:
+                break; // OK.
+            default:
+                throw new IllegalArgumentException("Bad blob tag " + tag);
+        }
         this.blob = blob;
     }
 
diff --git a/core/java/android/security/keymaster/KeymasterBooleanArgument.java b/core/java/android/security/keymaster/KeymasterBooleanArgument.java
index 5481e8f..9c03674 100644
--- a/core/java/android/security/keymaster/KeymasterBooleanArgument.java
+++ b/core/java/android/security/keymaster/KeymasterBooleanArgument.java
@@ -28,6 +28,12 @@
 
     public KeymasterBooleanArgument(int tag) {
         super(tag);
+        switch (KeymasterDefs.getTagType(tag)) {
+            case KeymasterDefs.KM_BOOL:
+                break; // OK.
+            default:
+                throw new IllegalArgumentException("Bad bool tag " + tag);
+        }
     }
 
     public KeymasterBooleanArgument(int tag, Parcel in) {
diff --git a/core/java/android/security/keymaster/KeymasterDateArgument.java b/core/java/android/security/keymaster/KeymasterDateArgument.java
index 310f546..bffd24d 100644
--- a/core/java/android/security/keymaster/KeymasterDateArgument.java
+++ b/core/java/android/security/keymaster/KeymasterDateArgument.java
@@ -27,6 +27,12 @@
 
     public KeymasterDateArgument(int tag, Date date) {
         super(tag);
+        switch (KeymasterDefs.getTagType(tag)) {
+            case KeymasterDefs.KM_DATE:
+                break; // OK.
+            default:
+                throw new IllegalArgumentException("Bad date tag " + tag);
+        }
         this.date = date;
     }
 
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index e653b74..5e2accd 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -16,6 +16,9 @@
 
 package android.security.keymaster;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Class tracking all the keymaster enum values needed for the binder API to keystore.
  * This must be kept in sync with hardware/libhardware/include/hardware/keymaster_defs.h
@@ -168,6 +171,10 @@
     public static final int KM_KEY_FORMAT_PKCS12 = 2;
     public static final int KM_KEY_FORMAT_RAW = 3;
 
+    // User authenticators.
+    public static final int HW_AUTH_PASSWORD = 1 << 0;
+    public static final int HW_AUTH_FINGERPRINT = 1 << 1;
+
     // Error codes.
     public static final int KM_ERROR_OK = 0;
     public static final int KM_ERROR_ROOT_OF_TRUST_ALREADY_SET = -1;
@@ -178,7 +185,7 @@
     public static final int KM_ERROR_UNSUPPORTED_KEY_SIZE = -6;
     public static final int KM_ERROR_UNSUPPORTED_BLOCK_MODE = -7;
     public static final int KM_ERROR_INCOMPATIBLE_BLOCK_MODE = -8;
-    public static final int KM_ERROR_UNSUPPORTED_TAG_LENGTH = -9;
+    public static final int KM_ERROR_UNSUPPORTED_MAC_LENGTH = -9;
     public static final int KM_ERROR_UNSUPPORTED_PADDING_MODE = -10;
     public static final int KM_ERROR_INCOMPATIBLE_PADDING_MODE = -11;
     public static final int KM_ERROR_UNSUPPORTED_DIGEST = -12;
@@ -224,7 +231,54 @@
     public static final int KM_ERROR_VERSION_MISMATCH = -101;
     public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
 
+    public static final Map<Integer, String> sErrorCodeToString = new HashMap<Integer, String>();
+    static {
+        sErrorCodeToString.put(KM_ERROR_OK, "OK");
+        sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_PURPOSE, "Unsupported purpose");
+        sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_PURPOSE, "Incompatible purpose");
+        sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_ALGORITHM, "Unsupported algorithm");
+        sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_ALGORITHM, "Incompatible algorithm");
+        sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_KEY_SIZE, "Unsupported key size");
+        sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_BLOCK_MODE, "Unsupported block mode");
+        sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_BLOCK_MODE, "Incompatible block mode");
+        sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_MAC_LENGTH,
+                "Unsupported MAC or authentication tag length");
+        sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_PADDING_MODE, "Unsupported padding mode");
+        sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_PADDING_MODE, "Incompatible padding mode");
+        sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_DIGEST, "Unsupported digest");
+        sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_DIGEST, "Incompatible digest");
+        sErrorCodeToString.put(KM_ERROR_INVALID_EXPIRATION_TIME, "Invalid expiration time");
+        sErrorCodeToString.put(KM_ERROR_INVALID_USER_ID, "Invalid user ID");
+        sErrorCodeToString.put(KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT,
+                "Invalid user authorization timeout");
+        sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_KEY_FORMAT, "Unsupported key format");
+        sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_KEY_FORMAT, "Incompatible key format");
+        sErrorCodeToString.put(KM_ERROR_INVALID_INPUT_LENGTH, "Invalid input length");
+        sErrorCodeToString.put(KM_ERROR_KEY_NOT_YET_VALID, "Key not yet valid");
+        sErrorCodeToString.put(KM_ERROR_KEY_EXPIRED, "Key expired");
+        sErrorCodeToString.put(KM_ERROR_KEY_USER_NOT_AUTHENTICATED, "Key user not authenticated");
+        sErrorCodeToString.put(KM_ERROR_INVALID_OPERATION_HANDLE, "Invalid operation handle");
+        sErrorCodeToString.put(KM_ERROR_VERIFICATION_FAILED, "Signature/MAC verification failed");
+        sErrorCodeToString.put(KM_ERROR_TOO_MANY_OPERATIONS, "Too many operations");
+        sErrorCodeToString.put(KM_ERROR_INVALID_KEY_BLOB, "Invalid key blob");
+        sErrorCodeToString.put(KM_ERROR_INVALID_ARGUMENT, "Invalid argument");
+        sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_TAG, "Unsupported tag");
+        sErrorCodeToString.put(KM_ERROR_INVALID_TAG, "Invalid tag");
+        sErrorCodeToString.put(KM_ERROR_MEMORY_ALLOCATION_FAILED, "Memory allocation failed");
+        sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_EC_FIELD, "Unsupported EC field");
+        sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
+        sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
+    }
+
     public static int getTagType(int tag) {
         return tag & (0xF << 28);
     }
+
+    public static String getErrorMessage(int errorCode) {
+        String result = sErrorCodeToString.get(errorCode);
+        if (result != null) {
+            return result;
+        }
+        return String.valueOf(errorCode);
+    }
 }
diff --git a/core/java/android/security/keymaster/KeymasterIntArgument.java b/core/java/android/security/keymaster/KeymasterIntArgument.java
index c3738d7..da81715 100644
--- a/core/java/android/security/keymaster/KeymasterIntArgument.java
+++ b/core/java/android/security/keymaster/KeymasterIntArgument.java
@@ -26,6 +26,15 @@
 
     public KeymasterIntArgument(int tag, int value) {
         super(tag);
+        switch (KeymasterDefs.getTagType(tag)) {
+            case KeymasterDefs.KM_INT:
+            case KeymasterDefs.KM_INT_REP:
+            case KeymasterDefs.KM_ENUM:
+            case KeymasterDefs.KM_ENUM_REP:
+                break; // OK.
+            default:
+                throw new IllegalArgumentException("Bad int tag " + tag);
+        }
         this.value = value;
     }
 
diff --git a/core/java/android/security/keymaster/KeymasterLongArgument.java b/core/java/android/security/keymaster/KeymasterLongArgument.java
index 3c565b8..9d2be09 100644
--- a/core/java/android/security/keymaster/KeymasterLongArgument.java
+++ b/core/java/android/security/keymaster/KeymasterLongArgument.java
@@ -26,6 +26,12 @@
 
     public KeymasterLongArgument(int tag, long value) {
         super(tag);
+        switch (KeymasterDefs.getTagType(tag)) {
+            case KeymasterDefs.KM_LONG:
+                break; // OK.
+            default:
+                throw new IllegalArgumentException("Bad long tag " + tag);
+        }
         this.value = value;
     }
 
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index 4fc9d24..9b46ad3 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -28,6 +28,7 @@
 public class OperationResult implements Parcelable {
     public final int resultCode;
     public final IBinder token;
+    public final long operationHandle;
     public final int inputConsumed;
     public final byte[] output;
 
@@ -45,6 +46,7 @@
     protected OperationResult(Parcel in) {
         resultCode = in.readInt();
         token = in.readStrongBinder();
+        operationHandle = in.readLong();
         inputConsumed = in.readInt();
         output = in.createByteArray();
     }
@@ -58,6 +60,7 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(resultCode);
         out.writeStrongBinder(token);
+        out.writeLong(operationHandle);
         out.writeInt(inputConsumed);
         out.writeByteArray(output);
     }
diff --git a/core/java/android/service/fingerprint/FingerprintManager.java b/core/java/android/service/fingerprint/FingerprintManager.java
deleted file mode 100644
index 6375668..0000000
--- a/core/java/android/service/fingerprint/FingerprintManager.java
+++ /dev/null
@@ -1,313 +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.
- */
-
-package android.service.fingerprint;
-
-import android.app.ActivityManagerNative;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Slog;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A class that coordinates access to the fingerprint hardware.
- * @hide
- */
-
-public class FingerprintManager {
-    private static final String TAG = "FingerprintManager";
-    private static final boolean DEBUG = true;
-    private static final int MSG_ENROLL_RESULT = 100;
-    private static final int MSG_ACQUIRED = 101;
-    private static final int MSG_PROCESSED = 102;
-    private static final int MSG_ERROR = 103;
-    private static final int MSG_REMOVED = 104;
-
-    // Errors generated by layers above HAL
-    public static final int FINGERPRINT_ERROR_NO_RECEIVER = -10;
-
-    // Message types.  Must agree with HAL (fingerprint.h)
-    public static final int FINGERPRINT_ERROR = -1;
-    public static final int FINGERPRINT_ACQUIRED = 1;
-    public static final int FINGERPRINT_PROCESSED = 2;
-    public static final int FINGERPRINT_TEMPLATE_ENROLLING = 3;
-    public static final int FINGERPRINT_TEMPLATE_REMOVED = 4;
-
-    // Error messages. Must agree with HAL (fingerprint.h)
-    public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
-    public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2;
-    public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
-    public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
-
-    // FINGERPRINT_ACQUIRED messages.  Must agree with HAL (fingerprint.h)
-    public static final int FINGERPRINT_ACQUIRED_GOOD = 0;
-    public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1;
-    public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2;
-    public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 4;
-    public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 8;
-    public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 16;
-
-    private IFingerprintService mService;
-    private FingerprintManagerReceiver mClientReceiver;
-    private Context mContext;
-    private IBinder mToken = new Binder();
-
-    private Handler mHandler = new Handler() {
-        public void handleMessage(android.os.Message msg) {
-            if (mClientReceiver != null) {
-                switch(msg.what) {
-                    case MSG_ENROLL_RESULT:
-                        mClientReceiver.onEnrollResult(msg.arg1, msg.arg2);
-                        break;
-                    case MSG_ACQUIRED:
-                        mClientReceiver.onAcquired(msg.arg1);
-                        break;
-                    case MSG_PROCESSED:
-                        mClientReceiver.onProcessed(msg.arg1);
-                        break;
-                    case MSG_ERROR:
-                        mClientReceiver.onError(msg.arg1);
-                        break;
-                    case MSG_REMOVED:
-                        mClientReceiver.onRemoved(msg.arg1);
-                }
-            }
-        }
-    };
-
-    public static final class FingerprintItem {
-        public CharSequence name;
-        public int id;
-        FingerprintItem(CharSequence name, int id) {
-            this.name = name;
-            this.id = id;
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public FingerprintManager(Context context, IFingerprintService service) {
-        mContext = context;
-        mService = service;
-        if (mService == null) {
-            Slog.v(TAG, "FingerprintManagerService was null");
-        }
-    }
-
-    private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
-
-        public void onEnrollResult(int fingerprintId,  int remaining) {
-            mHandler.obtainMessage(MSG_ENROLL_RESULT, fingerprintId, remaining).sendToTarget();
-        }
-
-        public void onAcquired(int acquireInfo) {
-            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0).sendToTarget();
-        }
-
-        public void onProcessed(int fingerprintId) {
-            mHandler.obtainMessage(MSG_PROCESSED, fingerprintId, 0).sendToTarget();
-        }
-
-        public void onError(int error) {
-            mHandler.obtainMessage(MSG_ERROR, error, 0).sendToTarget();
-        }
-
-        public void onRemoved(int fingerprintId) {
-            mHandler.obtainMessage(MSG_REMOVED, fingerprintId, 0).sendToTarget();
-        }
-    };
-
-    /**
-     * Determine whether the user has at least one fingerprint enrolled and enabled.
-     *
-     * @return true if at least one is enrolled and enabled
-     */
-    public boolean enrolledAndEnabled() {
-        ContentResolver res = mContext.getContentResolver();
-        return Settings.Secure.getInt(res, "fingerprint_enabled", 0) != 0
-                && FingerprintUtils.getFingerprintIdsForUser(res, getCurrentUserId()).length > 0;
-    }
-
-    /**
-     * Start the enrollment process.  Timeout dictates how long to wait for the user to
-     * enroll a fingerprint.
-     *
-     * @param timeout
-     */
-    public void enroll(long timeout) {
-        if (mServiceReceiver == null) {
-            sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0);
-            return;
-        }
-        if (mService != null) try {
-            mService.enroll(mToken, timeout, getCurrentUserId());
-        } catch (RemoteException e) {
-            Log.v(TAG, "Remote exception while enrolling: ", e);
-            sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
-        }
-    }
-
-    /**
-     * Remove the given fingerprintId from the system.  FingerprintId of 0 has special meaning
-     * which is to delete all fingerprint data for the current user. Use with caution.
-     * @param fingerprintId
-     */
-    public void remove(int fingerprintId) {
-        if (mServiceReceiver == null) {
-            sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0);
-            return;
-        }
-        if (mService != null) {
-            try {
-                mService.remove(mToken, fingerprintId, getCurrentUserId());
-            } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception during remove of fingerprintId: " + fingerprintId, e);
-            }
-        } else {
-            Log.w(TAG, "remove(): Service not connected!");
-            sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
-        }
-    }
-
-    /**
-     * Starts listening for fingerprint events.  When a finger is scanned or recognized, the
-     * client will be notified via the callback.
-     */
-    public void startListening(FingerprintManagerReceiver receiver) {
-        mClientReceiver = receiver;
-        if (mService != null) {
-            try {
-                mService.startListening(mToken, mServiceReceiver, getCurrentUserId());
-            } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in startListening(): ", e);
-            }
-        } else {
-            Log.w(TAG, "startListening(): Service not connected!");
-            sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
-        }
-    }
-
-    private int getCurrentUserId() {
-        try {
-            return ActivityManagerNative.getDefault().getCurrentUser().id;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to get current user id\n");
-            return UserHandle.USER_NULL;
-        }
-    }
-
-    /**
-     * Stops the client from listening to fingerprint events.
-     */
-    public void stopListening() {
-        if (mService != null) {
-            try {
-                mService.stopListening(mToken, getCurrentUserId());
-                mClientReceiver = null;
-            } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in stopListening(): ", e);
-            }
-        } else {
-            Log.w(TAG, "stopListening(): Service not connected!");
-            sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
-        }
-    }
-
-    public void enrollCancel() {
-        if (mServiceReceiver == null) {
-            sendError(FINGERPRINT_ERROR_NO_RECEIVER, 0, 0);
-            return;
-        }
-        if (mService != null) {
-            try {
-                mService.enrollCancel(mToken, getCurrentUserId());
-                mClientReceiver = null;
-            } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in enrollCancel(): ", e);
-                sendError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0, 0);
-            }
-        } else {
-            Log.w(TAG, "enrollCancel(): Service not connected!");
-        }
-    }
-
-    private void sendError(int msg, int arg1, int arg2) {
-        mHandler.obtainMessage(msg, arg1, arg2);
-    }
-
-    /**
-     * @return list of current fingerprint items
-     * @hide
-     */
-    public List<FingerprintItem> getEnrolledFingerprints() {
-        int[] ids = FingerprintUtils.getFingerprintIdsForUser(mContext.getContentResolver(),
-                getCurrentUserId());
-        List<FingerprintItem> result = new ArrayList<FingerprintItem>();
-        for (int i = 0; i < ids.length; i++) {
-            // TODO: persist names in Settings
-            FingerprintItem item = new FingerprintItem("Finger" + ids[i], ids[i]);
-            result.add(item);
-        }
-        return result;
-    }
-
-    /**
-     * Determine if fingerprint hardware is present and functional.
-     * @return true if hardware is present and functional, false otherwise.
-     * @hide
-     */
-    public boolean isHardwareDetected() {
-        if (mService != null) {
-            try {
-                return mService.isHardwareDetected();
-            } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e);
-            }
-        } else {
-            Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
-        }
-        return false;
-    }
-
-    /**
-     * Renames the given fingerprint template
-     * @param fpId the fingerprint id
-     * @param newName the new name
-     * @hide
-     */
-    public void rename(int fpId, String newName) {
-        // Renames the given fpId
-        if (mService != null) {
-            try {
-                mService.rename(fpId, newName);
-            } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in rename(): ", e);
-            }
-        } else {
-            Log.w(TAG, "rename(): Service not connected!");
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/java/android/service/fingerprint/FingerprintManagerReceiver.java b/core/java/android/service/fingerprint/FingerprintManagerReceiver.java
deleted file mode 100644
index 85677ba..0000000
--- a/core/java/android/service/fingerprint/FingerprintManagerReceiver.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package android.service.fingerprint;
-/**
- * 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.
- */
-
-/**
- * @hide
- */
-public class FingerprintManagerReceiver {
-    /**
-     * Fingerprint enrollment progress update. Enrollment is considered complete if
-     * remaining hits 0 without {@link #onError(int)} being called.
-     *
-     * @param fingerprintId the fingerprint we're currently enrolling
-     * @param remaining the number of samples required to complete enrollment. It's up to
-     * the hardware to define what each step in enrollment means. Some hardware
-     * requires multiple samples of the same part of the finger.  Others require sampling of
-     * different parts of the finger.  The enrollment flow can use remaining to
-     * mean "step x" of the process or "just need another sample."
-     */
-    public void onEnrollResult(int fingerprintId,  int remaining) { }
-
-    /**
-     * Fingerprint touch detected, but not processed yet. Clients will use this message to
-     * determine a good or bad scan before the fingerprint is processed.  This is meant for the
-     * client to provide feedback about the scan or alert the user that recognition is to follow.
-     *
-     * @param acquiredInfo one of:
-     * {@link FingerprintManager#FINGERPRINT_ACQUIRED_GOOD},
-     * {@link FingerprintManager#FINGERPRINT_ACQUIRED_PARTIAL},
-     * {@link FingerprintManager#FINGERPRINT_ACQUIRED_INSUFFICIENT},
-     * {@link FingerprintManager#FINGERPRINT_ACQUIRED_IMAGER_DIRTY},
-     * {@link FingerprintManager#FINGERPRINT_ACQUIRED_TOO_SLOW},
-     * {@link FingerprintManager#FINGERPRINT_ACQUIRED_TOO_FAST}
-     */
-    public void onAcquired(int acquiredInfo) { }
-
-    /**
-     * Fingerprint has been detected and processed.  A non-zero return indicates a valid
-     * fingerprint was detected.
-     *
-     * @param fingerprintId the finger id, or 0 if not recognized.
-     */
-    public void onProcessed(int fingerprintId) { }
-
-    /**
-     * An error was detected during scan or enrollment.  One of
-     * {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE},
-     * {@link FingerprintManager#FINGERPRINT_ERROR_UNABLE_TO_PROCESS} or
-     * {@link FingerprintManager#FINGERPRINT_ERROR_TIMEOUT}
-     * {@link FingerprintManager#FINGERPRINT_ERROR_NO_SPACE}
-     *
-     * @param error one of the above error codes
-     */
-    public void onError(int error) { }
-
-    /**
-     * The given fingerprint template was successfully removed by the driver.
-     * See {@link FingerprintManager#remove(int)}
-     *
-     * @param fingerprintId id of template to remove.
-     */
-    public void onRemoved(int fingerprintId) { }
-}
\ No newline at end of file
diff --git a/core/java/android/service/fingerprint/IFingerprintService.aidl b/core/java/android/service/fingerprint/IFingerprintService.aidl
deleted file mode 100644
index 9b4750b..0000000
--- a/core/java/android/service/fingerprint/IFingerprintService.aidl
+++ /dev/null
@@ -1,47 +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.
- */
-package android.service.fingerprint;
-
-import android.os.Bundle;
-import android.service.fingerprint.IFingerprintServiceReceiver;
-
-/**
- * Communication channel from client to the fingerprint service.
- * @hide
- */
-interface IFingerprintService {
-    // Any errors resulting from this call will be returned to the listener
-    void enroll(IBinder token, long timeout, int userId);
-
-    // Any errors resulting from this call will be returned to the listener
-    void enrollCancel(IBinder token, int userId);
-
-    // Any errors resulting from this call will be returned to the listener
-    void remove(IBinder token, int fingerprintId, int userId);
-
-    // Start listening for fingerprint events.  This has the side effect of starting
-    // the hardware if not already started.
-    void startListening(IBinder token, IFingerprintServiceReceiver receiver, int userId);
-
-    // Stops listening for fingerprints
-    void stopListening(IBinder token, int userId);
-
-    // Determine if HAL is loaded and ready
-    boolean isHardwareDetected();
-
-    // Rename the given fingerprint id
-    void rename(int fpId, String name);
-}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 0860153..fa782e4 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -77,6 +77,12 @@
      */
     public static final int INTERRUPTION_FILTER_NONE = 3;
 
+    /**
+     * {@link #getCurrentInterruptionFilter() Interruption filter} constant -
+     *     Alarms only interruption filter.
+     */
+    public static final int INTERRUPTION_FILTER_ALARMS = 4;
+
     /** {@link #getCurrentInterruptionFilter() Interruption filter} constant - returned when
      * the value is unavailable for any reason.  For example, before the notification listener
      * is connected.
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 979a01b..2702457 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -66,6 +66,7 @@
     private static final int MINUTES_MS = 60 * SECONDS_MS;
     private static final int ZERO_VALUE_MS = 10 * SECONDS_MS;
 
+    private static final boolean DEFAULT_ALLOW_REMINDERS = true;
     private static final boolean DEFAULT_ALLOW_EVENTS = true;
 
     private static final int XML_VERSION = 1;
@@ -75,6 +76,7 @@
     private static final String ALLOW_ATT_CALLS = "calls";
     private static final String ALLOW_ATT_MESSAGES = "messages";
     private static final String ALLOW_ATT_FROM = "from";
+    private static final String ALLOW_ATT_REMINDERS = "reminders";
     private static final String ALLOW_ATT_EVENTS = "events";
     private static final String SLEEP_TAG = "sleep";
     private static final String SLEEP_ATT_MODE = "mode";
@@ -100,6 +102,7 @@
 
     public boolean allowCalls;
     public boolean allowMessages;
+    public boolean allowReminders = DEFAULT_ALLOW_REMINDERS;
     public boolean allowEvents = DEFAULT_ALLOW_EVENTS;
     public int allowFrom = SOURCE_ANYONE;
 
@@ -119,6 +122,7 @@
     public ZenModeConfig(Parcel source) {
         allowCalls = source.readInt() == 1;
         allowMessages = source.readInt() == 1;
+        allowReminders = source.readInt() == 1;
         allowEvents = source.readInt() == 1;
         if (source.readInt() == 1) {
             sleepMode = source.readString();
@@ -147,6 +151,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(allowCalls ? 1 : 0);
         dest.writeInt(allowMessages ? 1 : 0);
+        dest.writeInt(allowReminders ? 1 : 0);
         dest.writeInt(allowEvents ? 1 : 0);
         if (sleepMode != null) {
             dest.writeInt(1);
@@ -182,6 +187,7 @@
             .append("allowCalls=").append(allowCalls)
             .append(",allowMessages=").append(allowMessages)
             .append(",allowFrom=").append(sourceToString(allowFrom))
+            .append(",allowReminders=").append(allowReminders)
             .append(",allowEvents=").append(allowEvents)
             .append(",sleepMode=").append(sleepMode)
             .append(",sleepStart=").append(sleepStartHour).append('.').append(sleepStartMinute)
@@ -217,6 +223,7 @@
         return other.allowCalls == allowCalls
                 && other.allowMessages == allowMessages
                 && other.allowFrom == allowFrom
+                && other.allowReminders == allowReminders
                 && other.allowEvents == allowEvents
                 && Objects.equals(other.sleepMode, sleepMode)
                 && other.sleepNone == sleepNone
@@ -232,9 +239,9 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(allowCalls, allowMessages, allowFrom, allowEvents, sleepMode, sleepNone,
-                sleepStartHour, sleepStartMinute, sleepEndHour, sleepEndMinute,
-                Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds),
+        return Objects.hash(allowCalls, allowMessages, allowFrom, allowReminders, allowEvents,
+                sleepMode, sleepNone, sleepStartHour, sleepStartMinute, sleepEndHour,
+                sleepEndMinute, Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds),
                 exitCondition, exitConditionComponent);
     }
 
@@ -300,6 +307,8 @@
                 if (ALLOW_TAG.equals(tag)) {
                     rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS, false);
                     rt.allowMessages = safeBoolean(parser, ALLOW_ATT_MESSAGES, false);
+                    rt.allowReminders = safeBoolean(parser, ALLOW_ATT_REMINDERS,
+                            DEFAULT_ALLOW_REMINDERS);
                     rt.allowEvents = safeBoolean(parser, ALLOW_ATT_EVENTS, DEFAULT_ALLOW_EVENTS);
                     rt.allowFrom = safeInt(parser, ALLOW_ATT_FROM, SOURCE_ANYONE);
                     if (rt.allowFrom < SOURCE_ANYONE || rt.allowFrom > MAX_SOURCE) {
@@ -344,6 +353,7 @@
         out.startTag(null, ALLOW_TAG);
         out.attribute(null, ALLOW_ATT_CALLS, Boolean.toString(allowCalls));
         out.attribute(null, ALLOW_ATT_MESSAGES, Boolean.toString(allowMessages));
+        out.attribute(null, ALLOW_ATT_REMINDERS, Boolean.toString(allowReminders));
         out.attribute(null, ALLOW_ATT_EVENTS, Boolean.toString(allowEvents));
         out.attribute(null, ALLOW_ATT_FROM, Integer.toString(allowFrom));
         out.endTag(null, ALLOW_TAG);
diff --git a/core/java/android/service/voice/IVoiceInteractionSession.aidl b/core/java/android/service/voice/IVoiceInteractionSession.aidl
index 4f4b2d5..7c90261 100644
--- a/core/java/android/service/voice/IVoiceInteractionSession.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionSession.aidl
@@ -20,11 +20,13 @@
 import android.graphics.Bitmap;
 import android.os.Bundle;
 
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
+
 /**
  * @hide
  */
 oneway interface IVoiceInteractionSession {
-    void show(in Bundle sessionArgs, int flags);
+    void show(in Bundle sessionArgs, int flags, IVoiceInteractionSessionShowCallback showCallback);
     void hide();
     void handleAssist(in Bundle assistData);
     void handleScreenshot(in Bitmap screenshot);
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 419b92b..fee0c75 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -82,6 +82,12 @@
      */
     public static final int START_WITH_SCREENSHOT = 1<<1;
 
+    /**
+     * Flag for use with {@link #showSession}: indicate that the session has been started from the
+     * system assist gesture.
+     */
+    public static final int START_SOURCE_ASSIST_GESTURE = 1<<2;
+
     IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() {
         @Override public void ready() {
             mHandler.sendEmptyMessage(MSG_READY);
diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
index ebc7507..4bc97c9 100644
--- a/core/java/android/service/voice/VoiceInteractionServiceInfo.java
+++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
@@ -43,6 +43,7 @@
     private String mSessionService;
     private String mRecognitionService;
     private String mSettingsActivity;
+    private boolean mSupportsAssistGesture;
 
     public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)
             throws PackageManager.NameNotFoundException {
@@ -94,6 +95,9 @@
                     com.android.internal.R.styleable.VoiceInteractionService_recognitionService);
             mSettingsActivity = array.getString(
                     com.android.internal.R.styleable.VoiceInteractionService_settingsActivity);
+            mSupportsAssistGesture = array.getBoolean(
+                    com.android.internal.R.styleable.VoiceInteractionService_supportsAssistGesture,
+                    false);
             array.recycle();
             if (mSessionService == null) {
                 mParseError = "No sessionService specified";
@@ -103,11 +107,6 @@
                 mParseError = "No recognitionService specified";
                 return;
             }
-            /* Not yet time
-            if (mRecognitionService == null) {
-                mParseError = "No recogitionService specified";
-                return;
-            } */
         } catch (XmlPullParserException e) {
             mParseError = "Error parsing voice interation service meta-data: " + e;
             Log.w(TAG, "error parsing voice interaction service meta-data", e);
@@ -145,4 +144,8 @@
     public String getSettingsActivity() {
         return mSettingsActivity;
     }
+
+    public boolean getSupportsAssistGesture() {
+        return mSupportsAssistGesture;
+    }
 }
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 7a5bb90..20d7079 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -16,6 +16,7 @@
 
 package android.service.voice;
 
+import android.app.AssistStructure;
 import android.app.Dialog;
 import android.app.Instrumentation;
 import android.app.VoiceInteractor;
@@ -43,6 +44,7 @@
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.IVoiceInteractorCallback;
 import com.android.internal.app.IVoiceInteractorRequest;
@@ -163,9 +165,10 @@
 
     final IVoiceInteractionSession mSession = new IVoiceInteractionSession.Stub() {
         @Override
-        public void show(Bundle sessionArgs, int flags) {
-            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIO(MSG_SHOW,
-                    flags, sessionArgs));
+        public void show(Bundle sessionArgs, int flags,
+                IVoiceInteractionSessionShowCallback showCallback) {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(MSG_SHOW,
+                    flags, sessionArgs, showCallback));
         }
 
         @Override
@@ -175,6 +178,18 @@
 
         @Override
         public void handleAssist(Bundle assistBundle) {
+            // We want to pre-warm the AssistStructure before handing it off to the main
+            // thread.  There is a strong argument to be made that it should be handed
+            // through as a separate param rather than part of the assistBundle.
+            if (assistBundle != null) {
+                Bundle assistContext = assistBundle.getBundle(Intent.EXTRA_ASSIST_CONTEXT);
+                if (assistContext != null) {
+                    AssistStructure as = AssistStructure.getAssistStructure(assistContext);
+                    if (as != null) {
+                        as.ensureData();
+                    }
+                }
+            }
             mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO(MSG_HANDLE_ASSIST,
                     assistBundle));
         }
@@ -412,9 +427,12 @@
                     onHandleScreenshot((Bitmap) msg.obj);
                     break;
                 case MSG_SHOW:
-                    if (DEBUG) Log.d(TAG, "doShow: args=" + msg.obj
-                            + " flags=" + msg.arg1);
-                    doShow((Bundle) msg.obj, msg.arg1);
+                    args = (SomeArgs)msg.obj;
+                    if (DEBUG) Log.d(TAG, "doShow: args=" + args.arg1
+                            + " flags=" + msg.arg1
+                            + " showCallback=" + args.arg2);
+                    doShow((Bundle) args.arg1, msg.arg1,
+                            (IVoiceInteractionSessionShowCallback) args.arg2);
                     break;
                 case MSG_HIDE:
                     if (DEBUG) Log.d(TAG, "doHide");
@@ -502,6 +520,10 @@
                 mCallbacks, true);
     }
 
+    public Context getContext() {
+        return mContext;
+    }
+
     Request newRequest(IVoiceInteractorCallback callback) {
         synchronized (this) {
             Request req = new Request(callback, this);
@@ -512,11 +534,7 @@
 
     Request removeRequest(IBinder reqInterface) {
         synchronized (this) {
-            Request req = mActiveRequests.get(reqInterface);
-            if (req != null) {
-                mActiveRequests.remove(req);
-            }
-            return req;
+            return mActiveRequests.remove(reqInterface);
         }
     }
 
@@ -527,7 +545,7 @@
         onCreate(args, startFlags);
     }
 
-    void doShow(Bundle args, int flags) {
+    void doShow(Bundle args, int flags, final IVoiceInteractionSessionShowCallback showCallback) {
         if (DEBUG) Log.v(TAG, "Showing window: mWindowAdded=" + mWindowAdded
                 + " mWindowVisible=" + mWindowVisible);
 
@@ -552,6 +570,22 @@
                 mWindowVisible = true;
                 mWindow.show();
             }
+            if (showCallback != null) {
+                mRootView.invalidate();
+                mRootView.getViewTreeObserver().addOnPreDrawListener(
+                        new ViewTreeObserver.OnPreDrawListener() {
+                            @Override
+                            public boolean onPreDraw() {
+                                mRootView.getViewTreeObserver().removeOnPreDrawListener(this);
+                                try {
+                                    showCallback.onShown();
+                                } catch (RemoteException e) {
+                                    Log.w(TAG, "Error calling onShown", e);
+                                }
+                                return true;
+                            }
+                        });
+            }
         } finally {
             mWindowWasVisible = true;
             mInShowWindow = false;
@@ -586,7 +620,8 @@
         mRootView = mInflater.inflate(
                 com.android.internal.R.layout.voice_interaction_session, null);
         mRootView.setSystemUiVisibility(
-                View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+                View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
         mWindow.setContentView(mRootView);
         mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
 
@@ -720,7 +755,9 @@
         mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme,
                 mCallbacks, this, mDispatcherState,
                 WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true);
-        mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        mWindow.getWindow().addFlags(
+                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED |
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
         initViews();
         mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
         mWindow.setToken(mToken);
@@ -799,6 +836,12 @@
         return false;
     }
 
+    /**
+     * Called when the user presses the back button while focus is in the session UI.  Note
+     * that this will only happen if the session UI has requested input focus in its window;
+     * otherwise, the back key will go to whatever window has focus and do whatever behavior
+     * it normally has there.
+     */
     public void onBackPressed() {
         hide();
     }
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index d46b6f5..1674950 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -155,7 +155,6 @@
                 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
         int mCurWindowFlags = mWindowFlags;
         int mCurWindowPrivateFlags = mWindowPrivateFlags;
-        int mOutsetBottomPx;
         final Rect mVisibleInsets = new Rect();
         final Rect mWinFrame = new Rect();
         final Rect mOverscanInsets = new Rect();
@@ -624,18 +623,9 @@
                     mLayout.token = mWindowToken;
 
                     if (!mCreated) {
-                        // Retrieve watch round and outset info
-                        final WindowManager windowService = (WindowManager)getSystemService(
-                                Context.WINDOW_SERVICE);
+                        // Retrieve watch round info
                         TypedArray windowStyle = obtainStyledAttributes(
                                 com.android.internal.R.styleable.Window);
-                        final Display display = windowService.getDefaultDisplay();
-                        final boolean shouldUseBottomOutset =
-                                display.getDisplayId() == Display.DEFAULT_DISPLAY;
-                        if (shouldUseBottomOutset) {
-                            mOutsetBottomPx = ScreenShapeHelper.getWindowOutsetBottomPx(
-                                    getResources().getDisplayMetrics(), windowStyle);
-                        }
                         mWindowIsRound = ScreenShapeHelper.getWindowIsRound(getResources());
                         windowStyle.recycle();
 
@@ -770,10 +760,7 @@
                             mDispatchedStableInsets.set(mStableInsets);
                             mFinalSystemInsets.set(mDispatchedOverscanInsets);
                             mFinalStableInsets.set(mDispatchedStableInsets);
-                            if (mOutsetBottomPx != 0) {
-                                mFinalSystemInsets.bottom =
-                                        mIWallpaperEngine.mDisplayPadding.bottom + mOutsetBottomPx;
-                            }
+                            mFinalSystemInsets.bottom = mIWallpaperEngine.mDisplayPadding.bottom;
                             WindowInsets insets = new WindowInsets(mFinalSystemInsets,
                                     null, mFinalStableInsets, mWindowIsRound);
                             onApplyWindowInsets(insets);
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 1bdaef0..239b386 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -79,7 +79,8 @@
                          boolean includepad,
                          TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
         this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
-                spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth);
+                spacingmult, spacingadd, includepad, StaticLayout.BREAK_STRATEGY_SIMPLE,
+                ellipsize, ellipsizedWidth);
     }
 
     /**
@@ -95,7 +96,7 @@
                          TextPaint paint,
                          int width, Alignment align, TextDirectionHeuristic textDir,
                          float spacingmult, float spacingadd,
-                         boolean includepad,
+                         boolean includepad, int breakStrategy,
                          TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
         super((ellipsize == null)
                 ? display
@@ -120,6 +121,7 @@
         mObjects = new PackedObjectVector<Directions>(1);
 
         mIncludePad = includepad;
+        mBreakStrategy = breakStrategy;
 
         /*
          * This is annoying, but we can't refer to the layout until
@@ -279,10 +281,9 @@
             sBuilder = null;
         }
 
-        // TODO: make sure reflowed is properly initialized
         if (reflowed == null) {
             reflowed = new StaticLayout(null);
-            b = StaticLayout.Builder.obtain();
+            b = StaticLayout.Builder.obtain(text, where, where + after, getWidth());
         }
 
         b.setText(text, where, where + after)
@@ -292,7 +293,8 @@
                 .setSpacingMult(getSpacingMultiplier())
                 .setSpacingAdd(getSpacingAdd())
                 .setEllipsizedWidth(mEllipsizedWidth)
-                .setEllipsize(mEllipsizeAt);
+                .setEllipsize(mEllipsizeAt)
+                .setBreakStrategy(mBreakStrategy);
         reflowed.generate(b, false, true);
         int n = reflowed.getLineCount();
 
@@ -356,6 +358,8 @@
             ints[DESCENT] = desc;
             objects[0] = reflowed.getLineDirections(i);
 
+            ints[HYPHEN] = reflowed.getHyphen(i);
+
             if (mEllipsize) {
                 ints[ELLIPSIS_START] = reflowed.getEllipsisStart(i);
                 ints[ELLIPSIS_COUNT] = reflowed.getEllipsisCount(i);
@@ -631,6 +635,14 @@
         return mBottomPadding;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public int getHyphen(int line) {
+        return mInts.getValue(line, HYPHEN);
+    }
+
     @Override
     public int getEllipsizedWidth() {
         return mEllipsizedWidth;
@@ -707,6 +719,7 @@
     private boolean mEllipsize;
     private int mEllipsizedWidth;
     private TextUtils.TruncateAt mEllipsizeAt;
+    private int mBreakStrategy;
 
     private PackedIntVector mInts;
     private PackedObjectVector<Directions> mObjects;
@@ -739,11 +752,12 @@
     private static final int TAB = START;
     private static final int TOP = 1;
     private static final int DESCENT = 2;
-    private static final int COLUMNS_NORMAL = 3;
+    private static final int HYPHEN = 3;
+    private static final int COLUMNS_NORMAL = 4;
 
-    private static final int ELLIPSIS_START = 3;
-    private static final int ELLIPSIS_COUNT = 4;
-    private static final int COLUMNS_ELLIPSIZE = 5;
+    private static final int ELLIPSIS_START = 4;
+    private static final int ELLIPSIS_COUNT = 5;
+    private static final int COLUMNS_ELLIPSIZE = 6;
 
     private static final int START_MASK = 0x1FFFFFFF;
     private static final int DIR_SHIFT  = 30;
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index 8cf1b4b..7bebbfb 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -244,13 +244,18 @@
                 next++;
             }
 
-            withinParagraph(out, text, i, next - nl, nl, next == end);
+            if (withinParagraph(out, text, i, next - nl, nl, next == end)) {
+                /* Paragraph should be closed */
+                out.append("</p>\n");
+                out.append(getOpenParaTagWithDirection(text, next, end));
+            }
         }
 
         out.append("</p>\n");
     }
 
-    private static void withinParagraph(StringBuilder out, Spanned text,
+    /* Returns true if the caller should close and reopen the paragraph. */
+    private static boolean withinParagraph(StringBuilder out, Spanned text,
                                         int start, int end, int nl,
                                         boolean last) {
         int next;
@@ -363,17 +368,14 @@
             }
         }
 
-        String p = last ? "" : "</p>\n" + getOpenParaTagWithDirection(text, start, end);
-
         if (nl == 1) {
             out.append("<br>\n");
-        } else if (nl == 2) {
-            out.append(p);
+            return false;
         } else {
             for (int i = 2; i < nl; i++) {
                 out.append("<br>");
             }
-            out.append(p);
+            return !last;
         }
     }
 
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
new file mode 100644
index 0000000..a99bdf5
--- /dev/null
+++ b/core/java/android/text/Hyphenator.java
@@ -0,0 +1,87 @@
+/*
+ * 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.text;
+
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.HashMap;
+import java.util.Locale;
+
+/**
+ * Hyphenator is a wrapper class for a native implementation of automatic hyphenation,
+ * in essence finding valid hyphenation opportunities in a word.
+ *
+ * @hide
+ */
+public class Hyphenator {
+    // This class has deliberately simple lifetime management (no finalizer) because in
+    // the common case a process will use a very small number of locales.
+
+    private static String TAG = "Hyphenator";
+
+    static HashMap<Locale, Hyphenator> sMap = new HashMap<Locale, Hyphenator>();
+
+    private long mNativePtr;
+
+    private Hyphenator(long nativePtr) {
+        mNativePtr = nativePtr;
+    }
+
+    public static long get(Locale locale) {
+        Hyphenator result = sMap.get(locale);
+        return result == null ? 0 : result.mNativePtr;
+    }
+
+    private static Hyphenator loadHyphenator(Locale locale) {
+        // TODO: find pattern dictionary (from system location) that best matches locale
+        if (Locale.US.equals(locale)) {
+            File f = new File(getSystemHyphenatorLocation(), "hyph-en-us.pat.txt");
+            try {
+                RandomAccessFile rf = new RandomAccessFile(f, "r");
+                byte[] buf = new byte[(int)rf.length()];
+                rf.read(buf);
+                rf.close();
+                String patternData = new String(buf);
+                long nativePtr = StaticLayout.nLoadHyphenator(patternData);
+                return new Hyphenator(nativePtr);
+            } catch (IOException e) {
+                Log.e(TAG, "error loading hyphenation " + f, e);
+            }
+        }
+        return null;
+    }
+
+    private static File getSystemHyphenatorLocation() {
+        // TODO: move to a sensible location under system
+        return new File("/system/usr/hyphen-data");
+    }
+
+    /**
+     * Load hyphenation patterns at initialization time. We want to have patterns
+     * for all locales loaded and ready to use so we don't have to do any file IO
+     * on the UI thread when drawing text in different locales.
+     *
+     * @hide
+     */
+    public static void init() {
+        Locale l = Locale.US;
+        sMap.put(l, loadHyphenator(l));
+    }
+}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index fcf1828..16ae5e2 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import android.annotation.IntDef;
 import android.emoji.EmojiFactory;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -33,6 +34,8 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 
 /**
@@ -43,6 +46,31 @@
  * For text that will not change, use a {@link StaticLayout}.
  */
 public abstract class Layout {
+    /** @hide */
+    @IntDef({BREAK_STRATEGY_SIMPLE, BREAK_STRATEGY_HIGH_QUALITY, BREAK_STRATEGY_BALANCED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BreakStrategy {}
+
+    /**
+     * Value for break strategy indicating simple line breaking. Automatic hyphens are not added
+     * (though soft hyphens are respected), and modifying text generally doesn't affect the layout
+     * before it (which yields a more consistent user experience when editing), but layout may not
+     * be the highest quality.
+     */
+    public static final int BREAK_STRATEGY_SIMPLE = 0;
+
+    /**
+     * Value for break strategy indicating high quality line breaking, including automatic
+     * hyphenation and doing whole-paragraph optimization of line breaks.
+     */
+    public static final int BREAK_STRATEGY_HIGH_QUALITY = 1;
+
+    /**
+     * Value for break strategy indicating balanced line breaking. The breaks are chosen to
+     * make all lines as close to the same length as possible, including automatic hyphenation.
+     */
+    public static final int BREAK_STRATEGY_BALANCED = 2;
+
     private static final ParagraphStyle[] NO_PARA_SPANS =
         ArrayUtils.emptyArray(ParagraphStyle.class);
 
@@ -225,17 +253,17 @@
 
         // Draw the lines, one at a time.
         // The baseline is the top of the following line minus the current line's descent.
-        for (int i = firstLine; i <= lastLine; i++) {
+        for (int lineNum = firstLine; lineNum <= lastLine; lineNum++) {
             int start = previousLineEnd;
-            previousLineEnd = getLineStart(i + 1);
-            int end = getLineVisibleEnd(i, start, previousLineEnd);
+            previousLineEnd = getLineStart(lineNum + 1);
+            int end = getLineVisibleEnd(lineNum, start, previousLineEnd);
 
             int ltop = previousLineBottom;
-            int lbottom = getLineTop(i+1);
+            int lbottom = getLineTop(lineNum + 1);
             previousLineBottom = lbottom;
-            int lbaseline = lbottom - getLineDescent(i);
+            int lbaseline = lbottom - getLineDescent(lineNum);
 
-            int dir = getParagraphDirection(i);
+            int dir = getParagraphDirection(lineNum);
             int left = 0;
             int right = mWidth;
 
@@ -254,7 +282,7 @@
                 // just collect the ones present at the start of the paragraph.
                 // If spanEnd is before the end of the paragraph, that's not
                 // our problem.
-                if (start >= spanEnd && (i == firstLine || isFirstParaLine)) {
+                if (start >= spanEnd && (lineNum == firstLine || isFirstParaLine)) {
                     spanEnd = sp.nextSpanTransition(start, textLength,
                                                     ParagraphStyle.class);
                     spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class);
@@ -280,7 +308,7 @@
                         int startLine = getLineForOffset(sp.getSpanStart(spans[n]));
                         // if there is more than one LeadingMarginSpan2, use
                         // the count that is greatest
-                        if (i < startLine + count) {
+                        if (lineNum < startLine + count) {
                             useFirstLineMargin = true;
                             break;
                         }
@@ -304,7 +332,7 @@
                 }
             }
 
-            boolean hasTabOrEmoji = getLineContainsTab(i);
+            boolean hasTabOrEmoji = getLineContainsTab(lineNum);
             // Can't tell if we have tabs for sure, currently
             if (hasTabOrEmoji && !tabStopsIsInitialized) {
                 if (tabStops == null) {
@@ -333,7 +361,7 @@
                     x = right;
                 }
             } else {
-                int max = (int)getLineExtent(i, tabStops, false);
+                int max = (int)getLineExtent(lineNum, tabStops, false);
                 if (align == Alignment.ALIGN_OPPOSITE) {
                     if (dir == DIR_LEFT_TO_RIGHT) {
                         x = right - max;
@@ -346,7 +374,8 @@
                 }
             }
 
-            Directions directions = getLineDirections(i);
+            paint.setHyphenEdit(getHyphen(lineNum));
+            Directions directions = getLineDirections(lineNum);
             if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTabOrEmoji) {
                 // XXX: assumes there's nothing additional to be done
                 canvas.drawText(buf, start, end, x, lbaseline, paint);
@@ -677,6 +706,15 @@
      */
     public abstract int getBottomPadding();
 
+    /**
+     * Returns the hyphen edit for a line.
+     *
+     * @hide
+     */
+    public int getHyphen(int line) {
+        return 0;
+    }
+
 
     /**
      * Returns true if the character at offset and the preceding character
@@ -1153,7 +1191,10 @@
                 return end - 1;
             }
 
-            if (ch != ' ' && ch != '\t') {
+            // Note: keep this in sync with Minikin LineBreaker::isLineEndSpace()
+            if (!(ch == ' ' || ch == '\t' || ch == 0x1680 ||
+                    (0x2000 <= ch && ch <= 0x200A && ch != 0x2007) ||
+                    ch == 0x205F || ch == 0x3000)) {
                 break;
             }
 
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index ee39e27..2bcb352 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -23,6 +23,7 @@
 import android.text.style.MetricAffectingSpan;
 import android.text.style.TabStopSpan;
 import android.util.Log;
+import android.util.Pools.SynchronizedPool;
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
@@ -56,28 +57,23 @@
             mNativePtr = nNewBuilder();
         }
 
-        static Builder obtain() {
-            Builder b = null;
-            synchronized (sLock) {
-                for (int i = 0; i < sCached.length; i++) {
-                    if (sCached[i] != null) {
-                        b = sCached[i];
-                        sCached[i] = null;
-                        break;
-                    }
-                }
-            }
+        public static Builder obtain(CharSequence source, int start, int end, int width) {
+            Builder b = sPool.acquire();
             if (b == null) {
                 b = new Builder();
             }
 
             // set default initial values
-            b.mWidth = 0;
+            b.mText = source;
+            b.mStart = start;
+            b.mEnd = end;
+            b.mWidth = width;
+            b.mAlignment = Alignment.ALIGN_NORMAL;
             b.mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR;
             b.mSpacingMult = 1.0f;
             b.mSpacingAdd = 0.0f;
             b.mIncludePad = true;
-            b.mEllipsizedWidth = 0;
+            b.mEllipsizedWidth = width;
             b.mEllipsize = null;
             b.mMaxLines = Integer.MAX_VALUE;
 
@@ -85,18 +81,11 @@
             return b;
         }
 
-        static void recycle(Builder b) {
+        private static void recycle(Builder b) {
             b.mPaint = null;
             b.mText = null;
             MeasuredText.recycle(b.mMeasuredText);
-            synchronized (sLock) {
-                for (int i = 0; i < sCached.length; i++) {
-                    if (sCached[i] == null) {
-                        sCached[i] = b;
-                        break;
-                    }
-                }
-            }
+            sPool.release(b);
         }
 
         // release any expensive state
@@ -129,6 +118,11 @@
             return this;
         }
 
+        public Builder setAlignment(Alignment alignment) {
+            mAlignment = alignment;
+            return this;
+        }
+
         public Builder setTextDir(TextDirectionHeuristic textDir) {
             mTextDir = textDir;
             return this;
@@ -166,12 +160,19 @@
             return this;
         }
 
+        public Builder setBreakStrategy(@BreakStrategy int breakStrategy) {
+            mBreakStrategy = breakStrategy;
+            return this;
+        }
+
         /**
          * Measurement and break iteration is done in native code. The protocol for using
          * the native code is as follows.
          *
-         * For each paragraph, do a nSetText of the paragraph text. Then, for each run within the
-         * paragraph:
+         * For each paragraph, do a nSetupParagraph, which sets paragraph text, line width, tab
+         * stops, break strategy (and possibly other parameters in the future).
+         *
+         * Then, for each run within the paragraph:
          *  - setLocale (this must be done at least for the first run, optional afterwards)
          *  - one of the following, depending on the type of run:
          *    + addStyleRun (a text run, to be measured in native code)
@@ -186,7 +187,7 @@
 
         private void setLocale(Locale locale) {
             if (!locale.equals(mLocale)) {
-                nSetLocale(mNativePtr, locale.toLanguageTag());
+                nSetLocale(mNativePtr, locale.toLanguageTag(), Hyphenator.get(locale));
                 mLocale = locale;
             }
         }
@@ -205,10 +206,8 @@
         }
 
         public StaticLayout build() {
-            // TODO: can optimize based on whether ellipsis is needed
-            StaticLayout result = new StaticLayout(mText);
-            result.generate(this, this.mIncludePad, this.mIncludePad);
-            recycle(this);
+            StaticLayout result = new StaticLayout(this);
+            Builder.recycle(this);
             return result;
         }
 
@@ -228,6 +227,7 @@
         int mEnd;
         TextPaint mPaint;
         int mWidth;
+        Alignment mAlignment;
         TextDirectionHeuristic mTextDir;
         float mSpacingMult;
         float mSpacingAdd;
@@ -235,6 +235,7 @@
         int mEllipsizedWidth;
         TextUtils.TruncateAt mEllipsize;
         int mMaxLines;
+        int mBreakStrategy;
 
         Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
 
@@ -243,8 +244,7 @@
 
         Locale mLocale;
 
-        private static final Object sLock = new Object();
-        private static final Builder[] sCached = new Builder[3];
+        private static final SynchronizedPool<Builder> sPool = new SynchronizedPool<Builder>(3);
     }
 
     public StaticLayout(CharSequence source, TextPaint paint,
@@ -314,10 +314,9 @@
                     : new Ellipsizer(source),
               paint, outerwidth, align, textDir, spacingmult, spacingadd);
 
-        Builder b = Builder.obtain();
-        b.setText(source, bufstart, bufend)
+        Builder b = Builder.obtain(source, bufstart, bufend, outerwidth)
             .setPaint(paint)
-            .setWidth(outerwidth)
+            .setAlignment(align)
             .setTextDir(textDir)
             .setSpacingMult(spacingmult)
             .setSpacingAdd(spacingadd)
@@ -364,6 +363,35 @@
         mLines = new int[mLineDirections.length];
     }
 
+    private StaticLayout(Builder b) {
+        super((b.mEllipsize == null)
+                ? b.mText
+                : (b.mText instanceof Spanned)
+                    ? new SpannedEllipsizer(b.mText)
+                    : new Ellipsizer(b.mText),
+                b.mPaint, b.mWidth, b.mAlignment, b.mSpacingMult, b.mSpacingAdd);
+
+        if (b.mEllipsize != null) {
+            Ellipsizer e = (Ellipsizer) getText();
+
+            e.mLayout = this;
+            e.mWidth = b.mEllipsizedWidth;
+            e.mMethod = b.mEllipsize;
+            mEllipsizedWidth = b.mEllipsizedWidth;
+
+            mColumns = COLUMNS_ELLIPSIZE;
+        } else {
+            mColumns = COLUMNS_NORMAL;
+            mEllipsizedWidth = b.mWidth;
+        }
+
+        mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, 2 * mColumns);
+        mLines = new int[mLineDirections.length];
+        mMaximumVisibleLineCount = b.mMaxLines;
+
+        generate(b, b.mIncludePad, b.mIncludePad);
+    }
+
     /* package */ void generate(Builder b, boolean includepad, boolean trackpad) {
         CharSequence source = b.mText;
         int bufStart = b.mStart;
@@ -459,7 +487,25 @@
             byte[] chdirs = measured.mLevels;
             int dir = measured.mDir;
             boolean easy = measured.mEasy;
-            nSetText(b.mNativePtr, chs, paraEnd - paraStart);
+
+            // tab stop locations
+            int[] variableTabStops = null;
+            if (spanned != null) {
+                TabStopSpan[] spans = getParagraphSpans(spanned, paraStart,
+                        paraEnd, TabStopSpan.class);
+                if (spans.length > 0) {
+                    int[] stops = new int[spans.length];
+                    for (int i = 0; i < spans.length; i++) {
+                        stops[i] = spans[i].getTabStop();
+                    }
+                    Arrays.sort(stops, 0, stops.length);
+                    variableTabStops = stops;
+                }
+            }
+
+            nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart,
+                    firstWidth, firstWidthLineCount, restWidth,
+                    variableTabStops, TAB_INCREMENT, b.mBreakStrategy);
 
             // measurement has to be done before performing line breaking
             // but we don't want to recompute fontmetrics or span ranges the
@@ -505,29 +551,13 @@
                 spanEndCacheCount++;
             }
 
-            // tab stop locations
-            int[] variableTabStops = null;
-            if (spanned != null) {
-                TabStopSpan[] spans = getParagraphSpans(spanned, paraStart,
-                        paraEnd, TabStopSpan.class);
-                if (spans.length > 0) {
-                    int[] stops = new int[spans.length];
-                    for (int i = 0; i < spans.length; i++) {
-                        stops[i] = spans[i].getTabStop();
-                    }
-                    Arrays.sort(stops, 0, stops.length);
-                    variableTabStops = stops;
-                }
-            }
-
             nGetWidths(b.mNativePtr, widths);
-            int breakCount = nComputeLineBreaks(b.mNativePtr, paraEnd - paraStart, firstWidth,
-                    firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, false, lineBreaks,
-                    lineBreaks.breaks, lineBreaks.widths, lineBreaks.flags, lineBreaks.breaks.length);
+            int breakCount = nComputeLineBreaks(b.mNativePtr, lineBreaks, lineBreaks.breaks,
+                    lineBreaks.widths, lineBreaks.flags, lineBreaks.breaks.length);
 
             int[] breaks = lineBreaks.breaks;
             float[] lineWidths = lineBreaks.widths;
-            boolean[] flags = lineBreaks.flags;
+            int[] flags = lineBreaks.flags;
 
             // here is the offset of the starting character of the line we are currently measuring
             int here = paraStart;
@@ -613,7 +643,7 @@
                     fm.top, fm.bottom,
                     v,
                     spacingmult, spacingadd, null,
-                    null, fm, false,
+                    null, fm, 0,
                     needMultiply, measured.mLevels, measured.mDir, measured.mEasy, bufEnd,
                     includepad, trackpad, null,
                     null, bufStart, ellipsize,
@@ -625,7 +655,7 @@
                       int above, int below, int top, int bottom, int v,
                       float spacingmult, float spacingadd,
                       LineHeightSpan[] chooseHt, int[] chooseHtv,
-                      Paint.FontMetricsInt fm, boolean hasTabOrEmoji,
+                      Paint.FontMetricsInt fm, int flags,
                       boolean needMultiply, byte[] chdirs, int dir,
                       boolean easy, int bufEnd, boolean includePad,
                       boolean trackPad, char[] chs,
@@ -718,8 +748,10 @@
         lines[off + mColumns + START] = end;
         lines[off + mColumns + TOP] = v;
 
-        if (hasTabOrEmoji)
-            lines[off + TAB] |= TAB_MASK;
+        // TODO: could move TAB to share same column as HYPHEN, simplifying this code and gaining
+        // one bit for start field
+        lines[off + TAB] |= flags & TAB_MASK;
+        lines[off + HYPHEN] = flags;
 
         lines[off + DIR] |= dir << DIR_SHIFT;
         Directions linedirs = DIRS_ALL_LEFT_TO_RIGHT;
@@ -938,6 +970,14 @@
         return mBottomPadding;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public int getHyphen(int line) {
+        return mLines[mColumns * line + HYPHEN] & 0xff;
+    }
+
     @Override
     public int getEllipsisCount(int line) {
         if (mColumns < COLUMNS_ELLIPSIZE) {
@@ -964,9 +1004,15 @@
     private static native long nNewBuilder();
     private static native void nFreeBuilder(long nativePtr);
     private static native void nFinishBuilder(long nativePtr);
-    private static native void nSetLocale(long nativePtr, String locale);
 
-    private static native void nSetText(long nativePtr, char[] text, int length);
+    /* package */ static native long nLoadHyphenator(String patternData);
+
+    private static native void nSetLocale(long nativePtr, String locale, long nativeHyphenator);
+
+    // Set up paragraph text and settings; done as one big method to minimize jni crossings
+    private static native void nSetupParagraph(long nativePtr, char[] text, int length,
+            float firstWidth, int firstWidthLineCount, float restWidth,
+            int[] variableTabStops, int defaultTabStop, int breakStrategy);
 
     private static native float nAddStyleRun(long nativePtr, long nativePaint,
             long nativeTypeface, int start, int end, boolean isRtl);
@@ -983,25 +1029,24 @@
     // the arrays inside the LineBreaks objects are passed in as well
     // to reduce the number of JNI calls in the common case where the
     // arrays do not have to be resized
-    private static native int nComputeLineBreaks(long nativePtr,
-            int length, float firstWidth, int firstWidthLineCount, float restWidth,
-            int[] variableTabStops, int defaultTabStop, boolean optimize, LineBreaks recycle,
-            int[] recycleBreaks, float[] recycleWidths, boolean[] recycleFlags, int recycleLength);
+    private static native int nComputeLineBreaks(long nativePtr, LineBreaks recycle,
+            int[] recycleBreaks, float[] recycleWidths, int[] recycleFlags, int recycleLength);
 
     private int mLineCount;
     private int mTopPadding, mBottomPadding;
     private int mColumns;
     private int mEllipsizedWidth;
 
-    private static final int COLUMNS_NORMAL = 3;
-    private static final int COLUMNS_ELLIPSIZE = 5;
+    private static final int COLUMNS_NORMAL = 4;
+    private static final int COLUMNS_ELLIPSIZE = 6;
     private static final int START = 0;
     private static final int DIR = START;
     private static final int TAB = START;
     private static final int TOP = 1;
     private static final int DESCENT = 2;
-    private static final int ELLIPSIS_START = 3;
-    private static final int ELLIPSIS_COUNT = 4;
+    private static final int HYPHEN = 3;
+    private static final int ELLIPSIS_START = 4;
+    private static final int ELLIPSIS_COUNT = 5;
 
     private int[] mLines;
     private Directions[] mLineDirections;
@@ -1023,7 +1068,7 @@
         private static final int INITIAL_SIZE = 16;
         public int[] breaks = new int[INITIAL_SIZE];
         public float[] widths = new float[INITIAL_SIZE];
-        public boolean[] flags = new boolean[INITIAL_SIZE]; // hasTabOrEmoji
+        public int[] flags = new int[INITIAL_SIZE]; // hasTabOrEmoji
         // breaks, widths, and flags should all have the same length
     }
 
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 4725581..479242c 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -955,6 +955,10 @@
                     span.updateDrawState(wp);
                 }
 
+                // Only draw hyphen on last run in line
+                if (jnext < mLen) {
+                    wp.setHyphenEdit(0);
+                }
                 x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x,
                         top, y, bottom, fmi, needWidth || jnext < measureLimit);
             }
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index 0c66709..d567d90 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -47,6 +47,7 @@
  *     before 1st Jan 1970 UTC).</li>
  *     <li>Much of the formatting / parsing assumes ASCII text and is therefore not suitable for
  *     use with non-ASCII scripts.</li>
+ *     <li>No support for pseudo-zones like "GMT-07:00".</li>
  * </ul>
  *
  * @deprecated Use {@link java.util.GregorianCalendar} instead.
diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java
index d29bfb6..0669b6f 100644
--- a/core/java/android/text/style/URLSpan.java
+++ b/core/java/android/text/style/URLSpan.java
@@ -16,6 +16,7 @@
 
 package android.text.style;
 
+import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
@@ -23,6 +24,7 @@
 import android.provider.Browser;
 import android.text.ParcelableSpan;
 import android.text.TextUtils;
+import android.util.Log;
 import android.view.View;
 
 public class URLSpan extends ClickableSpan implements ParcelableSpan {
@@ -59,6 +61,10 @@
         Context context = widget.getContext();
         Intent intent = new Intent(Intent.ACTION_VIEW, uri);
         intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
-        context.startActivity(intent);
+        try {
+            context.startActivity(intent);
+        } catch (ActivityNotFoundException e) {
+            Log.w("URLSpan", "Actvity was not found for intent, " + intent.toString());
+        }
     }
 }
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java
index e7857c0..287c696 100644
--- a/core/java/android/transition/Fade.java
+++ b/core/java/android/transition/Fade.java
@@ -108,7 +108,7 @@
     /**
      * Utility method to handle creating and running the Animator.
      */
-    private Animator createAnimation(View view, float startAlpha, float endAlpha) {
+    private Animator createAnimation(final View view, float startAlpha, final float endAlpha) {
         if (startAlpha == endAlpha) {
             return null;
         }
@@ -117,9 +117,15 @@
         if (DBG) {
             Log.d(LOG_TAG, "Created animator " + anim);
         }
-        FadeAnimatorListener listener = new FadeAnimatorListener(view);
+        final FadeAnimatorListener listener = new FadeAnimatorListener(view);
         anim.addListener(listener);
         anim.addPauseListener(listener);
+        addListener(new TransitionListenerAdapter() {
+            @Override
+            public void onTransitionEnd(Transition transition) {
+                view.setTransitionAlpha(1);
+            }
+        });
         return anim;
     }
 
@@ -143,7 +149,6 @@
 
     private static class FadeAnimatorListener extends AnimatorListenerAdapter {
         private final View mView;
-        private boolean mCanceled = false;
         private float mPausedAlpha = -1;
         private boolean mLayerTypeChanged = false;
 
@@ -160,18 +165,8 @@
         }
 
         @Override
-        public void onAnimationCancel(Animator animator) {
-            mCanceled = true;
-            if (mPausedAlpha >= 0) {
-                mView.setTransitionAlpha(mPausedAlpha);
-            }
-        }
-
-        @Override
         public void onAnimationEnd(Animator animator) {
-            if (!mCanceled) {
-                mView.setTransitionAlpha(1);
-            }
+            mView.setTransitionAlpha(1);
             if (mLayerTypeChanged) {
                 mView.setLayerType(View.LAYER_TYPE_NONE, null);
             }
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
index 84d9ce8..c44f42b 100644
--- a/core/java/android/util/DebugUtils.java
+++ b/core/java/android/util/DebugUtils.java
@@ -17,8 +17,10 @@
 package android.util;
 
 import java.io.PrintWriter;
-import java.lang.reflect.Method;
+import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.Locale;
 
 /**
@@ -203,4 +205,57 @@
         outBuilder.append(suffix);
         return outBuilder.toString();
     }
+
+    /**
+     * Use prefixed constants (static final values) on given class to turn value
+     * into human-readable string.
+     *
+     * @hide
+     */
+    public static String valueToString(Class<?> clazz, String prefix, int value) {
+        for (Field field : clazz.getDeclaredFields()) {
+            final int modifiers = field.getModifiers();
+            if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)
+                    && field.getType().equals(int.class) && field.getName().startsWith(prefix)) {
+                try {
+                    if (value == field.getInt(null)) {
+                        return field.getName().substring(prefix.length());
+                    }
+                } catch (IllegalAccessException ignored) {
+                }
+            }
+        }
+        return Integer.toString(value);
+    }
+
+    /**
+     * Use prefixed constants (static final values) on given class to turn flags
+     * into human-readable string.
+     *
+     * @hide
+     */
+    public static String flagsToString(Class<?> clazz, String prefix, int flags) {
+        final StringBuilder res = new StringBuilder();
+
+        for (Field field : clazz.getDeclaredFields()) {
+            final int modifiers = field.getModifiers();
+            if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)
+                    && field.getType().equals(int.class) && field.getName().startsWith(prefix)) {
+                try {
+                    final int value = field.getInt(null);
+                    if ((flags & value) != 0) {
+                        flags &= ~value;
+                        res.append(field.getName().substring(prefix.length())).append('|');
+                    }
+                } catch (IllegalAccessException ignored) {
+                }
+            }
+        }
+        if (flags != 0 || res.length() == 0) {
+            res.append(Integer.toHexString(flags));
+        } else {
+            res.deleteCharAt(res.length() - 1);
+        }
+        return res.toString();
+    }
 }
diff --git a/core/java/android/util/IntArray.java b/core/java/android/util/IntArray.java
index e8d3947..9326203 100644
--- a/core/java/android/util/IntArray.java
+++ b/core/java/android/util/IntArray.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.util.ArrayUtils;
 
+import java.util.Arrays;
 import libcore.util.EmptyArray;
 
 /**
@@ -78,6 +79,24 @@
     }
 
     /**
+     * Searches the array for the specified value using the binary search algorithm. The array must
+     * be sorted (as by the {@link Arrays#sort(int[], int, int)} method) prior to making this call.
+     * If it is not sorted, the results are undefined. If the range contains multiple elements with
+     * the specified value, there is no guarantee which one will be found.
+     *
+     * @param value The value to search for.
+     * @return index of the search key, if it is contained in the array; otherwise, <i>(-(insertion
+     *         point) - 1)</i>. The insertion point is defined as the point at which the key would
+     *         be inserted into the array: the index of the first element greater than the key, or
+     *         {@link #size()} if all elements in the array are less than the specified key.
+     *         Note that this guarantees that the return value will be >= 0 if and only if the key
+     *         is found.
+     */
+    public int binarySearch(int value) {
+        return ContainerHelpers.binarySearch(mValues, mSize, value);
+    }
+
+    /**
      * Adds the values in the specified array to this array.
      */
     public void addAll(IntArray values) {
@@ -159,4 +178,11 @@
     public int size() {
         return mSize;
     }
+
+    /**
+     * Returns a new array with the contents of this IntArray.
+     */
+    public int[] toArray() {
+        return Arrays.copyOf(mValues, mSize);
+    }
 }
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index 36d5b50..8b57d3d 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -20,7 +20,7 @@
 
 /**
  * A class that contains utility methods related to numbers.
- * 
+ *
  * @hide Pending API council approval
  */
 public final class MathUtils {
@@ -32,7 +32,7 @@
     }
 
     public static float abs(float v) {
-        return v > 0 ? v : -v; 
+        return v > 0 ? v : -v;
     }
 
     public static int constrain(int amount, int low, int high) {
@@ -116,6 +116,14 @@
         return v * v;
     }
 
+    public static float dot(float v1x, float v1y, float v2x, float v2y) {
+        return v1x * v2x + v1y * v2y;
+    }
+
+    public static float cross(float v1x, float v1y, float v2x, float v2y) {
+        return v1x * v2y - v1y * v2x;
+    }
+
     public static float radians(float degrees) {
         return degrees * DEG_TO_RAD;
     }
@@ -142,16 +150,16 @@
 
     public static float tan(float angle) {
         return (float) Math.tan(angle);
-    }    
+    }
 
     public static float lerp(float start, float stop, float amount) {
         return start + (stop - start) * amount;
     }
-    
+
     public static float norm(float start, float stop, float value) {
         return (value - start) / (stop - start);
     }
-    
+
     public static float map(float minStart, float minStop, float maxStart, float maxStop, float value) {
         return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
     }
@@ -164,7 +172,7 @@
         if (howsmall >= howbig) return howsmall;
         return (int) (sRandom.nextFloat() * (howbig - howsmall) + howsmall);
     }
-    
+
     public static float random(float howbig) {
         return sRandom.nextFloat() * howbig;
     }
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 3caf6f0..ec8f802 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -48,7 +48,6 @@
     private int mWidth;
     private int mHeight;
 
-
     static DisplayListCanvas obtain(@NonNull RenderNode node) {
         if (node == null) throw new IllegalArgumentException("node cannot be null");
         DisplayListCanvas canvas = sPool.acquire();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/core/java/android/view/IGraphicsStats.aidl
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to core/java/android/view/IGraphicsStats.aidl
index 272c321..c235eb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/core/java/android/view/IGraphicsStats.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
+/**
+ * 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
+ *     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,
@@ -14,8 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+package android.view;
 
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
+import android.os.ParcelFileDescriptor;
+
+/**
+ * @hide
+ */
+interface IGraphicsStats {
+    ParcelFileDescriptor requestBufferForProcess(String packageName, IBinder token);
 }
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index ef98bbc..236cfef 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -240,12 +240,7 @@
      * @see #start(int, int)
      * @see #isValid()
      */
-    public void end(DisplayListCanvas endCanvas) {
-        if (!(endCanvas instanceof DisplayListCanvas)) {
-            throw new IllegalArgumentException("Passed an invalid canvas to end!");
-        }
-
-        DisplayListCanvas canvas = (DisplayListCanvas) endCanvas;
+    public void end(DisplayListCanvas canvas) {
         canvas.onPostDraw();
         long renderNodeData = canvas.finishRecording();
         nSetDisplayListData(mNativeRenderNode, renderNodeData);
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 6508cca..5cf2c5c 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -130,6 +130,7 @@
     private float mFocusY;
 
     private boolean mQuickScaleEnabled;
+    private boolean mButtonScaleEnabled;
 
     private float mCurrSpan;
     private float mPrevSpan;
@@ -151,14 +152,17 @@
     private int mTouchHistoryDirection;
     private long mTouchHistoryLastAcceptedTime;
     private int mTouchMinMajor;
-    private MotionEvent mDoubleTapEvent;
-    private int mDoubleTapMode = DOUBLE_TAP_MODE_NONE;
     private final Handler mHandler;
 
+    private float mAnchoredScaleStartX;
+    private float mAnchoredScaleStartY;
+    private int mAnchoredScaleMode = ANCHORED_SCALE_MODE_NONE;
+
     private static final long TOUCH_STABILIZE_TIME = 128; // ms
-    private static final int DOUBLE_TAP_MODE_NONE = 0;
-    private static final int DOUBLE_TAP_MODE_IN_PROGRESS = 1;
     private static final float SCALE_FACTOR = .5f;
+    private static final int ANCHORED_SCALE_MODE_NONE = 0;
+    private static final int ANCHORED_SCALE_MODE_DOUBLE_TAP = 1;
+    private static final int ANCHORED_SCALE_MODE_BUTTON = 2;
 
 
     /**
@@ -310,8 +314,17 @@
             mGestureDetector.onTouchEvent(event);
         }
 
+        final int count = event.getPointerCount();
+        final int toolType = event.getToolType(0);
+        final boolean isButtonTool = toolType == MotionEvent.TOOL_TYPE_STYLUS
+                || toolType == MotionEvent.TOOL_TYPE_MOUSE;
+        final boolean isAnchoredScaleButtonDown = isButtonTool && (count == 1)
+                && (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0;
+
+        final boolean anchoredScaleCancelled =
+                mAnchoredScaleMode == ANCHORED_SCALE_MODE_BUTTON && !isAnchoredScaleButtonDown;
         final boolean streamComplete = action == MotionEvent.ACTION_UP ||
-                action == MotionEvent.ACTION_CANCEL;
+                action == MotionEvent.ACTION_CANCEL || anchoredScaleCancelled;
 
         if (action == MotionEvent.ACTION_DOWN || streamComplete) {
             // Reset any scale in progress with the listener.
@@ -321,11 +334,11 @@
                 mListener.onScaleEnd(this);
                 mInProgress = false;
                 mInitialSpan = 0;
-                mDoubleTapMode = DOUBLE_TAP_MODE_NONE;
-            } else if (mDoubleTapMode == DOUBLE_TAP_MODE_IN_PROGRESS && streamComplete) {
+                mAnchoredScaleMode = ANCHORED_SCALE_MODE_NONE;
+            } else if (inAnchoredScaleMode() && streamComplete) {
                 mInProgress = false;
                 mInitialSpan = 0;
-                mDoubleTapMode = DOUBLE_TAP_MODE_NONE;
+                mAnchoredScaleMode = ANCHORED_SCALE_MODE_NONE;
             }
 
             if (streamComplete) {
@@ -334,25 +347,32 @@
             }
         }
 
+        if (!mInProgress && mButtonScaleEnabled && !inAnchoredScaleMode()
+                && !streamComplete && isAnchoredScaleButtonDown) {
+            // Start of a button scale gesture
+            mAnchoredScaleStartX = event.getX();
+            mAnchoredScaleStartY = event.getY();
+            mAnchoredScaleMode = ANCHORED_SCALE_MODE_BUTTON;
+            mInitialSpan = 0;
+        }
+
         final boolean configChanged = action == MotionEvent.ACTION_DOWN ||
                 action == MotionEvent.ACTION_POINTER_UP ||
-                action == MotionEvent.ACTION_POINTER_DOWN;
-
+                action == MotionEvent.ACTION_POINTER_DOWN || anchoredScaleCancelled;
 
         final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP;
         final int skipIndex = pointerUp ? event.getActionIndex() : -1;
 
         // Determine focal point
         float sumX = 0, sumY = 0;
-        final int count = event.getPointerCount();
         final int div = pointerUp ? count - 1 : count;
         final float focusX;
         final float focusY;
-        if (mDoubleTapMode == DOUBLE_TAP_MODE_IN_PROGRESS) {
-            // In double tap mode, the focal pt is always where the double tap
-            // gesture started
-            focusX = mDoubleTapEvent.getX();
-            focusY = mDoubleTapEvent.getY();
+        if (inAnchoredScaleMode()) {
+            // In anchored scale mode, the focal pt is always where the double tap
+            // or button down gesture started
+            focusX = mAnchoredScaleStartX;
+            focusY = mAnchoredScaleStartY;
             if (event.getY() < focusY) {
                 mEventBeforeOrAboveStartingGestureEvent = true;
             } else {
@@ -390,7 +410,7 @@
         final float spanX = devX * 2;
         final float spanY = devY * 2;
         final float span;
-        if (inDoubleTapMode()) {
+        if (inAnchoredScaleMode()) {
             span = spanY;
         } else {
             span = (float) Math.hypot(spanX, spanY);
@@ -402,11 +422,10 @@
         final boolean wasInProgress = mInProgress;
         mFocusX = focusX;
         mFocusY = focusY;
-        if (!inDoubleTapMode() && mInProgress && (span < mMinSpan || configChanged)) {
+        if (!inAnchoredScaleMode() && mInProgress && (span < mMinSpan || configChanged)) {
             mListener.onScaleEnd(this);
             mInProgress = false;
             mInitialSpan = span;
-            mDoubleTapMode = DOUBLE_TAP_MODE_NONE;
         }
         if (configChanged) {
             mPrevSpanX = mCurrSpanX = spanX;
@@ -414,7 +433,7 @@
             mInitialSpan = mPrevSpan = mCurrSpan = span;
         }
 
-        final int minSpan = inDoubleTapMode() ? mSpanSlop : mMinSpan;
+        final int minSpan = inAnchoredScaleMode() ? mSpanSlop : mMinSpan;
         if (!mInProgress && span >=  minSpan &&
                 (wasInProgress || Math.abs(span - mInitialSpan) > mSpanSlop)) {
             mPrevSpanX = mCurrSpanX = spanX;
@@ -447,9 +466,8 @@
         return true;
     }
 
-
-    private boolean inDoubleTapMode() {
-        return mDoubleTapMode == DOUBLE_TAP_MODE_IN_PROGRESS;
+    private boolean inAnchoredScaleMode() {
+        return mAnchoredScaleMode != ANCHORED_SCALE_MODE_NONE;
     }
 
     /**
@@ -466,8 +484,9 @@
                         @Override
                         public boolean onDoubleTap(MotionEvent e) {
                             // Double tap: start watching for a swipe
-                            mDoubleTapEvent = e;
-                            mDoubleTapMode = DOUBLE_TAP_MODE_IN_PROGRESS;
+                            mAnchoredScaleStartX = e.getX();
+                            mAnchoredScaleStartY = e.getY();
+                            mAnchoredScaleMode = ANCHORED_SCALE_MODE_DOUBLE_TAP;
                             return true;
                         }
                     };
@@ -484,6 +503,27 @@
     }
 
     /**
+     * Sets whether the associates {@link OnScaleGestureListener} should receive onScale callbacks
+     * when the user presses a {@value MotionEvent#BUTTON_SECONDARY} (right mouse button, stylus
+     * first button) and drags the pointer on the screen. Note that this is enabled by default if
+     * the app targets API 23 and newer.
+     *
+     * @param scales true to enable stylus or mouse scaling, false to disable.
+     */
+    public void setSecondaryButtonScaleEnabled(boolean scales) {
+        mButtonScaleEnabled = scales;
+    }
+
+    /**
+     * Return whether the button scale gesture, in which the user presses a
+     * {@value MotionEvent#BUTTON_SECONDARY} (right mouse button, stylus first button) and drags the
+     * pointer on the screen, should perform scaling. {@see #setButtonScaleEnabled(boolean)}.
+     */
+    public boolean isSecondaryButtonScaleEnabled() {
+        return mButtonScaleEnabled;
+    }
+
+    /**
      * Returns {@code true} if a scale gesture is in progress.
      */
     public boolean isInProgress() {
@@ -586,7 +626,7 @@
      * @return The current scaling factor.
      */
     public float getScaleFactor() {
-        if (inDoubleTapMode()) {
+        if (inAnchoredScaleMode()) {
             // Drag is moving up; the further away from the gesture
             // start, the smaller the span should be, the closer,
             // the larger the span, and therefore the larger the scale
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 59ec058..ad34f02 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -723,6 +723,12 @@
             mSurface.release();
         }
         mSurface = surfaceTexture;
+
+        // If the view is visible, update the listener in the new surface to use
+        // the existing listener in the view.
+        if (((mViewFlags & VISIBILITY_MASK) == VISIBLE)) {
+            mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
+        }
         mUpdateSurface = true;
         invalidateParentIfNeeded();
     }
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 031be07..87d5d9a 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -23,7 +23,9 @@
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.os.Binder;
 import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.Trace;
@@ -124,7 +126,7 @@
         mRootNode.setClipToBounds(false);
         mNativeProxy = nCreateProxy(translucent, rootNodePtr);
 
-        AtlasInitializer.sInstance.init(context, mNativeProxy);
+        ProcessInitializer.sInstance.init(context, mNativeProxy);
 
         loadSystemProperties();
     }
@@ -410,15 +412,44 @@
         nTrimMemory(level);
     }
 
-    private static class AtlasInitializer {
-        static AtlasInitializer sInstance = new AtlasInitializer();
+    public static void dumpProfileData(byte[] data, FileDescriptor fd) {
+        nDumpProfileData(data, fd);
+    }
+
+    private static class ProcessInitializer {
+        static ProcessInitializer sInstance = new ProcessInitializer();
+        static IGraphicsStats sGraphicsStatsService;
+        private static IBinder sProcToken;
 
         private boolean mInitialized = false;
 
-        private AtlasInitializer() {}
+        private ProcessInitializer() {}
 
         synchronized void init(Context context, long renderProxy) {
             if (mInitialized) return;
+            mInitialized = true;
+            initGraphicsStats(context, renderProxy);
+            initAssetAtlas(context, renderProxy);
+        }
+
+        private static void initGraphicsStats(Context context, long renderProxy) {
+            IBinder binder = ServiceManager.getService("graphicsstats");
+            if (binder == null) return;
+
+            sGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
+            sProcToken = new Binder();
+            try {
+                final String pkg = context.getApplicationInfo().packageName;
+                ParcelFileDescriptor pfd = sGraphicsStatsService.
+                        requestBufferForProcess(pkg, sProcToken);
+                nSetProcessStatsBuffer(renderProxy, pfd.getFd());
+                pfd.close();
+            } catch (Exception e) {
+                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", e);
+            }
+        }
+
+        private static void initAssetAtlas(Context context, long renderProxy) {
             IBinder binder = ServiceManager.getService("assetatlas");
             if (binder == null) return;
 
@@ -432,7 +463,6 @@
                             // TODO Remove after fixing b/15425820
                             validateMap(context, map);
                             nSetAtlas(renderProxy, buffer, map);
-                            mInitialized = true;
                         }
                         // If IAssetAtlas is not the same class as the IBinder
                         // we are using a remote service and we can safely
@@ -477,6 +507,7 @@
     static native void setupShadersDiskCache(String cacheFile);
 
     private static native void nSetAtlas(long nativeProxy, GraphicBuffer buffer, long[] map);
+    private static native void nSetProcessStatsBuffer(long nativeProxy, int fd);
 
     private static native long nCreateRootRenderNode();
     private static native long nCreateProxy(boolean translucent, long rootRenderNode);
@@ -514,4 +545,5 @@
 
     private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
             @DumpFlags int dumpFlags);
+    private static native void nDumpProfileData(byte[] data, FileDescriptor fd);
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f5de8e3..b6f1e3b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -83,6 +83,7 @@
 import android.view.accessibility.AccessibilityEventSource;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -90,6 +91,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.Checkable;
 import android.widget.ScrollBarDrawable;
 
 import static android.os.Build.VERSION_CODES.*;
@@ -3168,6 +3170,9 @@
     private Drawable mBackground;
     private TintInfo mBackgroundTint;
 
+    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
+    private ForegroundInfo mForegroundInfo;
+
     /**
      * RenderNode used for backgrounds.
      * <p>
@@ -3182,13 +3187,23 @@
 
     private String mTransitionName;
 
-    private static class TintInfo {
+    static class TintInfo {
         ColorStateList mTintList;
         PorterDuff.Mode mTintMode;
         boolean mHasTintMode;
         boolean mHasTintList;
     }
 
+    private static class ForegroundInfo {
+        private Drawable mDrawable;
+        private TintInfo mTintInfo;
+        private int mGravity = Gravity.FILL;
+        private boolean mInsidePadding = true;
+        private boolean mBoundsChanged = true;
+        private final Rect mSelfBounds = new Rect();
+        private final Rect mOverlayBounds = new Rect();
+    }
+
     static class ListenerInfo {
         /**
          * Listener used to dispatch focus change events.
@@ -3568,6 +3583,8 @@
             // of whether a layout was requested on that View.
             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
 
+            Canvas.sCompatibilityRestore = targetSdkVersion < MNC;
+
             sCompatibilityDone = true;
         }
     }
@@ -4056,6 +4073,25 @@
                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
                             PROVIDER_BACKGROUND));
                     break;
+                case R.styleable.View_foreground:
+                    setForeground(a.getDrawable(attr));
+                    break;
+                case R.styleable.View_foregroundGravity:
+                    setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
+                    break;
+                case R.styleable.View_foregroundTintMode:
+                    setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
+                    break;
+                case R.styleable.View_foregroundTint:
+                    setForegroundTintList(a.getColorStateList(attr));
+                    break;
+                case R.styleable.View_foregroundInsidePadding:
+                    if (mForegroundInfo == null) {
+                        mForegroundInfo = new ForegroundInfo();
+                    }
+                    mForegroundInfo.mInsidePadding = a.getBoolean(attr,
+                            mForegroundInfo.mInsidePadding);
+                    break;
             }
         }
 
@@ -4813,10 +4849,11 @@
      * @hide
      */
     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
-        if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
-            if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
-                return true;
-            }
+        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
+            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
+            showContextMenu(event.getX(), event.getY(), event.getMetaState());
+            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
+            return true;
         }
         return false;
     }
@@ -5642,10 +5679,143 @@
     /**
      * Called when assist structure is being retrieved from a view as part of
      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
-     * @param structure Additional standard structured view structure to supply.
-     * @param extras Non-standard extensions.
+     * @param structure Fill in with structured view data.  The default implementation
+     * fills in all data that can be inferred from the view itself.
      */
-    public void onProvideAssistStructure(ViewAssistStructure structure, Bundle extras) {
+    public void onProvideAssistStructure(ViewAssistStructure structure) {
+        final int id = mID;
+        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
+                && (id&0x0000ffff) != 0) {
+            String pkg, type, entry;
+            try {
+                final Resources res = getResources();
+                entry = res.getResourceEntryName(id);
+                type = res.getResourceTypeName(id);
+                pkg = res.getResourcePackageName(id);
+            } catch (Resources.NotFoundException e) {
+                entry = type = pkg = null;
+            }
+            structure.setId(id, pkg, type, entry);
+        } else {
+            structure.setId(id, null, null, null);
+        }
+        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight-mLeft, mBottom-mTop);
+        structure.setVisibility(getVisibility());
+        structure.setEnabled(isEnabled());
+        if (isClickable()) {
+            structure.setClickable(true);
+        }
+        if (isFocusable()) {
+            structure.setFocusable(true);
+        }
+        if (isFocused()) {
+            structure.setFocused(true);
+        }
+        if (isAccessibilityFocused()) {
+            structure.setAccessibilityFocused(true);
+        }
+        if (isSelected()) {
+            structure.setSelected(true);
+        }
+        if (isActivated()) {
+            structure.setActivated(true);
+        }
+        if (isLongClickable()) {
+            structure.setLongClickable(true);
+        }
+        if (this instanceof Checkable) {
+            structure.setCheckable(true);
+            if (((Checkable)this).isChecked()) {
+                structure.setChecked(true);
+            }
+        }
+        structure.setClassName(getAccessibilityClassName().toString());
+        structure.setContentDescription(getContentDescription());
+    }
+
+    /**
+     * Called when assist structure is being retrieved from a view as part of
+     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
+     * generate additional virtual structure under this view.  The defaullt implementation
+     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
+     * view's virtual accessibility nodes, if any.  You can override this for a more
+     * optimal implementation providing this data.
+     */
+    public void onProvideVirtualAssistStructure(ViewAssistStructure structure) {
+        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
+        if (provider != null) {
+            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
+            Log.i("View", "Provider of " + this + ": children=" + info.getChildCount());
+            structure.setChildCount(1);
+            ViewAssistStructure root = structure.newChild(0);
+            populateVirtualAssistStructure(root, provider, info);
+            info.recycle();
+        }
+    }
+
+    private void populateVirtualAssistStructure(ViewAssistStructure structure,
+            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
+        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
+                null, null, null);
+        Rect rect = structure.getTempRect();
+        info.getBoundsInParent(rect);
+        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
+        structure.setVisibility(VISIBLE);
+        structure.setEnabled(info.isEnabled());
+        if (info.isClickable()) {
+            structure.setClickable(true);
+        }
+        if (info.isFocusable()) {
+            structure.setFocusable(true);
+        }
+        if (info.isFocused()) {
+            structure.setFocused(true);
+        }
+        if (info.isAccessibilityFocused()) {
+            structure.setAccessibilityFocused(true);
+        }
+        if (info.isSelected()) {
+            structure.setSelected(true);
+        }
+        if (info.isLongClickable()) {
+            structure.setLongClickable(true);
+        }
+        if (info.isCheckable()) {
+            structure.setCheckable(true);
+            if (info.isChecked()) {
+                structure.setChecked(true);
+            }
+        }
+        CharSequence cname = info.getClassName();
+        structure.setClassName(cname != null ? cname.toString() : null);
+        structure.setContentDescription(info.getContentDescription());
+        Log.i("View", "vassist " + cname + " @ " + rect.toShortString()
+                + " text=" + info.getText() + " cd=" + info.getContentDescription());
+        if (info.getText() != null || info.getError() != null) {
+            structure.setText(info.getText(), info.getTextSelectionStart(),
+                    info.getTextSelectionEnd());
+        }
+        final int NCHILDREN = info.getChildCount();
+        if (NCHILDREN > 0) {
+            structure.setChildCount(NCHILDREN);
+            for (int i=0; i<NCHILDREN; i++) {
+                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
+                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
+                ViewAssistStructure child = structure.newChild(i);
+                populateVirtualAssistStructure(child, provider, cinfo);
+                cinfo.recycle();
+            }
+        }
+    }
+
+    /**
+     * Dispatch creation of {@link ViewAssistStructure} down the hierarchy.  The default
+     * implementation calls {@link #onProvideAssistStructure} and
+     * {@link #onProvideVirtualAssistStructure}.
+     */
+    public void dispatchProvideAssistStructure(ViewAssistStructure structure) {
+        onProvideAssistStructure(structure);
+        onProvideVirtualAssistStructure(structure);
     }
 
     /**
@@ -5781,6 +5951,8 @@
                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
         }
+
+        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
     }
 
     private View findLabelForView(View view, int labeledId) {
@@ -8228,6 +8400,13 @@
                     return true;
                 }
             } break;
+            case R.id.accessibilityActionShowOnScreen: {
+                if (mAttachInfo != null) {
+                    final Rect r = mAttachInfo.mTmpInvalRect;
+                    getDrawingRect(r);
+                    return requestRectangleOnScreen(r, true);
+                }
+            } break;
         }
         return false;
     }
@@ -8801,6 +8980,10 @@
         if (dr != null && visible != dr.isVisible()) {
             dr.setVisible(visible, false);
         }
+        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+        if (fg != null && visible != fg.isVisible()) {
+            fg.setVisible(visible, false);
+        }
     }
 
     /**
@@ -9912,11 +10095,16 @@
      * @param oldt Previous vertical scroll origin.
      */
     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+        notifySubtreeAccessibilityStateChangedIfNeeded();
+
         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
             postSendViewScrolledAccessibilityEventCallback();
         }
 
         mBackgroundSizeChanged = true;
+        if (mForegroundInfo != null) {
+            mForegroundInfo.mBoundsChanged = true;
+        }
 
         final AttachInfo ai = mAttachInfo;
         if (ai != null) {
@@ -10755,6 +10943,9 @@
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
+            if (mForegroundInfo != null) {
+                mForegroundInfo.mBoundsChanged = true;
+            }
             invalidateParentIfNeeded();
             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
@@ -10820,6 +11011,9 @@
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
+            if (mForegroundInfo != null) {
+                mForegroundInfo.mBoundsChanged = true;
+            }
             invalidateParentIfNeeded();
             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
@@ -10879,6 +11073,9 @@
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
+            if (mForegroundInfo != null) {
+                mForegroundInfo.mBoundsChanged = true;
+            }
             invalidateParentIfNeeded();
             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
@@ -10935,6 +11132,9 @@
                 invalidate(true);
             }
             mBackgroundSizeChanged = true;
+            if (mForegroundInfo != null) {
+                mForegroundInfo.mBoundsChanged = true;
+            }
             invalidateParentIfNeeded();
             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
                 // View was rejected last time it was drawn by its parent; this may have changed
@@ -11100,6 +11300,7 @@
             invalidateViewProperty(false, true);
 
             invalidateParentIfNeededAndWasQuickRejected();
+            notifySubtreeAccessibilityStateChangedIfNeeded();
         }
     }
 
@@ -15313,13 +15514,14 @@
             // Step 4, draw the children
             dispatchDraw(canvas);
 
-            // Step 6, draw decorations (scrollbars)
-            onDrawScrollBars(canvas);
-
+            // Overlay is part of the content and draws beneath Foreground
             if (mOverlay != null && !mOverlay.isEmpty()) {
                 mOverlay.getOverlayView().dispatchDraw(canvas);
             }
 
+            // Step 6, draw decorations (foreground, scrollbars)
+            onDrawForeground(canvas);
+
             // we're done...
             return;
         }
@@ -15461,12 +15663,13 @@
 
         canvas.restoreToCount(saveCount);
 
-        // Step 6, draw decorations (scrollbars)
-        onDrawScrollBars(canvas);
-
+        // Overlay is part of the content and draws beneath Foreground
         if (mOverlay != null && !mOverlay.isEmpty()) {
             mOverlay.getOverlayView().dispatchDraw(canvas);
         }
+
+        // Step 6, draw decorations (foreground, scrollbars)
+        onDrawForeground(canvas);
     }
 
     /**
@@ -15849,6 +16052,9 @@
             mPrivateFlags |= drawn;
 
             mBackgroundSizeChanged = true;
+            if (mForegroundInfo != null) {
+                mForegroundInfo.mBoundsChanged = true;
+            }
 
             notifySubtreeAccessibilityStateChangedIfNeeded();
         }
@@ -15992,6 +16198,9 @@
         if (mBackground != null) {
             mBackground.setLayoutDirection(layoutDirection);
         }
+        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
+            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
+        }
         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
         onResolveDrawables(layoutDirection);
     }
@@ -16047,7 +16256,8 @@
      */
     @CallSuper
     protected boolean verifyDrawable(Drawable who) {
-        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who);
+        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
+                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
     }
 
     /**
@@ -16065,9 +16275,14 @@
     protected void drawableStateChanged() {
         final int[] state = getDrawableState();
 
-        final Drawable d = mBackground;
-        if (d != null && d.isStateful()) {
-            d.setState(state);
+        final Drawable bg = mBackground;
+        if (bg != null && bg.isStateful()) {
+            bg.setState(state);
+        }
+
+        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+        if (fg != null && fg.isStateful()) {
+            fg.setState(state);
         }
 
         if (mScrollCache != null) {
@@ -16099,6 +16314,9 @@
         if (mBackground != null) {
             mBackground.setHotspot(x, y);
         }
+        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
+            mForegroundInfo.mDrawable.setHotspot(x, y);
+        }
 
         dispatchDrawableHotspotChanged(x, y);
     }
@@ -16270,6 +16488,9 @@
         if (mStateListAnimator != null) {
             mStateListAnimator.jumpToCurrentState();
         }
+        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
+            mForegroundInfo.mDrawable.jumpToCurrentState();
+        }
     }
 
     /**
@@ -16554,6 +16775,249 @@
     }
 
     /**
+     * Returns the drawable used as the foreground of this View. The
+     * foreground drawable, if non-null, is always drawn on top of the view's content.
+     *
+     * @return a Drawable or null if no foreground was set
+     *
+     * @see #onDrawForeground(Canvas)
+     */
+    public Drawable getForeground() {
+        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+    }
+
+    /**
+     * Supply a Drawable that is to be rendered on top of all of the content in the view.
+     *
+     * @param foreground the Drawable to be drawn on top of the children
+     *
+     * @attr ref android.R.styleable#View_foreground
+     */
+    public void setForeground(Drawable foreground) {
+        if (mForegroundInfo == null) {
+            if (foreground == null) {
+                // Nothing to do.
+                return;
+            }
+            mForegroundInfo = new ForegroundInfo();
+        }
+
+        if (foreground == mForegroundInfo.mDrawable) {
+            // Nothing to do
+            return;
+        }
+
+        if (mForegroundInfo.mDrawable != null) {
+            mForegroundInfo.mDrawable.setCallback(null);
+            unscheduleDrawable(mForegroundInfo.mDrawable);
+        }
+
+        mForegroundInfo.mDrawable = foreground;
+        mForegroundInfo.mBoundsChanged = true;
+        if (foreground != null) {
+            setWillNotDraw(false);
+            foreground.setCallback(this);
+            foreground.setLayoutDirection(getLayoutDirection());
+            if (foreground.isStateful()) {
+                foreground.setState(getDrawableState());
+            }
+            applyForegroundTint();
+        }
+        requestLayout();
+        invalidate();
+    }
+
+    /**
+     * Magic bit used to support features of framework-internal window decor implementation details.
+     * This used to live exclusively in FrameLayout.
+     *
+     * @return true if the foreground should draw inside the padding region or false
+     *         if it should draw inset by the view's padding
+     * @hide internal use only; only used by FrameLayout and internal screen layouts.
+     */
+    public boolean isForegroundInsidePadding() {
+        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
+    }
+
+    /**
+     * Describes how the foreground is positioned.
+     *
+     * @return foreground gravity.
+     *
+     * @see #setForegroundGravity(int)
+     *
+     * @attr ref android.R.styleable#View_foregroundGravity
+     */
+    public int getForegroundGravity() {
+        return mForegroundInfo != null ? mForegroundInfo.mGravity
+                : Gravity.START | Gravity.TOP;
+    }
+
+    /**
+     * Describes how the foreground is positioned. Defaults to START and TOP.
+     *
+     * @param gravity see {@link android.view.Gravity}
+     *
+     * @see #getForegroundGravity()
+     *
+     * @attr ref android.R.styleable#View_foregroundGravity
+     */
+    public void setForegroundGravity(int gravity) {
+        if (mForegroundInfo == null) {
+            mForegroundInfo = new ForegroundInfo();
+        }
+
+        if (mForegroundInfo.mGravity != gravity) {
+            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
+                gravity |= Gravity.START;
+            }
+
+            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
+                gravity |= Gravity.TOP;
+            }
+
+            mForegroundInfo.mGravity = gravity;
+            requestLayout();
+        }
+    }
+
+    /**
+     * Applies a tint to the foreground drawable. Does not modify the current tint
+     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
+     * <p>
+     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
+     * mutate the drawable and apply the specified tint and tint mode using
+     * {@link Drawable#setTintList(ColorStateList)}.
+     *
+     * @param tint the tint to apply, may be {@code null} to clear tint
+     *
+     * @attr ref android.R.styleable#View_foregroundTint
+     * @see #getForegroundTintList()
+     * @see Drawable#setTintList(ColorStateList)
+     */
+    public void setForegroundTintList(@Nullable ColorStateList tint) {
+        if (mForegroundInfo == null) {
+            mForegroundInfo = new ForegroundInfo();
+        }
+        if (mForegroundInfo.mTintInfo == null) {
+            mForegroundInfo.mTintInfo = new TintInfo();
+        }
+        mForegroundInfo.mTintInfo.mTintList = tint;
+        mForegroundInfo.mTintInfo.mHasTintList = true;
+
+        applyForegroundTint();
+    }
+
+    /**
+     * Return the tint applied to the foreground drawable, if specified.
+     *
+     * @return the tint applied to the foreground drawable
+     * @attr ref android.R.styleable#View_foregroundTint
+     * @see #setForegroundTintList(ColorStateList)
+     */
+    @Nullable
+    public ColorStateList getForegroundTintList() {
+        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
+                ? mForegroundInfo.mTintInfo.mTintList : null;
+    }
+
+    /**
+     * Specifies the blending mode used to apply the tint specified by
+     * {@link #setForegroundTintList(ColorStateList)}} to the background
+     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
+     *
+     * @param tintMode the blending mode used to apply the tint, may be
+     *                 {@code null} to clear tint
+     * @attr ref android.R.styleable#View_foregroundTintMode
+     * @see #getForegroundTintMode()
+     * @see Drawable#setTintMode(PorterDuff.Mode)
+     */
+    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
+        if (mBackgroundTint == null) {
+            mBackgroundTint = new TintInfo();
+        }
+        mBackgroundTint.mTintMode = tintMode;
+        mBackgroundTint.mHasTintMode = true;
+
+        applyBackgroundTint();
+    }
+
+    /**
+     * Return the blending mode used to apply the tint to the foreground
+     * drawable, if specified.
+     *
+     * @return the blending mode used to apply the tint to the foreground
+     *         drawable
+     * @attr ref android.R.styleable#View_foregroundTintMode
+     * @see #setBackgroundTintMode(PorterDuff.Mode)
+     */
+    @Nullable
+    public PorterDuff.Mode getForegroundTintMode() {
+        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
+                ? mForegroundInfo.mTintInfo.mTintMode : null;
+    }
+
+    private void applyForegroundTint() {
+        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
+                && mForegroundInfo.mTintInfo != null) {
+            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
+            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
+                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
+
+                if (tintInfo.mHasTintList) {
+                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
+                }
+
+                if (tintInfo.mHasTintMode) {
+                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
+                }
+
+                // The drawable (or one of its children) may not have been
+                // stateful before applying the tint, so let's try again.
+                if (mForegroundInfo.mDrawable.isStateful()) {
+                    mForegroundInfo.mDrawable.setState(getDrawableState());
+                }
+            }
+        }
+    }
+
+    /**
+     * Draw any foreground content for this view.
+     *
+     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
+     * drawable or other view-specific decorations. The foreground is drawn on top of the
+     * primary view content.</p>
+     *
+     * @param canvas canvas to draw into
+     */
+    public void onDrawForeground(Canvas canvas) {
+        onDrawScrollBars(canvas);
+
+        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+        if (foreground != null) {
+            if (mForegroundInfo.mBoundsChanged) {
+                mForegroundInfo.mBoundsChanged = false;
+                final Rect selfBounds = mForegroundInfo.mSelfBounds;
+                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
+
+                if (mForegroundInfo.mInsidePadding) {
+                    selfBounds.set(0, 0, getWidth(), getHeight());
+                } else {
+                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
+                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
+                }
+
+                final int ld = getLayoutDirection();
+                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
+                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
+                foreground.setBounds(overlayBounds);
+            }
+
+            foreground.draw(canvas);
+        }
+    }
+
+    /**
      * Sets the padding. The view may add on the space required to display
      * the scrollbars, depending on the style and visibility of the scrollbars.
      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
@@ -18090,6 +18554,10 @@
                 // parts from this transparent region.
                 applyDrawableToTransparentRegion(mBackground, region);
             }
+            final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+            if (foreground != null) {
+                applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
+            }
         }
         return true;
     }
diff --git a/core/java/android/view/ViewAssistStructure.java b/core/java/android/view/ViewAssistStructure.java
index 5132bb9..7d263c5 100644
--- a/core/java/android/view/ViewAssistStructure.java
+++ b/core/java/android/view/ViewAssistStructure.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import android.graphics.Rect;
+import android.os.Bundle;
 import android.text.TextPaint;
 
 /**
@@ -23,6 +25,37 @@
  * View.onProvideAssistStructure}.
  */
 public abstract class ViewAssistStructure {
+    public abstract void setId(int id, String packageName, String typeName, String entryName);
+
+    public abstract void setDimens(int left, int top, int scrollX, int scrollY, int width,
+            int height);
+
+    public abstract void setVisibility(int visibility);
+
+    public abstract void setEnabled(boolean state);
+
+    public abstract void setClickable(boolean state);
+
+    public abstract void setLongClickable(boolean state);
+
+    public abstract void setFocusable(boolean state);
+
+    public abstract void setFocused(boolean state);
+
+    public abstract void setAccessibilityFocused(boolean state);
+
+    public abstract void setCheckable(boolean state);
+
+    public abstract void setChecked(boolean state);
+
+    public abstract void setSelected(boolean state);
+
+    public abstract void setActivated(boolean state);
+
+    public abstract void setClassName(String className);
+
+    public abstract void setContentDescription(CharSequence contentDescription);
+
     public abstract void setText(CharSequence text);
     public abstract void setText(CharSequence text, int selectionStart, int selectionEnd);
     public abstract void setTextPaint(TextPaint paint);
@@ -32,4 +65,17 @@
     public abstract int getTextSelectionStart();
     public abstract int getTextSelectionEnd();
     public abstract CharSequence getHint();
+
+    public abstract Bundle editExtras();
+    public abstract void clearExtras();
+
+    public abstract void setChildCount(int num);
+    public abstract int getChildCount();
+    public abstract ViewAssistStructure newChild(int index);
+
+    public abstract ViewAssistStructure asyncNewChild(int index);
+    public abstract void asyncCommit();
+
+    /** @hide */
+    public abstract Rect getTempRect();
 }
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 50e64c6..a237afd 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -1005,31 +1005,23 @@
             return fields;
         }
 
-        final ArrayList<Field> declaredFields = new ArrayList();
-        klass.getDeclaredFieldsUnchecked(false, declaredFields);
-
-        final ArrayList<Field> foundFields = new ArrayList<Field>();
-        final int count = declaredFields.size();
-        for (int i = 0; i < count; i++) {
-            final Field field = declaredFields.get(i);
-
-            // Ensure the field type can be resolved.
-            try {
-                field.getType();
-            } catch (NoClassDefFoundError e) {
-                continue;
+        try {
+            final Field[] declaredFields = klass.getDeclaredFieldsUnchecked(false);
+            final ArrayList<Field> foundFields = new ArrayList<Field>();
+            for (final Field field : declaredFields) {
+              // Fields which can't be resolved have a null type.
+              if (field.getType() != null && field.isAnnotationPresent(ExportedProperty.class)) {
+                  field.setAccessible(true);
+                  foundFields.add(field);
+                  sAnnotations.put(field, field.getAnnotation(ExportedProperty.class));
+              }
             }
-
-            if (field.isAnnotationPresent(ExportedProperty.class)) {
-                field.setAccessible(true);
-                foundFields.add(field);
-                sAnnotations.put(field, field.getAnnotation(ExportedProperty.class));
-            }
+            fields = foundFields.toArray(new Field[foundFields.size()]);
+            map.put(klass, fields);
+        } catch (NoClassDefFoundError e) {
+            throw new AssertionError(e);
         }
 
-        fields = foundFields.toArray(new Field[foundFields.size()]);
-        map.put(klass, fields);
-
         return fields;
     }
 
@@ -1651,4 +1643,4 @@
             }
         });
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 87f3e94..d0705bb 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2852,6 +2852,33 @@
         return false;
     }
 
+    /**
+     * Dispatch creation of {@link ViewAssistStructure} down the hierarchy.  This implementation
+     * adds in all child views of the view group, in addition to calling the default View
+     * implementation.
+     */
+    public void dispatchProvideAssistStructure(ViewAssistStructure structure) {
+        super.dispatchProvideAssistStructure(structure);
+        if (structure.getChildCount() == 0) {
+            final int childrenCount = getChildCount();
+            if (childrenCount > 0) {
+                structure.setChildCount(childrenCount);
+                final ArrayList<View> preorderedList = buildOrderedChildList();
+                final boolean customOrder = preorderedList == null
+                        && isChildrenDrawingOrderEnabled();
+                final View[] children = mChildren;
+                for (int i=0; i<childrenCount; i++) {
+                    final int childIndex = customOrder
+                            ? getChildDrawingOrder(childrenCount, i) : i;
+                    final View child = (preorderedList == null)
+                            ? children[childIndex] : preorderedList.get(childIndex);
+                    ViewAssistStructure cstructure = structure.newChild(i);
+                    child.dispatchProvideAssistStructure(cstructure);
+                }
+            }
+        }
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
@@ -5727,12 +5754,12 @@
             } else if (childDimension == LayoutParams.MATCH_PARENT) {
                 // Child wants to be our size... find out how big it should
                 // be
-                resultSize = 0;
+                resultSize = size;
                 resultMode = MeasureSpec.UNSPECIFIED;
             } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                 // Child wants to determine its own size.... find out how
                 // big it should be
-                resultSize = 0;
+                resultSize = size;
                 resultMode = MeasureSpec.UNSPECIFIED;
             }
             break;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 234de40..4158340 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -118,7 +118,6 @@
      * at 60 Hz. This can be used to measure the potential framerate.
      */
     private static final String PROPERTY_PROFILE_RENDERING = "viewroot.profile_rendering";
-    private static final String PROPERTY_MEDIA_DISABLED = "config.disable_media";
 
     // properties used by emulator to determine display shape
     public static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
@@ -301,8 +300,6 @@
     private Choreographer.FrameCallback mRenderProfiler;
     private boolean mRenderProfilingEnabled;
 
-    private boolean mMediaDisabled;
-
     // Variables to track frames per second, enabled via DEBUG_FPS flag
     private long mFpsStartTime = -1;
     private long mFpsPrevTime = -1;
@@ -5360,10 +5357,6 @@
     public void playSoundEffect(int effectId) {
         checkThread();
 
-        if (mMediaDisabled) {
-            return;
-        }
-
         try {
             final AudioManager audioManager = getAudioManager();
 
@@ -5570,9 +5563,6 @@
                 mProfileRendering = SystemProperties.getBoolean(PROPERTY_PROFILE_RENDERING, false);
                 profileRendering(mAttachInfo.mHasWindowFocus);
 
-                // Media (used by sound effects)
-                mMediaDisabled = SystemProperties.getBoolean(PROPERTY_MEDIA_DISABLED, false);
-
                 // Hardware rendering
                 if (mAttachInfo.mHardwareRenderer != null) {
                     if (mAttachInfo.mHardwareRenderer.loadSystemProperties()) {
@@ -6278,41 +6268,79 @@
 
 
             case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
-                if (mAccessibilityFocusedHost != null && mAccessibilityFocusedVirtualView != null) {
-                    // We care only for changes rooted in the focused host.
-                    final long eventSourceId = event.getSourceNodeId();
-                    final int hostViewId = AccessibilityNodeInfo.getAccessibilityViewId(
-                            eventSourceId);
-                    if (hostViewId != mAccessibilityFocusedHost.getAccessibilityViewId()) {
-                        break;
-                    }
-
-                    // We only care about changes that may change the virtual focused view bounds.
-                    final int changes = event.getContentChangeTypes();
-                    if ((changes & AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) != 0
-                            || changes == AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED) {
-                        AccessibilityNodeProvider provider = mAccessibilityFocusedHost
-                                .getAccessibilityNodeProvider();
-                        if (provider != null) {
-                            final int virtualChildId = AccessibilityNodeInfo.getVirtualDescendantId(
-                                    mAccessibilityFocusedVirtualView.getSourceNodeId());
-                            if (virtualChildId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
-                                mAccessibilityFocusedVirtualView = provider
-                                        .createAccessibilityNodeInfo(
-                                                AccessibilityNodeProvider.HOST_VIEW_ID);
-                            } else {
-                                mAccessibilityFocusedVirtualView = provider
-                                        .createAccessibilityNodeInfo(virtualChildId);
-                            }
-                        }
-                    }
-                }
+                handleWindowContentChangedEvent(event);
             } break;
         }
         mAccessibilityManager.sendAccessibilityEvent(event);
         return true;
     }
 
+    /**
+     * Updates the focused virtual view, when necessary, in response to a
+     * content changed event.
+     * <p>
+     * This is necessary to get updated bounds after a position change.
+     *
+     * @param event an accessibility event of type
+     *              {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
+     */
+    private void handleWindowContentChangedEvent(AccessibilityEvent event) {
+        // No virtual view focused, nothing to do here.
+        if (mAccessibilityFocusedHost == null || mAccessibilityFocusedVirtualView == null) {
+            return;
+        }
+
+        // If we have a node but no provider, abort.
+        final AccessibilityNodeProvider provider =
+                mAccessibilityFocusedHost.getAccessibilityNodeProvider();
+        if (provider == null) {
+            // TODO: Should we clear the focused virtual view?
+            return;
+        }
+
+        // We only care about change types that may affect the bounds of the
+        // focused virtual view.
+        final int changes = event.getContentChangeTypes();
+        if ((changes & AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) == 0
+                && changes != AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED) {
+            return;
+        }
+
+        final long eventSourceNodeId = event.getSourceNodeId();
+        final int changedViewId = AccessibilityNodeInfo.getAccessibilityViewId(eventSourceNodeId);
+
+        // Search up the tree for subtree containment.
+        boolean hostInSubtree = false;
+        View root = mAccessibilityFocusedHost;
+        while (root != null && !hostInSubtree) {
+            if (changedViewId == root.getAccessibilityViewId()) {
+                hostInSubtree = true;
+            } else {
+                final ViewParent parent = root.getParent();
+                if (parent instanceof View) {
+                    root = (View) parent;
+                } else {
+                    root = null;
+                }
+            }
+        }
+
+        // We care only about changes in subtrees containing the host view.
+        if (!hostInSubtree) {
+            return;
+        }
+
+        final long focusedSourceNodeId = mAccessibilityFocusedVirtualView.getSourceNodeId();
+        int focusedChildId = AccessibilityNodeInfo.getVirtualDescendantId(focusedSourceNodeId);
+        if (focusedChildId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+            // TODO: Should we clear the focused virtual view?
+            focusedChildId = AccessibilityNodeProvider.HOST_VIEW_ID;
+        }
+
+        // Refresh the node for the focused virtual view.
+        mAccessibilityFocusedVirtualView = provider.createAccessibilityNodeInfo(focusedChildId);
+    }
+
     @Override
     public void notifySubtreeAccessibilityStateChanged(View child, View source, int changeType) {
         postSendWindowContentChangedCallback(source, changeType);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 9a92932..36f047e 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1856,14 +1856,14 @@
     public abstract int getStatusBarColor();
 
     /**
-     * Sets the color of the status bar to {@param color}.
+     * Sets the color of the status bar to {@code color}.
      *
      * For this to take effect,
      * the window must be drawing the system bar backgrounds with
      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} and
      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS} must not be set.
      *
-     * If {@param color} is not opaque, consider setting
+     * If {@code color} is not opaque, consider setting
      * {@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and
      * {@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
      * <p>
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 66dae7b..54d78f3 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -223,6 +223,7 @@
             @ViewDebug.IntToString(from = TYPE_MAGNIFICATION_OVERLAY, to = "TYPE_MAGNIFICATION_OVERLAY"),
             @ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION"),
             @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION, to = "TYPE_VOICE_INTERACTION"),
+            @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, to = "TYPE_VOICE_INTERACTION_STARTING"),
         })
         public int type;
     
@@ -549,6 +550,12 @@
         public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32;
 
         /**
+         * Window type: Starting window for voice interaction layer.
+         * @hide
+         */
+        public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33;
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 6096d7d..0736ed8 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -29,6 +29,8 @@
 import android.util.Pools.SynchronizedPool;
 import android.view.View;
 
+import com.android.internal.R;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -264,7 +266,8 @@
      * Action to set the selection. Performing this action with no arguments
      * clears the selection.
      * <p>
-     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SELECTION_START_INT},
+     * <strong>Arguments:</strong>
+     * {@link #ACTION_ARGUMENT_SELECTION_START_INT},
      * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
      * <strong>Example:</strong>
      * <code><pre><p>
@@ -300,7 +303,8 @@
      * null</code> or empty {@link CharSequence} will clear the text. This action will also put the
      * cursor at the end of text.
      * <p>
-     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
+     * <strong>Arguments:</strong>
+     * {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
      * <strong>Example:</strong>
      * <code><pre><p>
      *   Bundle arguments = new Bundle();
@@ -324,12 +328,15 @@
      * Argument for which movement granularity to be used when traversing the node text.
      * <p>
      * <strong>Type:</strong> int<br>
-     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
-     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
+     * <strong>Actions:</strong>
+     * <ul>
+     *     <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
+     *     <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
+     * </ul>
      * </p>
      *
-     * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
-     * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+     * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+     * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
      */
     public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
             "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
@@ -338,12 +345,15 @@
      * Argument for which HTML element to get moving to the next/previous HTML element.
      * <p>
      * <strong>Type:</strong> String<br>
-     * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT},
-     *         {@link #ACTION_PREVIOUS_HTML_ELEMENT}
+     * <strong>Actions:</strong>
+     * <ul>
+     *     <li>{@link AccessibilityAction#ACTION_NEXT_HTML_ELEMENT}</li>
+     *     <li>{@link AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT}</li>
+     * </ul>
      * </p>
      *
-     * @see #ACTION_NEXT_HTML_ELEMENT
-     * @see #ACTION_PREVIOUS_HTML_ELEMENT
+     * @see AccessibilityAction#ACTION_NEXT_HTML_ELEMENT
+     * @see AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT
      */
     public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
             "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
@@ -353,12 +363,14 @@
      * or to move it otherwise.
      * <p>
      * <strong>Type:</strong> boolean<br>
-     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
-     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
-     * </p>
+     * <strong>Actions:</strong>
+     * <ul>
+     *     <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
+     *     <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
+     * </ul>
      *
-     * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
-     * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+     * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+     * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
      */
     public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
             "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
@@ -367,10 +379,12 @@
      * Argument for specifying the selection start.
      * <p>
      * <strong>Type:</strong> int<br>
-     * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
-     * </p>
+     * <strong>Actions:</strong>
+     * <ul>
+     *     <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
+     * </ul>
      *
-     * @see #ACTION_SET_SELECTION
+     * @see AccessibilityAction#ACTION_SET_SELECTION
      */
     public static final String ACTION_ARGUMENT_SELECTION_START_INT =
             "ACTION_ARGUMENT_SELECTION_START_INT";
@@ -379,26 +393,58 @@
      * Argument for specifying the selection end.
      * <p>
      * <strong>Type:</strong> int<br>
-     * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
-     * </p>
+     * <strong>Actions:</strong>
+     * <ul>
+     *     <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
+     * </ul>
      *
-     * @see #ACTION_SET_SELECTION
+     * @see AccessibilityAction#ACTION_SET_SELECTION
      */
     public static final String ACTION_ARGUMENT_SELECTION_END_INT =
             "ACTION_ARGUMENT_SELECTION_END_INT";
 
     /**
-     * Argument for specifying the text content to set
+     * Argument for specifying the text content to set.
      * <p>
      * <strong>Type:</strong> CharSequence<br>
-     * <strong>Actions:</strong> {@link #ACTION_SET_TEXT}
-     * </p>
+     * <strong>Actions:</strong>
+     * <ul>
+     *     <li>{@link AccessibilityAction#ACTION_SET_TEXT}</li>
+     * </ul>
      *
-     * @see #ACTION_SET_TEXT
+     * @see AccessibilityAction#ACTION_SET_TEXT
      */
     public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
             "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
 
+    /**
+     * Argument for specifying the collection row to make visible on screen.
+     * <p>
+     * <strong>Type:</strong> int<br>
+     * <strong>Actions:</strong>
+     * <ul>
+     *     <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
+     * </ul>
+     *
+     * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
+     */
+    public static final String ACTION_ARGUMENT_ROW_INT =
+            "android.view.accessibility.action.ARGUMENT_ROW_INT";
+
+    /**
+     * Argument for specifying the collection column to make visible on screen.
+     * <p>
+     * <strong>Type:</strong> int<br>
+     * <strong>Actions:</strong>
+     * <ul>
+     *     <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
+     * </ul>
+     *
+     * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
+     */
+    public static final String ACTION_ARGUMENT_COLUMN_INT =
+            "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
+
     // Focus types
 
     /**
@@ -537,7 +583,7 @@
     // Housekeeping.
     private static final int MAX_POOL_SIZE = 50;
     private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
-            new SynchronizedPool<AccessibilityNodeInfo>(MAX_POOL_SIZE);
+            new SynchronizedPool<>(MAX_POOL_SIZE);
 
     private boolean mSealed;
 
@@ -968,7 +1014,7 @@
         }
 
         if (mActions == null) {
-            mActions = new ArrayList<AccessibilityAction>();
+            mActions = new ArrayList<>();
         }
 
         mActions.remove(action);
@@ -1560,7 +1606,7 @@
     }
 
     /**
-     * Sets whether this node is visible to the user.
+     * Gets whether this node is visible to the user.
      *
      * @return Whether the node is visible to the user.
      */
@@ -3402,7 +3448,31 @@
                 new AccessibilityAction(
                         AccessibilityNodeInfo.ACTION_SET_TEXT, null);
 
-        private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<AccessibilityAction>();
+        /**
+         * Action that requests the node make its bounding rectangle visible
+         * on the screen, scrolling if necessary just enough.
+         *
+         * @see View#requestRectangleOnScreen(Rect)
+         */
+        public static final AccessibilityAction ACTION_SHOW_ON_SCREEN =
+                new AccessibilityAction(R.id.accessibilityActionShowOnScreen, null);
+
+        /**
+         * Action that scrolls the node to make the specified collection
+         * position visible on screen.
+         * <p>
+         * <strong>Arguments:</strong>
+         * <ul>
+         *     <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_ROW_INT}</li>
+         *     <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_COLUMN_INT}</li>
+         * <ul>
+         *
+         * @see AccessibilityNodeInfo#getCollectionInfo()
+         */
+        public static final AccessibilityAction ACTION_SCROLL_TO_POSITION =
+                new AccessibilityAction(R.id.accessibilityActionScrollToPosition, null);
+
+        private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
         static {
             sStandardActions.add(ACTION_FOCUS);
             sStandardActions.add(ACTION_CLEAR_FOCUS);
@@ -3426,6 +3496,8 @@
             sStandardActions.add(ACTION_COLLAPSE);
             sStandardActions.add(ACTION_DISMISS);
             sStandardActions.add(ACTION_SET_TEXT);
+            sStandardActions.add(ACTION_SHOW_ON_SCREEN);
+            sStandardActions.add(ACTION_SCROLL_TO_POSITION);
         }
 
         private final int mActionId;
@@ -3646,7 +3718,7 @@
         private static final int MAX_POOL_SIZE = 20;
 
         private static final SynchronizedPool<CollectionInfo> sPool =
-                new SynchronizedPool<CollectionInfo>(MAX_POOL_SIZE);
+                new SynchronizedPool<>(MAX_POOL_SIZE);
 
         private int mRowCount;
         private int mColumnCount;
@@ -3792,7 +3864,7 @@
         private static final int MAX_POOL_SIZE = 20;
 
         private static final SynchronizedPool<CollectionItemInfo> sPool =
-                new SynchronizedPool<CollectionItemInfo>(MAX_POOL_SIZE);
+                new SynchronizedPool<>(MAX_POOL_SIZE);
 
         /**
          * Obtains a pooled instance that is a clone of another one.
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 4737e9b..0b18bb8 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -284,13 +284,19 @@
      * currently set for that origin. The host application should invoke the
      * specified callback with the desired permission state. See
      * {@link GeolocationPermissions} for details.
+     *
+     * If this method isn't overridden, the callback is invoked with permission
+     * denied state.
+     *
      * @param origin The origin of the web content attempting to use the
      *               Geolocation API.
      * @param callback The callback to use to set the permission state for the
      *                 origin.
      */
     public void onGeolocationPermissionsShowPrompt(String origin,
-            GeolocationPermissions.Callback callback) {}
+            GeolocationPermissions.Callback callback) {
+        callback.invoke(origin, false, false);
+    }
 
     /**
      * Notify the host application that a request for Geolocation permissions,
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index aa77d5e..7ab5aaa 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -40,6 +40,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewAssistStructure;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
@@ -2424,6 +2425,11 @@
         return WebView.class.getName();
     }
 
+    @Override
+    public void onProvideVirtualAssistStructure(ViewAssistStructure structure) {
+        mProvider.getViewDelegate().onProvideVirtualAssistStructure(structure);
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 53c7e04..8a2b3fa 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -200,8 +200,6 @@
     public static final int ERROR_FILE_NOT_FOUND = -14;
     /** Too many requests during this load */
     public static final int ERROR_TOO_MANY_REQUESTS = -15;
-    /** Request blocked by the browser */
-    public static final int ERROR_BLOCKED = -16;
 
     /**
      * Report an error to the host application. These errors are unrecoverable
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index fa2ce1b..d5787de 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -32,6 +32,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewAssistStructure;
 import android.view.ViewGroup.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -298,6 +299,8 @@
     interface ViewDelegate {
         public boolean shouldDelayChildPressedState();
 
+        public void onProvideVirtualAssistStructure(ViewAssistStructure structure);
+
         public AccessibilityNodeProvider getAccessibilityNodeProvider();
 
         public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 168066a..e7b6238 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -61,6 +61,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
@@ -1504,11 +1505,11 @@
         super.onInitializeAccessibilityNodeInfoInternal(info);
         if (isEnabled()) {
             if (canScrollUp()) {
-                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+                info.addAction(AccessibilityAction.ACTION_SCROLL_BACKWARD);
                 info.setScrollable(true);
             }
             if (canScrollDown()) {
-                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+                info.addAction(AccessibilityAction.ACTION_SCROLL_FORWARD);
                 info.setScrollable(true);
             }
         }
@@ -2502,18 +2503,18 @@
 
         if (position == getSelectedItemPosition()) {
             info.setSelected(true);
-            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
+            info.addAction(AccessibilityAction.ACTION_CLEAR_SELECTION);
         } else {
-            info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
+            info.addAction(AccessibilityAction.ACTION_SELECT);
         }
 
         if (isClickable()) {
-            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
+            info.addAction(AccessibilityAction.ACTION_CLICK);
             info.setClickable(true);
         }
 
         if (isLongClickable()) {
-            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
+            info.addAction(AccessibilityAction.ACTION_LONG_CLICK);
             info.setLongClickable(true);
         }
     }
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 1716dbd..45eee34 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -40,8 +40,10 @@
  * @attr ref android.R.styleable#AnalogClock_dial
  * @attr ref android.R.styleable#AnalogClock_hand_hour
  * @attr ref android.R.styleable#AnalogClock_hand_minute
+ * @deprecated This widget is no longer supported.
  */
 @RemoteView
+@Deprecated
 public class AnalogClock extends View {
     private Time mCalendar;
 
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 7b8a979..a157087 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -49,7 +49,6 @@
  * A delegate for picking up a date (day / month / year).
  */
 class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate {
-
     private static final int USE_LOCALE = 0;
 
     private static final int UNINITIALIZED = -1;
@@ -61,9 +60,9 @@
 
     private static final int ANIMATION_DURATION = 300;
 
-    public static final int[] ATTRS_TEXT_COLOR = new int[]{com.android.internal.R.attr.textColor};
-
-    public static final int[] ATTRS_DISABLED_ALPHA = new int[]{
+    private static final int[] ATTRS_TEXT_COLOR = new int[] {
+            com.android.internal.R.attr.textColor};
+    private static final int[] ATTRS_DISABLED_ALPHA = new int[] {
             com.android.internal.R.attr.disabledAlpha};
 
     private SimpleDateFormat mYearFormat;
@@ -157,6 +156,8 @@
             header.setBackground(a.getDrawable(R.styleable.DatePicker_headerBackground));
         }
 
+        a.recycle();
+
         // Set up picker container.
         mAnimator = (ViewAnimator) mContainer.findViewById(R.id.animator);
 
@@ -174,32 +175,10 @@
         mYearPickerView.setDate(mCurrentDate.getTimeInMillis());
         mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener);
 
-        final int yearTextAppearanceResId = a.getResourceId(
-                R.styleable.DatePicker_yearListItemTextAppearance, 0);
-        if (yearTextAppearanceResId != 0) {
-            mYearPickerView.setYearTextAppearance(yearTextAppearanceResId);
-        }
-
-        final int yearActivatedTextAppearanceResId = a.getResourceId(
-                R.styleable.DatePicker_yearListItemActivatedTextAppearance, 0);
-        if (yearActivatedTextAppearanceResId != 0) {
-            mYearPickerView.setYearActivatedTextAppearance(yearActivatedTextAppearanceResId);
-        }
-
-        a.recycle();
-
         // Set up content descriptions.
         mSelectDay = res.getString(R.string.select_day);
         mSelectYear = res.getString(R.string.select_year);
 
-        final Animation inAnim = new AlphaAnimation(0, 1);
-        inAnim.setDuration(ANIMATION_DURATION);
-        mAnimator.setInAnimation(inAnim);
-
-        final Animation outAnim = new AlphaAnimation(1, 0);
-        outAnim.setDuration(ANIMATION_DURATION);
-        mAnimator.setOutAnimation(outAnim);
-
         // Initialize for current locale. This also initializes the date, so no
         // need to call onDateChanged.
         onLocaleChanged(mCurrentLocale);
diff --git a/core/java/android/widget/DayPickerAdapter.java b/core/java/android/widget/DayPickerAdapter.java
index 4f9f09e..9a4b6f5 100644
--- a/core/java/android/widget/DayPickerAdapter.java
+++ b/core/java/android/widget/DayPickerAdapter.java
@@ -18,10 +18,15 @@
 
 import com.android.internal.widget.PagerAdapter;
 
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.util.SparseArray;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.SimpleMonthView.OnDayClickListener;
@@ -37,9 +42,13 @@
     private final Calendar mMinDate = Calendar.getInstance();
     private final Calendar mMaxDate = Calendar.getInstance();
 
-    private final SparseArray<SimpleMonthView> mItems = new SparseArray<>();
+    private final SparseArray<ViewHolder> mItems = new SparseArray<>();
 
-    private Calendar mSelectedDay = Calendar.getInstance();
+    private final LayoutInflater mInflater;
+    private final int mLayoutResId;
+    private final int mCalendarViewId;
+
+    private Calendar mSelectedDay = null;
 
     private int mMonthTextAppearance;
     private int mDayOfWeekTextAppearance;
@@ -51,19 +60,29 @@
 
     private OnDaySelectedListener mOnDaySelectedListener;
 
+    private int mCount;
     private int mFirstDayOfWeek;
 
-    public DayPickerAdapter(Context context) {
+    public DayPickerAdapter(@NonNull Context context, @LayoutRes int layoutResId,
+            @IdRes int calendarViewId) {
+        mInflater = LayoutInflater.from(context);
+        mLayoutResId = layoutResId;
+        mCalendarViewId = calendarViewId;
+
         final TypedArray ta = context.obtainStyledAttributes(new int[] {
                 com.android.internal.R.attr.colorControlHighlight});
         mDayHighlightColor = ta.getColorStateList(0);
         ta.recycle();
     }
 
-    public void setRange(Calendar min, Calendar max) {
+    public void setRange(@NonNull Calendar min, @NonNull Calendar max) {
         mMinDate.setTimeInMillis(min.getTimeInMillis());
         mMaxDate.setTimeInMillis(max.getTimeInMillis());
 
+        final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
+        final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
+        mCount = diffMonth + MONTHS_IN_YEAR * diffYear + 1;
+
         // Positions are now invalid, clear everything and start over.
         notifyDataSetChanged();
     }
@@ -80,7 +99,7 @@
         // Update displayed views.
         final int count = mItems.size();
         for (int i = 0; i < count; i++) {
-            final SimpleMonthView monthView = mItems.valueAt(i);
+            final SimpleMonthView monthView = mItems.valueAt(i).calendar;
             monthView.setFirstDayOfWeek(weekStart);
         }
     }
@@ -94,23 +113,25 @@
      *
      * @param day the selected day
      */
-    public void setSelectedDay(Calendar day) {
+    public void setSelectedDay(@Nullable Calendar day) {
         final int oldPosition = getPositionForDay(mSelectedDay);
         final int newPosition = getPositionForDay(day);
 
         // Clear the old position if necessary.
-        if (oldPosition != newPosition) {
-            final SimpleMonthView oldMonthView = mItems.get(oldPosition, null);
+        if (oldPosition != newPosition && oldPosition >= 0) {
+            final ViewHolder oldMonthView = mItems.get(oldPosition, null);
             if (oldMonthView != null) {
-                oldMonthView.setSelectedDay(-1);
+                oldMonthView.calendar.setSelectedDay(-1);
             }
         }
 
         // Set the new position.
-        final SimpleMonthView newMonthView = mItems.get(newPosition, null);
-        if (newMonthView != null) {
-            final int dayOfMonth = day.get(Calendar.DAY_OF_MONTH);
-            newMonthView.setSelectedDay(dayOfMonth);
+        if (newPosition >= 0) {
+            final ViewHolder newMonthView = mItems.get(newPosition, null);
+            if (newMonthView != null) {
+                final int dayOfMonth = day.get(Calendar.DAY_OF_MONTH);
+                newMonthView.calendar.setSelectedDay(dayOfMonth);
+            }
         }
 
         mSelectedDay = day;
@@ -155,14 +176,13 @@
 
     @Override
     public int getCount() {
-        final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
-        final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
-        return diffMonth + MONTHS_IN_YEAR * diffYear + 1;
+        return mCount;
     }
 
     @Override
     public boolean isViewFromObject(View view, Object object) {
-        return view == object;
+        final ViewHolder holder = (ViewHolder) object;
+        return view == holder.container;
     }
 
     private int getMonthForPosition(int position) {
@@ -173,7 +193,11 @@
         return position / MONTHS_IN_YEAR + mMinDate.get(Calendar.YEAR);
     }
 
-    private int getPositionForDay(Calendar day) {
+    private int getPositionForDay(@Nullable Calendar day) {
+        if (day == null) {
+            return -1;
+        }
+
         final int yearOffset = (day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR));
         final int monthOffset = (day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH));
         return yearOffset * MONTHS_IN_YEAR + monthOffset;
@@ -181,7 +205,9 @@
 
     @Override
     public Object instantiateItem(ViewGroup container, int position) {
-        final SimpleMonthView v = new SimpleMonthView(container.getContext());
+        final View itemView = mInflater.inflate(mLayoutResId, container, false);
+
+        final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
         v.setOnDayClickListener(mOnDayClickListener);
         v.setMonthTextAppearance(mMonthTextAppearance);
         v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
@@ -205,7 +231,7 @@
         final int year = getYearForPosition(position);
 
         final int selectedDay;
-        if (mSelectedDay.get(Calendar.MONTH) == month) {
+        if (mSelectedDay != null && mSelectedDay.get(Calendar.MONTH) == month) {
             selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
         } else {
             selectedDay = -1;
@@ -227,33 +253,34 @@
 
         v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek,
                 enabledDayRangeStart, enabledDayRangeEnd);
+        v.setPrevEnabled(position > 0);
+        v.setNextEnabled(position < mCount - 1);
 
-        mItems.put(position, v);
+        final ViewHolder holder = new ViewHolder(position, itemView, v);
+        mItems.put(position, holder);
 
-        container.addView(v);
+        container.addView(itemView);
 
-        return v;
+        return holder;
     }
 
     @Override
     public void destroyItem(ViewGroup container, int position, Object object) {
-        container.removeView(mItems.get(position));
+        final ViewHolder holder = (ViewHolder) object;
+        container.removeView(holder.container);
 
         mItems.remove(position);
     }
 
     @Override
     public int getItemPosition(Object object) {
-        final int index = mItems.indexOfValue((SimpleMonthView) object);
-        if (index < 0) {
-            return mItems.keyAt(index);
-        }
-        return -1;
+        final ViewHolder holder = (ViewHolder) object;
+        return holder.position;
     }
 
     @Override
     public CharSequence getPageTitle(int position) {
-        final SimpleMonthView v = mItems.get(position);
+        final SimpleMonthView v = mItems.get(position).calendar;
         if (v != null) {
             return v.getTitle();
         }
@@ -275,9 +302,29 @@
                 }
             }
         }
+
+        @Override
+        public void onNavigationClick(SimpleMonthView view, int direction, boolean animate) {
+            if (mOnDaySelectedListener != null) {
+                mOnDaySelectedListener.onNavigationClick(DayPickerAdapter.this, direction, animate);
+            }
+        }
     };
 
+    private static class ViewHolder {
+        public final int position;
+        public final View container;
+        public final SimpleMonthView calendar;
+
+        public ViewHolder(int position, View container, SimpleMonthView calendar) {
+            this.position = position;
+            this.container = container;
+            this.calendar = calendar;
+        }
+    }
+
     public interface OnDaySelectedListener {
         public void onDaySelected(DayPickerAdapter view, Calendar day);
+        public void onNavigationClick(DayPickerAdapter view, int direction, boolean animate);
     }
 }
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index a7ae926..ec2528f 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -88,7 +88,8 @@
         a.recycle();
 
         // Set up adapter.
-        mAdapter = new DayPickerAdapter(context);
+        mAdapter = new DayPickerAdapter(context,
+                R.layout.date_picker_month_item_material, R.id.month_view);
         mAdapter.setMonthTextAppearance(monthTextAppearanceResId);
         mAdapter.setDayOfWeekTextAppearance(dayOfWeekTextAppearanceResId);
         mAdapter.setDayTextAppearance(dayTextAppearanceResId);
@@ -128,6 +129,14 @@
                     mOnDaySelectedListener.onDaySelected(DayPickerView.this, day);
                 }
             }
+
+            @Override
+            public void onNavigationClick(DayPickerAdapter view, int direction, boolean animate) {
+                // ViewPager clamps input values, so we don't need to worry
+                // about passing invalid indices.
+                final int nextItem = getCurrentItem() + direction;
+                setCurrentItem(nextItem, animate);
+            }
         });
     }
 
@@ -178,7 +187,6 @@
      * @param setSelected whether to set the specified day as selected
      */
     private void setDate(long timeInMillis, boolean animate, boolean setSelected) {
-        // Set the selected day
         if (setSelected) {
             mSelectedDay.setTimeInMillis(timeInMillis);
         }
@@ -187,6 +195,9 @@
         if (position != getCurrentItem()) {
             setCurrentItem(position, animate);
         }
+
+        mTempCalendar.setTimeInMillis(timeInMillis);
+        mAdapter.setSelectedDay(mTempCalendar);
     }
 
     public long getDate() {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 3fca463..32b99a8 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -16,18 +16,6 @@
 
 package android.widget;
 
-import android.content.UndoManager;
-import android.content.UndoOperation;
-import android.content.UndoOwner;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.InputFilter;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.GrowingArrayUtils;
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.widget.EditableInputConnection;
-
 import android.R;
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
@@ -35,6 +23,9 @@
 import android.content.ClipData.Item;
 import android.content.Context;
 import android.content.Intent;
+import android.content.UndoManager;
+import android.content.UndoOperation;
+import android.content.UndoOwner;
 import android.content.pm.PackageManager;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -46,13 +37,17 @@
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.inputmethodservice.ExtractEditText;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.ParcelableParcel;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.text.DynamicLayout;
 import android.text.Editable;
+import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Layout;
 import android.text.ParcelableSpan;
@@ -105,6 +100,11 @@
 import android.widget.TextView.Drawables;
 import android.widget.TextView.OnEditorActionListener;
 
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.widget.EditableInputConnection;
+
 import java.text.BreakIterator;
 import java.util.Arrays;
 import java.util.Comparator;
@@ -2939,7 +2939,27 @@
      * The default callback provides a subset of Select All, Cut, Copy and Paste actions, depending
      * on which of these this TextView supports.
      */
-    private class SelectionActionModeCallback implements ActionMode.Callback {
+    private class SelectionActionModeCallback extends ActionMode.Callback2 {
+        private final Path mSelectionPath = new Path();
+        private final RectF mSelectionBounds = new RectF();
+
+        private int mSelectionHandleHeight;
+        private int mInsertionHandleHeight;
+
+        public SelectionActionModeCallback() {
+            SelectionModifierCursorController selectionController = getSelectionController();
+            if (selectionController.mStartHandle == null) {
+                selectionController.initDrawables();
+                selectionController.initHandles();
+            }
+            mSelectionHandleHeight = Math.max(
+                    mSelectHandleLeft.getMinimumHeight(), mSelectHandleRight.getMinimumHeight());
+            InsertionPointCursorController insertionController = getInsertionController();
+            if (insertionController != null) {
+                insertionController.getHandle();
+                mInsertionHandleHeight = mSelectHandleCenter.getMinimumHeight();
+            }
+        }
 
         @Override
         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
@@ -2956,13 +2976,6 @@
             mode.setSubtitle(null);
             mode.setTitleOptionalHint(true);
 
-            menu.add(0, TextView.ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
-                    setIcon(styledAttributes.getResourceId(
-                            R.styleable.SelectionModeDrawables_actionModeSelectAllDrawable, 0)).
-                    setAlphabeticShortcut('a').
-                    setShowAsAction(
-                            MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-
             if (mTextView.canCut()) {
                 menu.add(0, TextView.ID_CUT, 0, com.android.internal.R.string.cut).
                     setIcon(styledAttributes.getResourceId(
@@ -2990,6 +3003,13 @@
                                 MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
             }
 
+            menu.add(0, TextView.ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
+                    setIcon(styledAttributes.getResourceId(
+                            R.styleable.SelectionModeDrawables_actionModeSelectAllDrawable, 0)).
+                    setAlphabeticShortcut('a').
+                    setShowAsAction(
+                            MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+
             if (mTextView.isSuggestionsEnabled() && isCursorInsideSuggestionSpan()) {
                 menu.add(0, TextView.ID_REPLACE, 0, com.android.internal.R.string.replace).
                         setShowAsAction(
@@ -3057,6 +3077,40 @@
 
             mSelectionActionMode = null;
         }
+
+        @Override
+        public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
+            if (!view.equals(mTextView) || mTextView.getLayout() == null) {
+                super.onGetContentRect(mode, view, outRect);
+                return;
+            }
+            if (mTextView.getSelectionStart() != mTextView.getSelectionEnd()) {
+                // We have a selection.
+                mSelectionPath.reset();
+                mTextView.getLayout().getSelectionPath(
+                        mTextView.getSelectionStart(), mTextView.getSelectionEnd(), mSelectionPath);
+                mSelectionPath.computeBounds(mSelectionBounds, true);
+                mSelectionBounds.bottom += mSelectionHandleHeight;
+            } else {
+                // We have a single cursor.
+                int line = mTextView.getLayout().getLineForOffset(mTextView.getSelectionStart());
+                float primaryHorizontal =
+                        mTextView.getLayout().getPrimaryHorizontal(mTextView.getSelectionStart());
+                mSelectionBounds.set(
+                        primaryHorizontal,
+                        mTextView.getLayout().getLineTop(line),
+                        primaryHorizontal + 1,
+                        mTextView.getLayout().getLineTop(line + 1) + mInsertionHandleHeight);
+            }
+            // Take TextView's padding and scroll into account.
+            int textHorizontalOffset = mTextView.viewportToContentHorizontalOffset();
+            int textVerticalOffset = mTextView.viewportToContentVerticalOffset();
+            outRect.set(
+                    (int) Math.floor(mSelectionBounds.left + textHorizontalOffset),
+                    (int) Math.floor(mSelectionBounds.top + textVerticalOffset),
+                    (int) Math.ceil(mSelectionBounds.right + textHorizontalOffset),
+                    (int) Math.ceil(mSelectionBounds.bottom + textVerticalOffset));
+        }
     }
 
     private void onReplace() {
@@ -3066,97 +3120,6 @@
         showSuggestions();
     }
 
-    private class ActionPopupWindow extends PinnedPopupWindow implements OnClickListener {
-        private static final int POPUP_TEXT_LAYOUT =
-                com.android.internal.R.layout.text_edit_action_popup_text;
-        private TextView mPasteTextView;
-        private TextView mReplaceTextView;
-
-        @Override
-        protected void createPopupWindow() {
-            mPopupWindow = new PopupWindow(mTextView.getContext(), null,
-                    com.android.internal.R.attr.textSelectHandleWindowStyle);
-            mPopupWindow.setClippingEnabled(true);
-        }
-
-        @Override
-        protected void initContentView() {
-            LinearLayout linearLayout = new LinearLayout(mTextView.getContext());
-            linearLayout.setOrientation(LinearLayout.HORIZONTAL);
-            mContentView = linearLayout;
-            mContentView.setBackgroundResource(
-                    com.android.internal.R.drawable.text_edit_paste_window);
-
-            LayoutInflater inflater = (LayoutInflater) mTextView.getContext().
-                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
-            LayoutParams wrapContent = new LayoutParams(
-                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-
-            mPasteTextView = (TextView) inflater.inflate(POPUP_TEXT_LAYOUT, null);
-            mPasteTextView.setLayoutParams(wrapContent);
-            mContentView.addView(mPasteTextView);
-            mPasteTextView.setText(com.android.internal.R.string.paste);
-            mPasteTextView.setOnClickListener(this);
-
-            mReplaceTextView = (TextView) inflater.inflate(POPUP_TEXT_LAYOUT, null);
-            mReplaceTextView.setLayoutParams(wrapContent);
-            mContentView.addView(mReplaceTextView);
-            mReplaceTextView.setText(com.android.internal.R.string.replace);
-            mReplaceTextView.setOnClickListener(this);
-        }
-
-        @Override
-        public void show() {
-            boolean canPaste = mTextView.canPaste();
-            boolean canSuggest = mTextView.isSuggestionsEnabled() && isCursorInsideSuggestionSpan();
-            mPasteTextView.setVisibility(canPaste ? View.VISIBLE : View.GONE);
-            mReplaceTextView.setVisibility(canSuggest ? View.VISIBLE : View.GONE);
-
-            if (!canPaste && !canSuggest) return;
-
-            super.show();
-        }
-
-        @Override
-        public void onClick(View view) {
-            if (view == mPasteTextView && mTextView.canPaste()) {
-                mTextView.onTextContextMenuItem(TextView.ID_PASTE);
-                hide();
-            } else if (view == mReplaceTextView) {
-                onReplace();
-            }
-        }
-
-        @Override
-        protected int getTextOffset() {
-            return (mTextView.getSelectionStart() + mTextView.getSelectionEnd()) / 2;
-        }
-
-        @Override
-        protected int getVerticalLocalPosition(int line) {
-            return mTextView.getLayout().getLineTop(line) - mContentView.getMeasuredHeight();
-        }
-
-        @Override
-        protected int clipVertically(int positionY) {
-            if (positionY < 0) {
-                final int offset = getTextOffset();
-                final Layout layout = mTextView.getLayout();
-                final int line = layout.getLineForOffset(offset);
-                positionY += layout.getLineBottom(line) - layout.getLineTop(line);
-                positionY += mContentView.getMeasuredHeight();
-
-                // Assumes insertion and selection handles share the same height
-                final Drawable handle = mTextView.getContext().getDrawable(
-                        mTextView.mTextSelectHandleRes);
-                positionY += handle.getIntrinsicHeight();
-            }
-
-            return positionY;
-        }
-    }
-
     /**
      * A listener to call {@link InputMethodManager#updateCursorAnchorInfo(View, CursorAnchorInfo)}
      * while the input method is requesting the cursor/anchor position. Does nothing as long as
@@ -3348,7 +3311,7 @@
         // Minimum touch target size for handles
         private int mMinSize;
         // Indicates the line of text that the handle is on.
-        protected int mLine = -1;
+        protected int mPrevLine = -1;
 
         public HandleView(Drawable drawableLtr, Drawable drawableRtl) {
             super(mTextView.getContext());
@@ -3499,7 +3462,7 @@
                     addPositionToTouchUpFilter(offset);
                 }
                 final int line = layout.getLineForOffset(offset);
-                mLine = line;
+                mPrevLine = line;
 
                 mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX -
                         getHorizontalOffset() + getCursorOffset());
@@ -3839,19 +3802,22 @@
         public void updatePosition(float x, float y) {
             final int trueOffset = mTextView.getOffsetForPosition(x, y);
             final int currLine = mTextView.getLineAtCoordinate(y);
-            int offset = trueOffset;
-            boolean positionCursor = false;
 
+            // Don't select white space on different lines.
+            if (isWhitespaceLine(mPrevLine, currLine, trueOffset)) return;
+
+            boolean positionCursor = false;
+            int offset = trueOffset;
             int end = getWordEnd(offset, true);
             int start = getWordStart(offset);
 
             if (offset < mPrevOffset) {
                 // User is increasing the selection.
-                if (!mInWord || currLine < mLine) {
+                if (!mInWord || currLine < mPrevLine) {
                     // We're not in a word, or we're on a different line so we'll expand by
                     // word. First ensure the user has at least entered the next word.
                     int offsetToWord = Math.min((end - start) / 2, 2);
-                    if (offset <= end - offsetToWord || currLine < mLine) {
+                    if (offset <= end - offsetToWord || currLine < mPrevLine) {
                         offset = start;
                     } else {
                         offset = mPrevOffset;
@@ -3863,7 +3829,7 @@
                 positionCursor = true;
             } else if (offset - mTouchWordOffset > mPrevOffset) {
                 // User is shrinking the selection.
-                if (currLine > mLine) {
+                if (currLine > mPrevLine) {
                     // We're on a different line, so we'll snap to word boundaries.
                     offset = end;
                 }
@@ -3878,7 +3844,7 @@
                 final int selectionEnd = mTextView.getSelectionEnd();
                 if (offset >= selectionEnd) {
                     // We can't cross the handles so let's just constrain the Y value.
-                    int alteredOffset = mTextView.getOffsetAtCoordinate(mLine, x);
+                    int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x);
                     if (alteredOffset >= selectionEnd) {
                         // Can't pass the other drag handle.
                         offset = Math.max(0, selectionEnd - 1);
@@ -3939,6 +3905,10 @@
         public void updatePosition(float x, float y) {
             final int trueOffset = mTextView.getOffsetForPosition(x, y);
             final int currLine = mTextView.getLineAtCoordinate(y);
+
+            // Don't select white space on different lines.
+            if (isWhitespaceLine(mPrevLine, currLine, trueOffset)) return;
+
             int offset = trueOffset;
             boolean positionCursor = false;
 
@@ -3947,11 +3917,11 @@
 
             if (offset > mPrevOffset) {
                 // User is increasing the selection.
-                if (!mInWord || currLine > mLine) {
+                if (!mInWord || currLine > mPrevLine) {
                     // We're not in a word, or we're on a different line so we'll expand by
                     // word. First ensure the user has at least entered the next word.
                     int midPoint = Math.min((end - start) / 2, 2);
-                    if (offset >= start + midPoint || currLine > mLine) {
+                    if (offset >= start + midPoint || currLine > mPrevLine) {
                         offset = end;
                     } else {
                         offset = mPrevOffset;
@@ -3963,7 +3933,7 @@
                 positionCursor = true;
             } else if (offset + mTouchWordOffset < mPrevOffset) {
                 // User is shrinking the selection.
-                if (currLine > mLine) {
+                if (currLine > mPrevLine) {
                     // We're on a different line, so we'll snap to word boundaries.
                     offset = getWordStart(offset);
                 }
@@ -3977,7 +3947,7 @@
                 final int selectionStart = mTextView.getSelectionStart();
                 if (offset <= selectionStart) {
                     // We can't cross the handles so let's just constrain the Y value.
-                    int alteredOffset = mTextView.getOffsetAtCoordinate(mLine, x);
+                    int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x);
                     int length = mTextView.getText().length();
                     if (alteredOffset <= selectionStart) {
                         // Can't pass the other drag handle.
@@ -4002,6 +3972,36 @@
     }
 
     /**
+     * Checks whether selection is happening on a different line than previous and
+     * if that line only contains whitespace up to the touch location.
+     *
+     * @param prevLine The previous line the selection was on.
+     * @param currLine The current line being selected.
+     * @param offset The offset in the text where the touch occurred.
+     * @return Whether or not it was just a white space line being selected.
+     */
+    private boolean isWhitespaceLine(int prevLine, int currLine, int offset) {
+        if (prevLine == currLine) {
+            // Same line; don't care.
+            return false;
+        }
+        CharSequence text = mTextView.getText();
+        if (offset == text.length()) {
+            // No character at the last position.
+            return false;
+        }
+        int lineEndOffset = mTextView.getLayout().getLineEnd(currLine);
+        for (int cp, i = offset; i < lineEndOffset; i += Character.charCount(cp)) {
+            cp = Character.codePointAt(text, i);
+            if (!Character.isSpaceChar(cp) && !Character.isWhitespace(cp)) {
+                // There are non white space chars on the line.
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
      * A CursorController instance can be used to control a cursor in the text.
      */
     private interface CursorController extends ViewTreeObserver.OnTouchModeChangeListener {
@@ -4065,7 +4065,6 @@
     }
 
     class SelectionModifierCursorController implements CursorController {
-        private static final int DELAY_BEFORE_REPLACE_ACTION = 200; // milliseconds
         // The cursor controller handles, lazily created when shown.
         private SelectionStartHandleView mStartHandle;
         private SelectionEndHandleView mEndHandle;
@@ -4081,6 +4080,8 @@
         private int mStartOffset = -1;
         // Indicates whether the user is selecting text and using the drag accelerator.
         private boolean mDragAcceleratorActive;
+        // Indicates the line of text the drag accelerator is on.
+        private int mPrevLine = -1;
 
         SelectionModifierCursorController() {
             resetTouchOffsets();
@@ -4173,6 +4174,8 @@
                         }
                     }
 
+                    // New selection, reset line.
+                    mPrevLine = mTextView.getLineAtCoordinate(y);
                     mDownPositionX = x;
                     mDownPositionY = y;
                     mGestureStayedInTapRegion = true;
@@ -4229,6 +4232,13 @@
                             if (my > fingerOffset) my -= fingerOffset;
                             offset = mTextView.getOffsetForPosition(mx, my);
 
+                            int currLine = mTextView.getLineAtCoordinate(my);
+
+                            // Don't select white space on different lines.
+                            if (isWhitespaceLine(mPrevLine, currLine, offset)) return;
+
+                            mPrevLine = currLine;
+
                             // Perform the check for closeness at edge of view, if we're very close
                             // don't adjust the offset to be in front of the finger - otherwise the
                             // user can't select words at the edge.
@@ -4616,8 +4626,8 @@
 
                 // Otherwise the user inserted the composition.
                 String newText = TextUtils.substring(source, start, end);
-                EditOperation edit = new EditOperation(mEditor, false, "", dstart, newText);
-                recordEdit(edit);
+                EditOperation edit = new EditOperation(mEditor, "", dstart, newText);
+                recordEdit(edit, false /* forceMerge */);
                 return true;
             }
 
@@ -4636,11 +4646,15 @@
             // Build a new operation with all the information from this edit.
             String newText = TextUtils.substring(source, start, end);
             String oldText = TextUtils.substring(dest, dstart, dend);
-            EditOperation edit = new EditOperation(mEditor, forceMerge, oldText, dstart, newText);
-            recordEdit(edit);
+            EditOperation edit = new EditOperation(mEditor, oldText, dstart, newText);
+            recordEdit(edit, forceMerge);
         }
 
-        private void recordEdit(EditOperation edit) {
+        /**
+         * Fetches the last undo operation and checks to see if a new edit should be merged into it.
+         * If forceMerge is true then the new edit is always merged.
+         */
+        private void recordEdit(EditOperation edit, boolean forceMerge) {
             // Fetch the last edit operation and attempt to merge in the new edit.
             final UndoManager um = mEditor.mUndoManager;
             um.beginUpdate("Edit text");
@@ -4650,6 +4664,11 @@
                 // Add this as the first edit.
                 if (DEBUG_UNDO) Log.d(TAG, "filter: adding first op " + edit);
                 um.addOperation(edit, UndoManager.MERGE_MODE_NONE);
+            } else if (forceMerge) {
+                // Forced merges take priority because they could be the result of a non-user-edit
+                // change and this case should not create a new undo operation.
+                if (DEBUG_UNDO) Log.d(TAG, "filter: force merge " + edit);
+                lastEdit.forceMergeWith(edit);
             } else if (!mIsUserEdit) {
                 // An application directly modified the Editable outside of a text edit. Treat this
                 // as a new change and don't attempt to merge.
@@ -4725,7 +4744,6 @@
         private static final int TYPE_REPLACE = 2;
 
         private int mType;
-        private boolean mForceMerge;
         private String mOldText;
         private int mOldTextStart;
         private String mNewText;
@@ -4736,13 +4754,10 @@
 
         /**
          * Constructs an edit operation from a text input operation on editor that replaces the
-         * oldText starting at dstart with newText. If forceMerge is true then always forcibly
-         * merge this operation with any previous one.
+         * oldText starting at dstart with newText.
          */
-        public EditOperation(Editor editor, boolean forceMerge, String oldText, int dstart,
-                String newText) {
+        public EditOperation(Editor editor, String oldText, int dstart, String newText) {
             super(editor.mUndoOwner);
-            mForceMerge = forceMerge;
             mOldText = oldText;
             mNewText = newText;
 
@@ -4769,7 +4784,6 @@
         public EditOperation(Parcel src, ClassLoader loader) {
             super(src, loader);
             mType = src.readInt();
-            mForceMerge = src.readInt() != 0;
             mOldText = src.readString();
             mOldTextStart = src.readInt();
             mNewText = src.readString();
@@ -4781,7 +4795,6 @@
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mType);
-            dest.writeInt(mForceMerge ? 1 : 0);
             dest.writeString(mOldText);
             dest.writeInt(mOldTextStart);
             dest.writeString(mNewText);
@@ -4833,10 +4846,6 @@
                 Log.d(TAG, "mergeWith old " + this);
                 Log.d(TAG, "mergeWith new " + edit);
             }
-            if (edit.mForceMerge) {
-                forceMergeWith(edit);
-                return true;
-            }
             switch (mType) {
                 case TYPE_INSERT:
                     return mergeInsertWith(edit);
@@ -4894,7 +4903,7 @@
          * Forcibly creates a single merged edit operation by simulating the entire text
          * contents being replaced.
          */
-        private void forceMergeWith(EditOperation edit) {
+        public void forceMergeWith(EditOperation edit) {
             if (DEBUG_UNDO) Log.d(TAG, "forceMerge");
             Editor editor = getOwnerData();
 
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index f6d198b..0602944 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -53,8 +53,6 @@
  * only if {@link #setMeasureAllChildren(boolean) setConsiderGoneChildrenWhenMeasuring()}
  * is set to true.
  *
- * @attr ref android.R.styleable#FrameLayout_foreground
- * @attr ref android.R.styleable#FrameLayout_foregroundGravity
  * @attr ref android.R.styleable#FrameLayout_measureAllChildren
  */
 @RemoteView
@@ -64,13 +62,6 @@
     @ViewDebug.ExportedProperty(category = "measurement")
     boolean mMeasureAllChildren = false;
 
-    @ViewDebug.ExportedProperty(category = "drawing")
-    private Drawable mForeground;
-    private ColorStateList mForegroundTintList = null;
-    private PorterDuff.Mode mForegroundTintMode = null;
-    private boolean mHasForegroundTint = false;
-    private boolean mHasForegroundTintMode = false;
-
     @ViewDebug.ExportedProperty(category = "padding")
     private int mForegroundPaddingLeft = 0;
 
@@ -85,15 +76,6 @@
 
     private final Rect mSelfBounds = new Rect();
     private final Rect mOverlayBounds = new Rect();
-
-    @ViewDebug.ExportedProperty(category = "drawing")
-    private int mForegroundGravity = Gravity.FILL;
-
-    /** {@hide} */
-    @ViewDebug.ExportedProperty(category = "drawing")
-    protected boolean mForegroundInPadding = true;
-
-    boolean mForegroundBoundsChanged = false;
     
     private final ArrayList<View> mMatchParentChildren = new ArrayList<View>(1);
     
@@ -115,48 +97,12 @@
 
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, com.android.internal.R.styleable.FrameLayout, defStyleAttr, defStyleRes);
-
-        mForegroundGravity = a.getInt(
-                com.android.internal.R.styleable.FrameLayout_foregroundGravity, mForegroundGravity);
-
-        final Drawable d = a.getDrawable(com.android.internal.R.styleable.FrameLayout_foreground);
-        if (d != null) {
-            setForeground(d);
-        }
         
         if (a.getBoolean(com.android.internal.R.styleable.FrameLayout_measureAllChildren, false)) {
             setMeasureAllChildren(true);
         }
 
-        if (a.hasValue(R.styleable.FrameLayout_foregroundTintMode)) {
-            mForegroundTintMode = Drawable.parseTintMode(a.getInt(
-                    R.styleable.FrameLayout_foregroundTintMode, -1), mForegroundTintMode);
-            mHasForegroundTintMode = true;
-        }
-
-        if (a.hasValue(R.styleable.FrameLayout_foregroundTint)) {
-            mForegroundTintList = a.getColorStateList(R.styleable.FrameLayout_foregroundTint);
-            mHasForegroundTint = true;
-        }
-
-        mForegroundInPadding = a.getBoolean(R.styleable.FrameLayout_foregroundInsidePadding, true);
-
         a.recycle();
-
-        applyForegroundTint();
-    }
-
-    /**
-     * Describes how the foreground is positioned.
-     *
-     * @return foreground gravity.
-     *
-     * @see #setForegroundGravity(int)
-     *
-     * @attr ref android.R.styleable#FrameLayout_foregroundGravity
-     */
-    public int getForegroundGravity() {
-        return mForegroundGravity;
     }
 
     /**
@@ -166,25 +112,18 @@
      *
      * @see #getForegroundGravity()
      *
-     * @attr ref android.R.styleable#FrameLayout_foregroundGravity
+     * @attr ref android.R.styleable#View_foregroundGravity
      */
     @android.view.RemotableViewMethod
     public void setForegroundGravity(int foregroundGravity) {
-        if (mForegroundGravity != foregroundGravity) {
-            if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
-                foregroundGravity |= Gravity.START;
-            }
+        if (getForegroundGravity() != foregroundGravity) {
+            super.setForegroundGravity(foregroundGravity);
 
-            if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
-                foregroundGravity |= Gravity.TOP;
-            }
-
-            mForegroundGravity = foregroundGravity;
-
-
-            if (mForegroundGravity == Gravity.FILL && mForeground != null) {
+            // calling get* again here because the set above may apply default constraints
+            final Drawable foreground = getForeground();
+            if (getForegroundGravity() == Gravity.FILL && foreground != null) {
                 Rect padding = new Rect();
-                if (mForeground.getPadding(padding)) {
+                if (foreground.getPadding(padding)) {
                     mForegroundPaddingLeft = padding.left;
                     mForegroundPaddingTop = padding.top;
                     mForegroundPaddingRight = padding.right;
@@ -201,53 +140,6 @@
         }
     }
 
-    @Override
-    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
-        super.onVisibilityChanged(changedView, visibility);
-
-        final Drawable dr = mForeground;
-        if (dr != null) {
-            final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
-            if (visible != dr.isVisible()) {
-                dr.setVisible(visible, false);
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected boolean verifyDrawable(Drawable who) {
-        return super.verifyDrawable(who) || (who == mForeground);
-    }
-
-    @Override
-    public void jumpDrawablesToCurrentState() {
-        super.jumpDrawablesToCurrentState();
-        if (mForeground != null) mForeground.jumpToCurrentState();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected void drawableStateChanged() {
-        super.drawableStateChanged();
-        if (mForeground != null && mForeground.isStateful()) {
-            mForeground.setState(getDrawableState());
-        }
-    }
-
-    @Override
-    public void drawableHotspotChanged(float x, float y) {
-        super.drawableHotspotChanged(x, y);
-
-        if (mForeground != null) {
-            mForeground.setHotspot(x, y);
-        }
-    }
-
     /**
      * Returns a set of layout parameters with a width of
      * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT},
@@ -258,161 +150,23 @@
         return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
     }
 
-    /**
-     * Supply a Drawable that is to be rendered on top of all of the child
-     * views in the frame layout.  Any padding in the Drawable will be taken
-     * into account by ensuring that the children are inset to be placed
-     * inside of the padding area.
-     * 
-     * @param d The Drawable to be drawn on top of the children.
-     * 
-     * @attr ref android.R.styleable#FrameLayout_foreground
-     */
-    public void setForeground(Drawable d) {
-        if (mForeground != d) {
-            if (mForeground != null) {
-                mForeground.setCallback(null);
-                unscheduleDrawable(mForeground);
-            }
-
-            mForeground = d;
-            mForegroundPaddingLeft = 0;
-            mForegroundPaddingTop = 0;
-            mForegroundPaddingRight = 0;
-            mForegroundPaddingBottom = 0;
-
-            if (d != null) {
-                setWillNotDraw(false);
-                d.setCallback(this);
-                d.setLayoutDirection(getLayoutDirection());
-                if (d.isStateful()) {
-                    d.setState(getDrawableState());
-                }
-                applyForegroundTint();
-                if (mForegroundGravity == Gravity.FILL) {
-                    Rect padding = new Rect();
-                    if (d.getPadding(padding)) {
-                        mForegroundPaddingLeft = padding.left;
-                        mForegroundPaddingTop = padding.top;
-                        mForegroundPaddingRight = padding.right;
-                        mForegroundPaddingBottom = padding.bottom;
-                    }
-                }
-            }  else {
-                setWillNotDraw(true);
-            }
-            requestLayout();
-            invalidate();
-        }
-    }
-
-    /**
-     * Returns the drawable used as the foreground of this FrameLayout. The
-     * foreground drawable, if non-null, is always drawn on top of the children.
-     *
-     * @return A Drawable or null if no foreground was set.
-     */
-    public Drawable getForeground() {
-        return mForeground;
-    }
-
-    /**
-     * Applies a tint to the foreground drawable. Does not modify the current
-     * tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
-     * <p>
-     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
-     * mutate the drawable and apply the specified tint and tint mode using
-     * {@link Drawable#setTintList(ColorStateList)}.
-     *
-     * @param tint the tint to apply, may be {@code null} to clear tint
-     *
-     * @attr ref android.R.styleable#FrameLayout_foregroundTint
-     * @see #getForegroundTintList()
-     * @see Drawable#setTintList(ColorStateList)
-     */
-    public void setForegroundTintList(@Nullable ColorStateList tint) {
-        mForegroundTintList = tint;
-        mHasForegroundTint = true;
-
-        applyForegroundTint();
-    }
-
-    /**
-     * @return the tint applied to the foreground drawable
-     * @attr ref android.R.styleable#FrameLayout_foregroundTint
-     * @see #setForegroundTintList(ColorStateList)
-     */
-    @Nullable
-    public ColorStateList getForegroundTintList() {
-        return mForegroundTintList;
-    }
-
-    /**
-     * Specifies the blending mode used to apply the tint specified by
-     * {@link #setForegroundTintList(ColorStateList)}} to the foreground drawable.
-     * The default mode is {@link PorterDuff.Mode#SRC_IN}.
-     *
-     * @param tintMode the blending mode used to apply the tint, may be
-     *                 {@code null} to clear tint
-     * @attr ref android.R.styleable#FrameLayout_foregroundTintMode
-     * @see #getForegroundTintMode()
-     * @see Drawable#setTintMode(PorterDuff.Mode)
-     */
-    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
-        mForegroundTintMode = tintMode;
-        mHasForegroundTintMode = true;
-
-        applyForegroundTint();
-    }
-
-    /**
-     * @return the blending mode used to apply the tint to the foreground
-     *         drawable
-     * @attr ref android.R.styleable#FrameLayout_foregroundTintMode
-     * @see #setForegroundTintMode(PorterDuff.Mode)
-     */
-    @Nullable
-    public PorterDuff.Mode getForegroundTintMode() {
-        return mForegroundTintMode;
-    }
-
-    private void applyForegroundTint() {
-        if (mForeground != null && (mHasForegroundTint || mHasForegroundTintMode)) {
-            mForeground = mForeground.mutate();
-
-            if (mHasForegroundTint) {
-                mForeground.setTintList(mForegroundTintList);
-            }
-
-            if (mHasForegroundTintMode) {
-                mForeground.setTintMode(mForegroundTintMode);
-            }
-
-            // The drawable (or one of its children) may not have been
-            // stateful before applying the tint, so let's try again.
-            if (mForeground.isStateful()) {
-                mForeground.setState(getDrawableState());
-            }
-        }
-    }
-
     int getPaddingLeftWithForeground() {
-        return mForegroundInPadding ? Math.max(mPaddingLeft, mForegroundPaddingLeft) :
+        return isForegroundInsidePadding() ? Math.max(mPaddingLeft, mForegroundPaddingLeft) :
             mPaddingLeft + mForegroundPaddingLeft;
     }
 
     int getPaddingRightWithForeground() {
-        return mForegroundInPadding ? Math.max(mPaddingRight, mForegroundPaddingRight) :
+        return isForegroundInsidePadding() ? Math.max(mPaddingRight, mForegroundPaddingRight) :
             mPaddingRight + mForegroundPaddingRight;
     }
 
     private int getPaddingTopWithForeground() {
-        return mForegroundInPadding ? Math.max(mPaddingTop, mForegroundPaddingTop) :
+        return isForegroundInsidePadding() ? Math.max(mPaddingTop, mForegroundPaddingTop) :
             mPaddingTop + mForegroundPaddingTop;
     }
 
     private int getPaddingBottomWithForeground() {
-        return mForegroundInPadding ? Math.max(mPaddingBottom, mForegroundPaddingBottom) :
+        return isForegroundInsidePadding() ? Math.max(mPaddingBottom, mForegroundPaddingBottom) :
             mPaddingBottom + mForegroundPaddingBottom;
     }
 
@@ -527,8 +281,6 @@
         final int parentTop = getPaddingTopWithForeground();
         final int parentBottom = bottom - top - getPaddingBottomWithForeground();
 
-        mForegroundBoundsChanged = true;
-        
         for (int i = 0; i < count; i++) {
             final View child = getChildAt(i);
             if (child.getVisibility() != GONE) {
@@ -585,62 +337,6 @@
     }
 
     /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        super.onSizeChanged(w, h, oldw, oldh);
-        mForegroundBoundsChanged = true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void draw(Canvas canvas) {
-        super.draw(canvas);
-
-        if (mForeground != null) {
-            final Drawable foreground = mForeground;
-
-            if (mForegroundBoundsChanged) {
-                mForegroundBoundsChanged = false;
-                final Rect selfBounds = mSelfBounds;
-                final Rect overlayBounds = mOverlayBounds;
-
-                final int w = mRight-mLeft;
-                final int h = mBottom-mTop;
-
-                if (mForegroundInPadding) {
-                    selfBounds.set(0, 0, w, h);
-                } else {
-                    selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
-                }
-
-                final int layoutDirection = getLayoutDirection();
-                Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
-                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds,
-                        layoutDirection);
-                foreground.setBounds(overlayBounds);
-            }
-            
-            foreground.draw(canvas);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean gatherTransparentRegion(Region region) {
-        boolean opaque = super.gatherTransparentRegion(region);
-        if (region != null && mForeground != null) {
-            applyDrawableToTransparentRegion(mForeground, region);
-        }
-        return opaque;
-    }
-
-    /**
      * Sets whether to consider all children, or just those in
      * the VISIBLE or INVISIBLE state, when measuring. Defaults to false.
      *
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index af5a8bf..b187c1c 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -1209,13 +1209,13 @@
         switch (keyCode) {
             
         case KeyEvent.KEYCODE_DPAD_LEFT:
-            if (movePrevious()) {
+            if (moveDirection(-1)) {
                 playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
                 return true;
             }
             break;
         case KeyEvent.KEYCODE_DPAD_RIGHT:
-            if (moveNext()) {
+            if (moveDirection(1)) {
                 playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
                 return true;
             }
@@ -1255,18 +1255,12 @@
         return super.onKeyUp(keyCode, event);
     }
     
-    boolean movePrevious() {
-        if (mItemCount > 0 && mSelectedPosition > 0) {
-            scrollToChild(mSelectedPosition - mFirstPosition - 1);
-            return true;
-        } else {
-            return false;
-        }
-    }
+    boolean moveDirection(int direction) {
+        direction = isLayoutRtl() ? -direction : direction;
+        int targetPosition = mSelectedPosition + direction;
 
-    boolean moveNext() {
-        if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) {
-            scrollToChild(mSelectedPosition - mFirstPosition + 1);
+        if (mItemCount > 0 && targetPosition >= 0 && targetPosition < mItemCount) {
+            scrollToChild(targetPosition - mFirstPosition);
             return true;
         } else {
             return false;
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index c6e3dc8..be0ca71 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
+import android.os.Bundle;
 import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.MathUtils;
@@ -32,12 +33,15 @@
 import android.view.ViewGroup;
 import android.view.ViewRootImpl;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo;
 import android.view.animation.GridLayoutAnimationController;
 import android.widget.RemoteViews.RemoteView;
 
+import com.android.internal.R;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -117,7 +121,7 @@
     }
 
     public GridView(Context context, AttributeSet attrs) {
-        this(context, attrs, com.android.internal.R.attr.gridViewStyle);
+        this(context, attrs, R.attr.gridViewStyle);
     }
 
     public GridView(Context context, AttributeSet attrs, int defStyleAttr) {
@@ -128,30 +132,30 @@
         super(context, attrs, defStyleAttr, defStyleRes);
 
         final TypedArray a = context.obtainStyledAttributes(
-                attrs, com.android.internal.R.styleable.GridView, defStyleAttr, defStyleRes);
+                attrs, R.styleable.GridView, defStyleAttr, defStyleRes);
 
         int hSpacing = a.getDimensionPixelOffset(
-                com.android.internal.R.styleable.GridView_horizontalSpacing, 0);
+                R.styleable.GridView_horizontalSpacing, 0);
         setHorizontalSpacing(hSpacing);
 
         int vSpacing = a.getDimensionPixelOffset(
-                com.android.internal.R.styleable.GridView_verticalSpacing, 0);
+                R.styleable.GridView_verticalSpacing, 0);
         setVerticalSpacing(vSpacing);
 
-        int index = a.getInt(com.android.internal.R.styleable.GridView_stretchMode, STRETCH_COLUMN_WIDTH);
+        int index = a.getInt(R.styleable.GridView_stretchMode, STRETCH_COLUMN_WIDTH);
         if (index >= 0) {
             setStretchMode(index);
         }
 
-        int columnWidth = a.getDimensionPixelOffset(com.android.internal.R.styleable.GridView_columnWidth, -1);
+        int columnWidth = a.getDimensionPixelOffset(R.styleable.GridView_columnWidth, -1);
         if (columnWidth > 0) {
             setColumnWidth(columnWidth);
         }
 
-        int numColumns = a.getInt(com.android.internal.R.styleable.GridView_numColumns, 1);
+        int numColumns = a.getInt(R.styleable.GridView_numColumns, 1);
         setNumColumns(numColumns);
 
-        index = a.getInt(com.android.internal.R.styleable.GridView_gravity, -1);
+        index = a.getInt(R.styleable.GridView_gravity, -1);
         if (index >= 0) {
             setGravity(index);
         }
@@ -2356,6 +2360,36 @@
         final CollectionInfo collectionInfo = CollectionInfo.obtain(
                 rowsCount, columnsCount, false, selectionMode);
         info.setCollectionInfo(collectionInfo);
+
+        if (columnsCount > 0 || rowsCount > 0) {
+            info.addAction(AccessibilityAction.ACTION_SCROLL_TO_POSITION);
+        }
+    }
+
+    /** @hide */
+    @Override
+    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+        if (super.performAccessibilityActionInternal(action, arguments)) {
+            return true;
+        }
+
+        switch (action) {
+            case R.id.accessibilityActionScrollToPosition: {
+                // GridView only supports scrolling in one direction, so we can
+                // ignore the column argument.
+                final int numColumns = getNumColumns();
+                final int row = arguments.getInt(AccessibilityNodeInfo.ACTION_ARGUMENT_ROW_INT, -1);
+                final int position = Math.min(row * numColumns, getCount() - 1);
+                if (row >= 0) {
+                    // The accessibility service gets data asynchronously, so
+                    // we'll be a little lenient by clamping the last position.
+                    smoothScrollToPosition(position);
+                    return true;
+                }
+            } break;
+        }
+
+        return false;
     }
 
     @Override
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 041796b..6d2f368 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -687,12 +687,19 @@
         return mDrawMatrix;
     }
 
+    /**
+     * Adds a transformation {@link Matrix} that is applied
+     * to the view's drawable when it is drawn.  Allows custom scaling,
+     * translation, and perspective distortion.
+     * 
+     * @param matrix the transformation parameters in matrix form
+     */
     public void setImageMatrix(Matrix matrix) {
-        // collaps null and identity to just null
+        // collapse null and identity to just null
         if (matrix != null && matrix.isIdentity()) {
             matrix = null;
         }
-        
+
         // don't invalidate unless we're actually changing our matrix
         if (matrix == null && !mMatrix.isIdentity() ||
                 matrix != null && !mMatrix.equals(matrix)) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index ee2c055..def5929 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.os.Bundle;
 import android.os.Trace;
 import com.android.internal.R;
 import com.android.internal.util.Predicate;
@@ -42,6 +43,7 @@
 import android.view.ViewParent;
 import android.view.ViewRootImpl;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo;
 import android.view.accessibility.AccessibilityNodeProvider;
@@ -3893,6 +3895,33 @@
         final CollectionInfo collectionInfo = CollectionInfo.obtain(
                 rowsCount, 1, false, selectionMode);
         info.setCollectionInfo(collectionInfo);
+
+        if (rowsCount > 0) {
+            info.addAction(AccessibilityAction.ACTION_SCROLL_TO_POSITION);
+        }
+    }
+
+    /** @hide */
+    @Override
+    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+        if (super.performAccessibilityActionInternal(action, arguments)) {
+            return true;
+        }
+
+        switch (action) {
+            case R.id.accessibilityActionScrollToPosition: {
+                final int row = arguments.getInt(AccessibilityNodeInfo.ACTION_ARGUMENT_ROW_INT, -1);
+                final int position = Math.min(row, getCount() - 1);
+                if (row >= 0) {
+                    // The accessibility service gets data asynchronously, so
+                    // we'll be a little lenient by clamping the last position.
+                    smoothScrollToPosition(position);
+                    return true;
+                }
+            } break;
+        }
+
+        return false;
     }
 
     @Override
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 50d701a..16353e8 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -316,7 +316,7 @@
                 mProgressTintInfo = new ProgressTintInfo();
             }
             mProgressTintInfo.mProgressTintMode = Drawable.parseTintMode(a.getInt(
-                    R.styleable.ProgressBar_progressBackgroundTintMode, -1), null);
+                    R.styleable.ProgressBar_progressTintMode, -1), null);
             mProgressTintInfo.mHasProgressTintMode = true;
         }
 
@@ -334,7 +334,7 @@
                 mProgressTintInfo = new ProgressTintInfo();
             }
             mProgressTintInfo.mProgressBackgroundTintMode = Drawable.parseTintMode(a.getInt(
-                    R.styleable.ProgressBar_progressTintMode, -1), null);
+                    R.styleable.ProgressBar_progressBackgroundTintMode, -1), null);
             mProgressTintInfo.mHasProgressBackgroundTintMode = true;
         }
 
@@ -365,7 +365,7 @@
             mProgressTintInfo.mHasSecondaryProgressTint = true;
         }
 
-        if (a.hasValue(R.styleable.ProgressBar_indeterminateTint)) {
+        if (a.hasValue(R.styleable.ProgressBar_indeterminateTintMode)) {
             if (mProgressTintInfo == null) {
                 mProgressTintInfo = new ProgressTintInfo();
             }
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 20aa972..52e1728 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -79,8 +79,10 @@
     // Transparent alpha level
     private static final int ALPHA_TRANSPARENT = 0;
 
-    private static final int DEGREES_FOR_ONE_HOUR = 30;
-    private static final int DEGREES_FOR_ONE_MINUTE = 6;
+    private static final int HOURS_IN_DAY = 24;
+    private static final int MINUTES_IN_HOUR = 60;
+    private static final int DEGREES_FOR_ONE_HOUR = 360 / HOURS_IN_DAY;
+    private static final int DEGREES_FOR_ONE_MINUTE = 360 / MINUTES_IN_HOUR;
 
     private static final int[] HOURS_NUMBERS = {12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
     private static final int[] HOURS_NUMBERS_24 = {0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
@@ -122,8 +124,9 @@
     private final Paint mPaintCenter = new Paint();
 
     private final Paint[][] mPaintSelector = new Paint[2][3];
-    private final int[][] mColorSelector = new int[2][3];
-    private final IntHolder[][] mAlphaSelector = new IntHolder[2][3];
+
+    private final int mSelectorColor;
+    private final int mSelectorDotColor;
 
     private final Paint mPaintBackground = new Paint();
 
@@ -139,14 +142,15 @@
     private final float[] mInnerTextX = new float[12];
     private final float[] mInnerTextY = new float[12];
 
-    private final int[] mLineLength = new int[3];
-    private final int[] mSelectionDegrees = new int[3];
+    private final int[] mSelectionDegrees = new int[2];
 
     private final ArrayList<Animator> mHoursToMinutesAnims = new ArrayList<>();
     private final ArrayList<Animator> mMinuteToHoursAnims = new ArrayList<>();
 
     private final RadialPickerTouchHelper mTouchHelper;
 
+    private final Path mSelectorPath = new Path();
+
     private boolean mIs24HourMode;
     private boolean mShowHours;
 
@@ -165,13 +169,13 @@
     private int mYCenter;
     private int mCircleRadius;
 
-    private int mMinHypotenuseForInnerNumber;
-    private int mMaxHypotenuseForOuterNumber;
-    private int mHalfwayHypotenusePoint;
+    private int mMinDistForInnerNumber;
+    private int mMaxDistForOuterNumber;
+    private int mHalfwayDist;
 
     private String[] mOuterTextHours;
     private String[] mInnerTextHours;
-    private String[] mOuterTextMinutes;
+    private String[] mMinutesText;
     private AnimatorSet mTransition;
 
     private int mAmOrPm;
@@ -316,11 +320,6 @@
         for (int i = 0; i < mAlpha.length; i++) {
             mAlpha[i] = new IntHolder(ALPHA_OPAQUE);
         }
-        for (int i = 0; i < mAlphaSelector.length; i++) {
-            for (int j = 0; j < mAlphaSelector[i].length; j++) {
-                mAlphaSelector[i][j] = new IntHolder(ALPHA_OPAQUE);
-            }
-        }
 
         mTextColor[HOURS] = a.getColorStateList(R.styleable.TimePicker_numbersTextColor);
         mTextColor[HOURS_INNER] = a.getColorStateList(R.styleable.TimePicker_numbersInnerTextColor);
@@ -345,33 +344,28 @@
         final int[] activatedStateSet = StateSet.get(
                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED);
 
+        mSelectorColor = selectorActivatedColor;
+        mSelectorDotColor = mTextColor[HOURS].getColorForState(activatedStateSet, 0);
+
         mPaintSelector[HOURS][SELECTOR_CIRCLE] = new Paint();
         mPaintSelector[HOURS][SELECTOR_CIRCLE].setAntiAlias(true);
-        mColorSelector[HOURS][SELECTOR_CIRCLE] = selectorActivatedColor;
 
         mPaintSelector[HOURS][SELECTOR_DOT] = new Paint();
         mPaintSelector[HOURS][SELECTOR_DOT].setAntiAlias(true);
-        mColorSelector[HOURS][SELECTOR_DOT] =
-                mTextColor[HOURS].getColorForState(activatedStateSet, 0);
 
         mPaintSelector[HOURS][SELECTOR_LINE] = new Paint();
         mPaintSelector[HOURS][SELECTOR_LINE].setAntiAlias(true);
         mPaintSelector[HOURS][SELECTOR_LINE].setStrokeWidth(2);
-        mColorSelector[HOURS][SELECTOR_LINE] = selectorActivatedColor;
 
         mPaintSelector[MINUTES][SELECTOR_CIRCLE] = new Paint();
         mPaintSelector[MINUTES][SELECTOR_CIRCLE].setAntiAlias(true);
-        mColorSelector[MINUTES][SELECTOR_CIRCLE] = selectorActivatedColor;
 
         mPaintSelector[MINUTES][SELECTOR_DOT] = new Paint();
         mPaintSelector[MINUTES][SELECTOR_DOT].setAntiAlias(true);
-        mColorSelector[MINUTES][SELECTOR_DOT] =
-                mTextColor[MINUTES].getColorForState(activatedStateSet, 0);
 
         mPaintSelector[MINUTES][SELECTOR_LINE] = new Paint();
         mPaintSelector[MINUTES][SELECTOR_LINE].setAntiAlias(true);
         mPaintSelector[MINUTES][SELECTOR_LINE].setStrokeWidth(2);
-        mColorSelector[MINUTES][SELECTOR_LINE] = selectorActivatedColor;
 
         mPaintBackground.setColor(a.getColor(R.styleable.TimePicker_numbersBackgroundColor,
                 context.getColor(R.color.timepicker_default_numbers_background_color_material)));
@@ -469,11 +463,10 @@
     private void setCurrentHourInternal(int hour, boolean callback, boolean autoAdvance) {
         final int degrees = (hour % 12) * DEGREES_FOR_ONE_HOUR;
         mSelectionDegrees[HOURS] = degrees;
-        mSelectionDegrees[HOURS_INNER] = degrees;
 
         // 0 is 12 AM (midnight) and 12 is 12 PM (noon).
         final int amOrPm = (hour == 0 || (hour % 24) < 12) ? AM : PM;
-        final boolean isOnInnerCircle = mIs24HourMode && hour >= 1 && hour <= 12;
+        final boolean isOnInnerCircle = getInnerCircleForHour(hour);
         if (mAmOrPm != amOrPm || mIsOnInnerCircle != isOnInnerCircle) {
             mAmOrPm = amOrPm;
             mIsOnInnerCircle = isOnInnerCircle;
@@ -495,8 +488,7 @@
      * @return the current hour between 0 and 23 (inclusive)
      */
     public int getCurrentHour() {
-        return getHourForDegrees(
-                mSelectionDegrees[mIsOnInnerCircle ? HOURS_INNER : HOURS], mIsOnInnerCircle);
+        return getHourForDegrees(mSelectionDegrees[HOURS], mIsOnInnerCircle);
     }
 
     private int getHourForDegrees(int degrees, boolean innerCircle) {
@@ -504,11 +496,11 @@
         if (mIs24HourMode) {
             // Convert the 12-hour value into 24-hour time based on where the
             // selector is positioned.
-            if (innerCircle && hour == 0) {
-                // Inner circle is 1 through 12.
+            if (!innerCircle && hour == 0) {
+                // Outer circle is 1 through 12.
                 hour = 12;
-            } else if (!innerCircle && hour != 0) {
-                // Outer circle is 13 through 23 and 0.
+            } else if (innerCircle && hour != 0) {
+                // Inner circle is 13 through 23 and 0.
                 hour += 12;
             }
         } else if (mAmOrPm == PM) {
@@ -517,6 +509,9 @@
         return hour;
     }
 
+    /**
+     * @param hour the hour in 24-hour time or 12-hour time
+     */
     private int getDegreesForHour(int hour) {
         // Convert to be 0-11.
         if (mIs24HourMode) {
@@ -529,12 +524,19 @@
         return hour * DEGREES_FOR_ONE_HOUR;
     }
 
+    /**
+     * @param hour the hour in 24-hour time or 12-hour time
+     */
+    private boolean getInnerCircleForHour(int hour) {
+        return mIs24HourMode && (hour == 0 || hour > 12);
+    }
+
     public void setCurrentMinute(int minute) {
         setCurrentMinuteInternal(minute, true);
     }
 
     private void setCurrentMinuteInternal(int minute, boolean callback) {
-        mSelectionDegrees[MINUTES] = (minute % 60) * DEGREES_FOR_ONE_MINUTE;
+        mSelectionDegrees[MINUTES] = (minute % MINUTES_IN_HOUR) * DEGREES_FOR_ONE_MINUTE;
 
         invalidate();
 
@@ -579,6 +581,7 @@
 
         initData();
         invalidate();
+        mTouchHelper.invalidateRoot();
     }
 
     public void showMinutes(boolean animate) {
@@ -594,14 +597,15 @@
 
         initData();
         invalidate();
+        mTouchHelper.invalidateRoot();
     }
 
     private void initHoursAndMinutesText() {
         // Initialize the hours and minutes numbers.
         for (int i = 0; i < 12; i++) {
             mHours12Texts[i] = String.format("%d", HOURS_NUMBERS[i]);
-            mOuterHours24Texts[i] = String.format("%02d", HOURS_NUMBERS_24[i]);
-            mInnerHours24Texts[i] = String.format("%d", HOURS_NUMBERS[i]);
+            mInnerHours24Texts[i] = String.format("%02d", HOURS_NUMBERS_24[i]);
+            mOuterHours24Texts[i] = String.format("%d", HOURS_NUMBERS[i]);
             mMinutesTexts[i] = String.format("%02d", MINUTES_NUMBERS[i]);
         }
     }
@@ -612,22 +616,16 @@
             mInnerTextHours = mInnerHours24Texts;
         } else {
             mOuterTextHours = mHours12Texts;
-            mInnerTextHours = null;
+            mInnerTextHours = mHours12Texts;
         }
 
-        mOuterTextMinutes = mMinutesTexts;
+        mMinutesText = mMinutesTexts;
 
         final int hoursAlpha = mShowHours ? ALPHA_OPAQUE : ALPHA_TRANSPARENT;
         mAlpha[HOURS].setValue(hoursAlpha);
-        mAlphaSelector[HOURS][SELECTOR_CIRCLE].setValue(hoursAlpha);
-        mAlphaSelector[HOURS][SELECTOR_DOT].setValue(hoursAlpha);
-        mAlphaSelector[HOURS][SELECTOR_LINE].setValue(hoursAlpha);
 
         final int minutesAlpha = mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE;
         mAlpha[MINUTES].setValue(minutesAlpha);
-        mAlphaSelector[MINUTES][SELECTOR_CIRCLE].setValue(minutesAlpha);
-        mAlphaSelector[MINUTES][SELECTOR_DOT].setValue(minutesAlpha);
-        mAlphaSelector[MINUTES][SELECTOR_LINE].setValue(minutesAlpha);
     }
 
     @Override
@@ -640,9 +638,9 @@
         mYCenter = getHeight() / 2;
         mCircleRadius = Math.min(mXCenter, mYCenter);
 
-        mMinHypotenuseForInnerNumber = mCircleRadius - mTextInset[HOURS_INNER] - mSelectorRadius;
-        mMaxHypotenuseForOuterNumber = mCircleRadius - mTextInset[HOURS] + mSelectorRadius;
-        mHalfwayHypotenusePoint = mCircleRadius - (mTextInset[HOURS] + mTextInset[HOURS_INNER]) / 2;
+        mMinDistForInnerNumber = mCircleRadius - mTextInset[HOURS_INNER] - mSelectorRadius;
+        mMaxDistForOuterNumber = mCircleRadius - mTextInset[HOURS] + mSelectorRadius;
+        mHalfwayDist = mCircleRadius - (mTextInset[HOURS] + mTextInset[HOURS_INNER]) / 2;
 
         calculatePositionsHours();
         calculatePositionsMinutes();
@@ -675,7 +673,7 @@
                     mOuterTextHours, mOuterTextX[HOURS], mOuterTextY[HOURS], mPaint[HOURS],
                     hoursAlpha, !mIsOnInnerCircle, mSelectionDegrees[HOURS], false);
 
-            // Draw inner hours (12-23) for 24-hour time.
+            // Draw inner hours (13-00) for 24-hour time.
             if (mIs24HourMode && mInnerTextHours != null) {
                 drawTextElements(canvas, mTextSize[HOURS_INNER], mTypeface, mTextColor[HOURS_INNER],
                         mInnerTextHours, mInnerTextX, mInnerTextY, mPaint[HOURS], hoursAlpha,
@@ -687,6 +685,7 @@
     private void drawMinutes(Canvas canvas, float alphaMod) {
         final int minutesAlpha = (int) (mAlpha[MINUTES].getValue() * alphaMod + 0.5f);
         if (minutesAlpha > 0) {
+            // Draw the minute selector under the elements.
             drawSelector(canvas, MINUTES, mSelectorPath, alphaMod);
 
             // Exclude the selector region, then draw minutes with no
@@ -694,7 +693,7 @@
             canvas.save(Canvas.CLIP_SAVE_FLAG);
             canvas.clipPath(mSelectorPath, Region.Op.DIFFERENCE);
             drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mTextColor[MINUTES],
-                    mOuterTextMinutes, mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES],
+                    mMinutesText, mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES],
                     minutesAlpha, false, 0, false);
             canvas.restore();
 
@@ -703,7 +702,7 @@
             canvas.save(Canvas.CLIP_SAVE_FLAG);
             canvas.clipPath(mSelectorPath, Region.Op.INTERSECT);
             drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mTextColor[MINUTES],
-                    mOuterTextMinutes, mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES],
+                    mMinutesText, mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES],
                     minutesAlpha, true, mSelectionDegrees[MINUTES], true);
             canvas.restore();
         }
@@ -714,69 +713,61 @@
         canvas.drawCircle(mXCenter, mYCenter, mCenterDotRadius, mPaintCenter);
     }
 
+    private int applyAlpha(int argb, int alpha) {
+        final int srcAlpha = (argb >> 24) & 0xFF;
+        final int dstAlpha = (int) (srcAlpha * (alpha / 255.0) + 0.5f);
+        return (0xFFFFFF & argb) | (dstAlpha << 24);
+    }
+
     private int getMultipliedAlpha(int argb, int alpha) {
         return (int) (Color.alpha(argb) * (alpha / 255.0) + 0.5);
     }
 
-    private final Path mSelectorPath = new Path();
-
     private void drawSelector(Canvas canvas, int index, Path selectorPath, float alphaMod) {
+        final int alpha = (int) (mAlpha[index % 2].getValue() * alphaMod + 0.5f);
+        final int color = applyAlpha(mSelectorColor, alpha);
+
         // Calculate the current radius at which to place the selection circle.
-        mLineLength[index] = mCircleRadius - mTextInset[index];
+        final int selRadius = mSelectorRadius;
+        final int selLength = mCircleRadius - mTextInset[index];
+        final double selAngleRad = Math.toRadians(mSelectionDegrees[index % 2]);
+        final float selCenterX = mXCenter + selLength * (float) Math.sin(selAngleRad);
+        final float selCenterY = mYCenter - selLength * (float) Math.cos(selAngleRad);
 
-        final double selectionRadians = Math.toRadians(mSelectionDegrees[index]);
-
-        float pointX = mXCenter + (int) (mLineLength[index] * Math.sin(selectionRadians));
-        float pointY = mYCenter - (int) (mLineLength[index] * Math.cos(selectionRadians));
-
-        int color;
-        int alpha;
-        Paint paint;
-
-        // Draw the selection circle
-        color = mColorSelector[index % 2][SELECTOR_CIRCLE];
-        alpha = (int) (mAlphaSelector[index % 2][SELECTOR_CIRCLE].getValue() * alphaMod + 0.5f);
-        paint = mPaintSelector[index % 2][SELECTOR_CIRCLE];
+        // Draw the selection circle.
+        final Paint paint = mPaintSelector[index % 2][SELECTOR_CIRCLE];
         paint.setColor(color);
-        paint.setAlpha(getMultipliedAlpha(color, alpha));
-        canvas.drawCircle(pointX, pointY, mSelectorRadius, paint);
+        canvas.drawCircle(selCenterX, selCenterY, selRadius, paint);
 
         // If needed, set up the clip path for later.
         if (selectorPath != null) {
-            mSelectorPath.reset();
-            mSelectorPath.addCircle(pointX, pointY, mSelectorRadius, Path.Direction.CCW);
+            selectorPath.reset();
+            selectorPath.addCircle(selCenterX, selCenterY, selRadius, Path.Direction.CCW);
         }
 
-        // Draw the dot if needed.
-        final boolean shouldDrawDot = mSelectionDegrees[index] % 30 != 0;
+        // Draw the dot if we're between two items.
+        final boolean shouldDrawDot = mSelectionDegrees[index % 2] % 30 != 0;
         if (shouldDrawDot) {
-            // We're not on a direct tick
-            color = mColorSelector[index % 2][SELECTOR_DOT];
-            alpha = (int) (mAlphaSelector[index % 2][SELECTOR_DOT].getValue() * alphaMod + 0.5f);
-            paint = mPaintSelector[index % 2][SELECTOR_DOT];
-            paint.setColor(color);
-            paint.setAlpha(getMultipliedAlpha(color, alpha));
-            canvas.drawCircle(pointX, pointY, mSelectorDotRadius, paint);
+            final Paint dotPaint = mPaintSelector[index % 2][SELECTOR_DOT];
+            dotPaint.setColor(mSelectorDotColor);
+            canvas.drawCircle(selCenterX, selCenterY, mSelectorDotRadius, dotPaint);
         }
 
         // Shorten the line to only go from the edge of the center dot to the
         // edge of the selection circle.
-        final double sin = Math.sin(selectionRadians);
-        final double cos = Math.cos(selectionRadians);
-        final int lineLength = mLineLength[index] - mSelectorRadius;
+        final double sin = Math.sin(selAngleRad);
+        final double cos = Math.cos(selAngleRad);
+        final int lineLength = selLength - selRadius;
         final int centerX = mXCenter + (int) (mCenterDotRadius * sin);
         final int centerY = mYCenter - (int) (mCenterDotRadius * cos);
-        pointX = centerX + (int) (lineLength * sin);
-        pointY = centerY - (int) (lineLength * cos);
+        final float linePointX = centerX + (int) (lineLength * sin);
+        final float linePointY = centerY - (int) (lineLength * cos);
 
-        // Draw the line
-        color = mColorSelector[index % 2][SELECTOR_LINE];
-        alpha = (int) (mAlphaSelector[index % 2][SELECTOR_LINE].getValue() * alphaMod + 0.5f);
-        paint = mPaintSelector[index % 2][SELECTOR_LINE];
-        paint.setColor(color);
-        paint.setStrokeWidth(mSelectorStroke);
-        paint.setAlpha(getMultipliedAlpha(color, alpha));
-        canvas.drawLine(mXCenter, mYCenter, pointX, pointY, paint);
+        // Draw the line.
+        final Paint linePaint = mPaintSelector[index % 2][SELECTOR_LINE];
+        linePaint.setColor(color);
+        linePaint.setStrokeWidth(mSelectorStroke);
+        canvas.drawLine(mXCenter, mYCenter, linePointX, linePointY, linePaint);
     }
 
     private void calculatePositionsHours() {
@@ -890,21 +881,8 @@
         if (mHoursToMinutesAnims.size() == 0) {
             mHoursToMinutesAnims.add(getFadeOutAnimator(mAlpha[HOURS],
                     ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
-            mHoursToMinutesAnims.add(getFadeOutAnimator(mAlphaSelector[HOURS][SELECTOR_CIRCLE],
-                    ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
-            mHoursToMinutesAnims.add(getFadeOutAnimator(mAlphaSelector[HOURS][SELECTOR_DOT],
-                    ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
-            mHoursToMinutesAnims.add(getFadeOutAnimator(mAlphaSelector[HOURS][SELECTOR_LINE],
-                    ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
-
             mHoursToMinutesAnims.add(getFadeInAnimator(mAlpha[MINUTES],
                     ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
-            mHoursToMinutesAnims.add(getFadeInAnimator(mAlphaSelector[MINUTES][SELECTOR_CIRCLE],
-                    ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
-            mHoursToMinutesAnims.add(getFadeInAnimator(mAlphaSelector[MINUTES][SELECTOR_DOT],
-                    ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
-            mHoursToMinutesAnims.add(getFadeInAnimator(mAlphaSelector[MINUTES][SELECTOR_LINE],
-                    ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
         }
 
         if (mTransition != null && mTransition.isRunning()) {
@@ -919,21 +897,8 @@
         if (mMinuteToHoursAnims.size() == 0) {
             mMinuteToHoursAnims.add(getFadeOutAnimator(mAlpha[MINUTES],
                     ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
-            mMinuteToHoursAnims.add(getFadeOutAnimator(mAlphaSelector[MINUTES][SELECTOR_CIRCLE],
-                    ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
-            mMinuteToHoursAnims.add(getFadeOutAnimator(mAlphaSelector[MINUTES][SELECTOR_DOT],
-                    ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
-            mMinuteToHoursAnims.add(getFadeOutAnimator(mAlphaSelector[MINUTES][SELECTOR_LINE],
-                    ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
-
             mMinuteToHoursAnims.add(getFadeInAnimator(mAlpha[HOURS],
                     ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
-            mMinuteToHoursAnims.add(getFadeInAnimator(mAlphaSelector[HOURS][SELECTOR_CIRCLE],
-                    ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
-            mMinuteToHoursAnims.add(getFadeInAnimator(mAlphaSelector[HOURS][SELECTOR_DOT],
-                    ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
-            mMinuteToHoursAnims.add(getFadeInAnimator(mAlphaSelector[HOURS][SELECTOR_LINE],
-                    ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
         }
 
         if (mTransition != null && mTransition.isRunning()) {
@@ -945,56 +910,43 @@
     }
 
     private int getDegreesFromXY(float x, float y, boolean constrainOutside) {
-        final double hypotenuse = Math.sqrt(
-                (y - mYCenter) * (y - mYCenter) + (x - mXCenter) * (x - mXCenter));
+        // Ensure the point is inside the touchable area.
+        final int innerBound;
+        final int outerBound;
+        if (mIs24HourMode && mShowHours) {
+            innerBound = mMinDistForInnerNumber;
+            outerBound = mMaxDistForOuterNumber;
+        } else {
+            final int index = mShowHours ? HOURS : MINUTES;
+            final int center = mCircleRadius - mTextInset[index];
+            innerBound = center - mSelectorRadius;
+            outerBound = center + mSelectorRadius;
+        }
 
-        // Basic check if we're outside the range of the disk
-        if (constrainOutside && hypotenuse > mCircleRadius) {
+        final double dX = x - mXCenter;
+        final double dY = y - mYCenter;
+        final double distFromCenter = Math.sqrt(dX * dX + dY * dY);
+        if (distFromCenter < innerBound || constrainOutside && distFromCenter > outerBound) {
             return -1;
         }
 
-        // Check
+        // Convert to degrees.
+        final int degrees = (int) (Math.toDegrees(Math.atan2(dY, dX) + Math.PI / 2) + 0.5);
+        if (degrees < 0) {
+            return degrees + 360;
+        } else {
+            return degrees;
+        }
+    }
+
+    private boolean getInnerCircleFromXY(float x, float y) {
         if (mIs24HourMode && mShowHours) {
-            if (hypotenuse >= mMinHypotenuseForInnerNumber
-                    && hypotenuse <= mHalfwayHypotenusePoint) {
-                mIsOnInnerCircle = true;
-            } else if ((hypotenuse <= mMaxHypotenuseForOuterNumber || !constrainOutside)
-                    && hypotenuse >= mHalfwayHypotenusePoint) {
-                mIsOnInnerCircle = false;
-            } else {
-                return -1;
-            }
-        } else {
-            final int index =  (mShowHours) ? HOURS : MINUTES;
-            final float length = (mCircleRadius - mTextInset[index]);
-            final int distanceToNumber = (int) (hypotenuse - length);
-            final int maxAllowedDistance = mTextInset[index];
-            if (distanceToNumber < -maxAllowedDistance
-                    || (constrainOutside && distanceToNumber > maxAllowedDistance)) {
-                return -1;
-            }
+            final double dX = x - mXCenter;
+            final double dY = y - mYCenter;
+            final double distFromCenter = Math.sqrt(dX * dX + dY * dY);
+            return distFromCenter <= mHalfwayDist;
         }
-
-        final float opposite = Math.abs(y - mYCenter);
-        int degrees = (int) (Math.toDegrees(Math.asin(opposite / hypotenuse)) + 0.5);
-
-        // Now we have to translate to the correct quadrant.
-        final boolean rightSide = (x > mXCenter);
-        final boolean topSide = (y < mYCenter);
-        if (rightSide) {
-            if (topSide) {
-                degrees = 90 - degrees;
-            } else {
-                degrees = 90 + degrees;
-            }
-        } else {
-            if (topSide) {
-                degrees = 270 + degrees;
-            } else {
-                degrees = 270 - degrees;
-            }
-        }
-        return degrees;
+        return false;
     }
 
     boolean mChangedDuringTouch = false;
@@ -1034,34 +986,28 @@
 
     private boolean handleTouchInput(
             float x, float y, boolean forceSelection, boolean autoAdvance) {
-        // Calling getDegreesFromXY has side effects, so cache
-        // whether we used to be on the inner circle.
-        final boolean wasOnInnerCircle = mIsOnInnerCircle;
+        final boolean isOnInnerCircle = getInnerCircleFromXY(x, y);
         final int degrees = getDegreesFromXY(x, y, false);
         if (degrees == -1) {
             return false;
         }
 
-        final int[] selectionDegrees = mSelectionDegrees;
         final int type;
         final int newValue;
         final boolean valueChanged;
 
         if (mShowHours) {
             final int snapDegrees = snapOnly30s(degrees, 0) % 360;
-            valueChanged = selectionDegrees[HOURS] != snapDegrees
-                    || selectionDegrees[HOURS_INNER] != snapDegrees
-                    || wasOnInnerCircle != mIsOnInnerCircle;
-
-            selectionDegrees[HOURS] = snapDegrees;
-            selectionDegrees[HOURS_INNER] = snapDegrees;
+            valueChanged = mIsOnInnerCircle != isOnInnerCircle
+                    || mSelectionDegrees[HOURS] != snapDegrees;
+            mIsOnInnerCircle = isOnInnerCircle;
+            mSelectionDegrees[HOURS] = snapDegrees;
             type = HOURS;
             newValue = getCurrentHour();
         } else {
             final int snapDegrees = snapPrefer30s(degrees) % 360;
-            valueChanged = selectionDegrees[MINUTES] != snapDegrees;
-
-            selectionDegrees[MINUTES] = snapDegrees;
+            valueChanged = mSelectionDegrees[MINUTES] != snapDegrees;
+            mSelectionDegrees[MINUTES] = snapDegrees;
             type = MINUTES;
             newValue = getCurrentMinute();
         }
@@ -1179,17 +1125,11 @@
         @Override
         protected int getVirtualViewAt(float x, float y) {
             final int id;
-
-            // Calling getDegreesXY() has side-effects, so we need to cache the
-            // current inner circle value and restore after the call.
-            final boolean wasOnInnerCircle = mIsOnInnerCircle;
             final int degrees = getDegreesFromXY(x, y, true);
-            final boolean isOnInnerCircle = mIsOnInnerCircle;
-            mIsOnInnerCircle = wasOnInnerCircle;
-
             if (degrees != -1) {
                 final int snapDegrees = snapOnly30s(degrees, 0) % 360;
                 if (mShowHours) {
+                    final boolean isOnInnerCircle = getInnerCircleFromXY(x, y);
                     final int hour24 = getHourForDegrees(snapDegrees, isOnInnerCircle);
                     final int hour = mIs24HourMode ? hour24 : hour24To12(hour24);
                     id = makeId(TYPE_HOUR, hour);
@@ -1200,8 +1140,10 @@
 
                     // If the touched minute is closer to the current minute
                     // than it is to the snapped minute, return current.
+                    final int currentOffset = getCircularDiff(current, touched, MINUTES_IN_HOUR);
+                    final int snappedOffset = getCircularDiff(snapped, touched, MINUTES_IN_HOUR);
                     final int minute;
-                    if (Math.abs(current - touched) < Math.abs(snapped - touched)) {
+                    if (currentOffset < snappedOffset) {
                         minute = current;
                     } else {
                         minute = snapped;
@@ -1215,6 +1157,20 @@
             return id;
         }
 
+        /**
+         * Returns the difference in degrees between two values along a circle.
+         *
+         * @param first value in the range [0,max]
+         * @param second value in the range [0,max]
+         * @param max the maximum value along the circle
+         * @return the difference in between the two values
+         */
+        private int getCircularDiff(int first, int second, int max) {
+            final int diff = Math.abs(first - second);
+            final int midpoint = max / 2;
+            return (diff > midpoint) ? (max - diff) : diff;
+        }
+
         @Override
         protected void getVisibleVirtualViews(IntArray virtualViewIds) {
             if (mShowHours) {
@@ -1225,7 +1181,7 @@
                 }
             } else {
                 final int current = getCurrentMinute();
-                for (int i = 0; i < 60; i += MINUTE_INCREMENT) {
+                for (int i = 0; i < MINUTES_IN_HOUR; i += MINUTE_INCREMENT) {
                     virtualViewIds.add(makeId(TYPE_MINUTE, i));
 
                     // If the current minute falls between two increments,
@@ -1283,7 +1239,7 @@
                 if (value < current && nextValue > current) {
                     // The current value is between two snap values.
                     return makeId(type, current);
-                } else if (nextValue < 60) {
+                } else if (nextValue < MINUTES_IN_HOUR) {
                     return makeId(type, nextValue);
                 }
             }
@@ -1337,7 +1293,7 @@
             final float centerRadius;
             final float degrees;
             if (type == TYPE_HOUR) {
-                final boolean innerCircle = mIs24HourMode && value > 0 && value <= 12;
+                final boolean innerCircle = getInnerCircleForHour(value);
                 if (innerCircle) {
                     centerRadius = mCircleRadius - mTextInset[HOURS_INNER];
                     radius = mSelectorRadius;
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 349f3f0..a50941b 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -815,12 +815,12 @@
         mContext = context;
         mIntent = intent;
 
-        mAppWidgetId = intent.getIntExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID, -1);
-
-        mLayoutInflater = LayoutInflater.from(context);
         if (mIntent == null) {
             throw new IllegalArgumentException("Non-null Intent must be specified.");
         }
+
+        mAppWidgetId = intent.getIntExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID, -1);
+        mLayoutInflater = LayoutInflater.from(context);
         mRequestedViews = new RemoteViewsFrameLayoutRefSet();
 
         // Strip the previously injected app widget id from service intent
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 4e5a39a..d9f1f0e 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -26,6 +26,7 @@
 import android.graphics.Paint.Style;
 import android.graphics.Rect;
 import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.text.TextPaint;
 import android.text.format.DateFormat;
@@ -59,6 +60,12 @@
     private static final String DEFAULT_TITLE_FORMAT = "MMMMy";
     private static final String DAY_OF_WEEK_FORMAT = "EEEEE";
 
+    /** Virtual view ID for previous button. */
+    private static final int ITEM_ID_PREV = 0x101;
+
+    /** Virtual view ID for next button. */
+    private static final int ITEM_ID_NEXT = 0x100;
+
     private final TextPaint mMonthPaint = new TextPaint();
     private final TextPaint mDayOfWeekPaint = new TextPaint();
     private final TextPaint mDayPaint = new TextPaint();
@@ -66,27 +73,43 @@
     private final Paint mDayHighlightPaint = new Paint();
 
     private final Calendar mCalendar = Calendar.getInstance();
-    private final Calendar mDayLabelCalendar = Calendar.getInstance();
+    private final Calendar mDayOfWeekLabelCalendar = Calendar.getInstance();
 
     private final MonthViewTouchHelper mTouchHelper;
 
     private final SimpleDateFormat mTitleFormatter;
     private final SimpleDateFormat mDayOfWeekFormatter;
 
+    // Desired dimensions.
+    private final int mDesiredMonthHeight;
+    private final int mDesiredDayOfWeekHeight;
+    private final int mDesiredDayHeight;
+    private final int mDesiredCellWidth;
+    private final int mDesiredDaySelectorRadius;
+
+    // Next/previous drawables.
+    private final Drawable mPrevDrawable;
+    private final Drawable mNextDrawable;
+    private final Rect mPrevHitArea;
+    private final Rect mNextHitArea;
+    private final CharSequence mPrevContentDesc;
+    private final CharSequence mNextContentDesc;
+
     private CharSequence mTitle;
 
     private int mMonth;
     private int mYear;
 
+    // Dimensions as laid out.
+    private int mMonthHeight;
+    private int mDayOfWeekHeight;
+    private int mDayHeight;
+    private int mCellWidth;
+    private int mDaySelectorRadius;
+
     private int mPaddedWidth;
     private int mPaddedHeight;
 
-    private final int mMonthHeight;
-    private final int mDayOfWeekHeight;
-    private final int mDayHeight;
-    private final int mCellWidth;
-    private final int mDaySelectorRadius;
-
     /** The day of month for the selected day, or -1 if no day is selected. */
     private int mActivatedDay = -1;
 
@@ -122,7 +145,10 @@
 
     private ColorStateList mDayTextColor;
 
-    private int mTouchedDay = -1;
+    private int mTouchedItem = -1;
+
+    private boolean mPrevEnabled;
+    private boolean mNextEnabled;
 
     public SimpleMonthView(Context context) {
         this(context, null);
@@ -140,11 +166,18 @@
         super(context, attrs, defStyleAttr, defStyleRes);
 
         final Resources res = context.getResources();
-        mMonthHeight = res.getDimensionPixelSize(R.dimen.date_picker_month_height);
-        mDayOfWeekHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_of_week_height);
-        mDayHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_height);
-        mCellWidth = res.getDimensionPixelSize(R.dimen.date_picker_day_width);
-        mDaySelectorRadius = res.getDimensionPixelSize(R.dimen.date_picker_day_selector_radius);
+        mDesiredMonthHeight = res.getDimensionPixelSize(R.dimen.date_picker_month_height);
+        mDesiredDayOfWeekHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_of_week_height);
+        mDesiredDayHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_height);
+        mDesiredCellWidth = res.getDimensionPixelSize(R.dimen.date_picker_day_width);
+        mDesiredDaySelectorRadius = res.getDimensionPixelSize(R.dimen.date_picker_day_selector_radius);
+
+        mPrevDrawable = context.getDrawable(R.drawable.ic_chevron_left);
+        mNextDrawable = context.getDrawable(R.drawable.ic_chevron_right);
+        mPrevHitArea = mPrevDrawable != null ? new Rect() : null;
+        mNextHitArea = mNextDrawable != null ? new Rect() : null;
+        mPrevContentDesc = res.getText(R.string.date_picker_prev_month_button);
+        mNextContentDesc = res.getText(R.string.date_picker_next_month_button);
 
         // Set up accessibility components.
         mTouchHelper = new MonthViewTouchHelper(this);
@@ -160,6 +193,18 @@
         initPaints(res);
     }
 
+    public void setNextEnabled(boolean enabled) {
+        mNextEnabled = enabled;
+        mTouchHelper.invalidateRoot();
+        invalidate();
+    }
+
+    public void setPrevEnabled(boolean enabled) {
+        mPrevEnabled = enabled;
+        mTouchHelper.invalidateRoot();
+        invalidate();
+    }
+
     /**
      * Applies the specified text appearance resource to a paint, returning the
      * text color if one is set in the text appearance.
@@ -192,7 +237,16 @@
     }
 
     public void setMonthTextAppearance(int resId) {
-        applyTextAppearance(mMonthPaint, resId);
+        final ColorStateList monthColor = applyTextAppearance(mMonthPaint, resId);
+        if (monthColor != null) {
+            if (mPrevDrawable != null) {
+                mPrevDrawable.setTintList(monthColor);
+            }
+            if (mNextDrawable != null) {
+                mNextDrawable.setTintList(monthColor);
+            }
+        }
+
         invalidate();
     }
 
@@ -300,23 +354,26 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
+        final int x = (int) (event.getX() + 0.5f);
+        final int y = (int) (event.getY() + 0.5f);
+
         switch (event.getAction()) {
             case MotionEvent.ACTION_DOWN:
             case MotionEvent.ACTION_MOVE:
-                final int touchedDay = getDayAtLocation(event.getX(), event.getY());
-                if (mTouchedDay != touchedDay) {
-                    mTouchedDay = touchedDay;
+                final int touchedItem = getItemAtLocation(x, y);
+                if (mTouchedItem != touchedItem) {
+                    mTouchedItem = touchedItem;
                     invalidate();
                 }
                 break;
 
             case MotionEvent.ACTION_UP:
-                final int clickedDay = getDayAtLocation(event.getX(), event.getY());
-                onDayClicked(clickedDay);
+                final int clickedItem = getItemAtLocation(x, y);
+                onItemClicked(clickedItem, true);
                 // Fall through.
             case MotionEvent.ACTION_CANCEL:
                 // Reset touched day on stream end.
-                mTouchedDay = -1;
+                mTouchedItem = -1;
                 invalidate();
                 break;
         }
@@ -332,6 +389,7 @@
         drawMonth(canvas);
         drawDaysOfWeek(canvas);
         drawDays(canvas);
+        drawButtons(canvas);
 
         canvas.translate(-paddingLeft, -paddingTop);
     }
@@ -347,34 +405,43 @@
     }
 
     private void drawDaysOfWeek(Canvas canvas) {
-        final float cellWidthHalf = mPaddedWidth / (DAYS_IN_WEEK * 2);
+        final TextPaint p = mDayOfWeekPaint;
+        final int headerHeight = mMonthHeight;
+        final int rowHeight = mDayOfWeekHeight;
+        final int colWidth = mCellWidth;
 
-        // Vertically centered within the cell height.
-        final float lineHeight = mDayOfWeekPaint.ascent() + mDayOfWeekPaint.descent();
-        final float y = mMonthHeight + (mDayOfWeekHeight - lineHeight) / 2f;
+        // Text is vertically centered within the day of week height.
+        final float halfLineHeight = (p.ascent() + p.descent()) / 2f;
+        final int rowCenter = headerHeight + rowHeight / 2;
 
-        for (int i = 0; i < DAYS_IN_WEEK; i++) {
-            final int calendarDay = (i + mWeekStart) % DAYS_IN_WEEK;
-            mDayLabelCalendar.set(Calendar.DAY_OF_WEEK, calendarDay);
-
-            final String dayLabel = mDayOfWeekFormatter.format(mDayLabelCalendar.getTime());
-            final float x = (2 * i + 1) * cellWidthHalf;
-            canvas.drawText(dayLabel, x, y, mDayOfWeekPaint);
+        for (int col = 0; col < DAYS_IN_WEEK; col++) {
+            final int colCenter = colWidth * col + colWidth / 2;
+            final int dayOfWeek = (col + mWeekStart) % DAYS_IN_WEEK;
+            final String label = getDayOfWeekLabel(dayOfWeek);
+            canvas.drawText(label, colCenter, rowCenter - halfLineHeight, p);
         }
     }
 
+    private String getDayOfWeekLabel(int dayOfWeek) {
+        mDayOfWeekLabelCalendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
+        return mDayOfWeekFormatter.format(mDayOfWeekLabelCalendar.getTime());
+    }
+
     /**
      * Draws the month days.
      */
     private void drawDays(Canvas canvas) {
-        final int cellWidthHalf = mPaddedWidth / (DAYS_IN_WEEK * 2);
+        final TextPaint p = mDayPaint;
+        final int headerHeight = mMonthHeight + mDayOfWeekHeight;
+        final int rowHeight = mDayHeight;
+        final int colWidth = mCellWidth;
 
-        // Vertically centered within the cell height.
-        final float halfLineHeight = (mDayPaint.ascent() + mDayPaint.descent()) / 2;
-        float centerY = mMonthHeight + mDayOfWeekHeight + mDayHeight / 2f;
+        // Text is vertically centered within the row height.
+        final float halfLineHeight = (p.ascent() + p.descent()) / 2f;
+        int rowCenter = headerHeight + rowHeight / 2;
 
-        for (int day = 1, j = findDayOffset(); day <= mDaysInMonth; day++) {
-            final int x = (2 * j + 1) * cellWidthHalf;
+        for (int day = 1, col = findDayOffset(); day <= mDaysInMonth; day++) {
+            final int colCenter = colWidth * col + colWidth / 2;
             int stateMask = 0;
 
             if (day >= mEnabledDayStart && day <= mEnabledDayEnd) {
@@ -386,12 +453,12 @@
                 stateMask |= StateSet.VIEW_STATE_ACTIVATED;
 
                 // Adjust the circle to be centered on the row.
-                canvas.drawCircle(x, centerY, mDaySelectorRadius, mDaySelectorPaint);
-            } else if (mTouchedDay == day) {
+                canvas.drawCircle(colCenter, rowCenter, mDaySelectorRadius, mDaySelectorPaint);
+            } else if (mTouchedItem == day) {
                 stateMask |= StateSet.VIEW_STATE_PRESSED;
 
                 // Adjust the circle to be centered on the row.
-                canvas.drawCircle(x, centerY, mDaySelectorRadius, mDayHighlightPaint);
+                canvas.drawCircle(colCenter, rowCenter, mDaySelectorRadius, mDayHighlightPaint);
             }
 
             final boolean isDayToday = mToday == day;
@@ -402,19 +469,29 @@
                 final int[] stateSet = StateSet.get(stateMask);
                 dayTextColor = mDayTextColor.getColorForState(stateSet, 0);
             }
-            mDayPaint.setColor(dayTextColor);
+            p.setColor(dayTextColor);
 
-            canvas.drawText("" + day, x, centerY - halfLineHeight, mDayPaint);
+            canvas.drawText(Integer.toString(day), colCenter, rowCenter - halfLineHeight, p);
 
-            j++;
+            col++;
 
-            if (j == DAYS_IN_WEEK) {
-                j = 0;
-                centerY += mDayHeight;
+            if (col == DAYS_IN_WEEK) {
+                col = 0;
+                rowCenter += rowHeight;
             }
         }
     }
 
+    private void drawButtons(Canvas canvas) {
+        if (mPrevEnabled && mPrevDrawable != null) {
+            mPrevDrawable.draw(canvas);
+        }
+
+        if (mNextEnabled && mNextDrawable != null) {
+            mNextDrawable.draw(canvas);
+        }
+    }
+
     private static boolean isValidDayOfWeek(int day) {
         return day >= Calendar.SUNDAY && day <= Calendar.SATURDAY;
     }
@@ -558,9 +635,9 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int preferredHeight = mDayHeight * mNumWeeks + mDayOfWeekHeight + mMonthHeight
-                + getPaddingTop() + getPaddingBottom();
-        final int preferredWidth = mCellWidth * DAYS_IN_WEEK
+        final int preferredHeight = mDesiredDayHeight * mNumWeeks + mDesiredDayOfWeekHeight
+                + mDesiredMonthHeight + getPaddingTop() + getPaddingBottom();
+        final int preferredWidth = mDesiredCellWidth * DAYS_IN_WEEK
                 + getPaddingStart() + getPaddingEnd();
         final int resolvedWidth = resolveSize(preferredWidth, widthMeasureSpec);
         final int resolvedHeight = resolveSize(preferredHeight, heightMeasureSpec);
@@ -568,9 +645,73 @@
     }
 
     @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        mPaddedWidth = w - getPaddingLeft() - getPaddingRight();
-        mPaddedHeight = w - getPaddingTop() - getPaddingBottom();
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (!changed) {
+            return;
+        }
+
+        // Let's initialize a completely reasonable number of variables.
+        final int w = right - left;
+        final int h = bottom - top;
+        final int paddingLeft = getPaddingLeft();
+        final int paddingTop = getPaddingTop();
+        final int paddingRight = getPaddingRight();
+        final int paddingBottom = getPaddingBottom();
+        final int paddedRight = w - paddingRight;
+        final int paddedBottom = h - paddingBottom;
+        final int paddedWidth = paddedRight - paddingLeft;
+        final int paddedHeight = paddedBottom - paddingTop;
+        if (paddedWidth == mPaddedWidth || paddedHeight == mPaddedHeight) {
+            return;
+        }
+
+        mPaddedWidth = paddedWidth;
+        mPaddedHeight = paddedHeight;
+
+        // We may have been laid out smaller than our preferred size. If so,
+        // scale all dimensions to fit.
+        final int measuredPaddedHeight = getMeasuredHeight() - paddingTop - paddingBottom;
+        final float scaleH = paddedHeight / (float) measuredPaddedHeight;
+        final int monthHeight = (int) (mDesiredMonthHeight * scaleH);
+        final int cellWidth = mPaddedWidth / DAYS_IN_WEEK;
+        mMonthHeight = monthHeight;
+        mDayOfWeekHeight = (int) (mDesiredDayOfWeekHeight * scaleH);
+        mDayHeight = (int) (mDesiredDayHeight * scaleH);
+        mCellWidth = cellWidth;
+
+        // Compute the largest day selector radius that's still within the clip
+        // bounds and desired selector radius.
+        final int maxSelectorWidth = cellWidth / 2 + Math.min(paddingLeft, paddingRight);
+        final int maxSelectorHeight = mDayHeight / 2 + paddingBottom;
+        mDaySelectorRadius = Math.min(mDesiredDaySelectorRadius,
+                Math.min(maxSelectorWidth, maxSelectorHeight));
+
+        // Vertically center the previous/next drawables within the month
+        // header, horizontally center within the day cell, then expand the
+        // hit area to ensure it's at least 48x48dp.
+        final Drawable prevDrawable = mPrevDrawable;
+        if (prevDrawable != null) {
+            final int dW = prevDrawable.getIntrinsicWidth();
+            final int dH = prevDrawable.getIntrinsicHeight();
+            final int iconTop = (monthHeight - dH) / 2;
+            final int iconLeft = (cellWidth - dW) / 2;
+
+            // Button bounds don't include padding, but hit area does.
+            prevDrawable.setBounds(iconLeft, iconTop, iconLeft + dW, iconTop + dH);
+            mPrevHitArea.set(0, 0, paddingLeft + cellWidth, paddingTop + monthHeight);
+        }
+
+        final Drawable nextDrawable = mNextDrawable;
+        if (nextDrawable != null) {
+            final int dW = nextDrawable.getIntrinsicWidth();
+            final int dH = nextDrawable.getIntrinsicHeight();
+            final int iconTop = (monthHeight - dH) / 2;
+            final int iconRight = paddedWidth - (cellWidth - dW) / 2;
+
+            // Button bounds don't include padding, but hit area does.
+            nextDrawable.setBounds(iconRight - dW, iconTop, iconRight, iconTop + dH);
+            mNextHitArea.set(paddedRight - cellWidth, 0, w, paddingTop + monthHeight);
+        }
 
         // Invalidate cached accessibility information.
         mTouchHelper.invalidateRoot();
@@ -585,22 +726,29 @@
     }
 
     /**
-     * Calculates the day of the month at the specified touch position. Returns
-     * the day of the month or -1 if the position wasn't in a valid day.
+     * Calculates the day of the month or item identifier at the specified
+     * touch position. Returns the day of the month or -1 if the position
+     * wasn't in a valid day.
      *
      * @param x the x position of the touch event
      * @param y the y position of the touch event
-     * @return the day of the month at (x, y) or -1 if the position wasn't in a
-     *         valid day
+     * @return the day of the month at (x, y), an item identifier, or -1 if the
+     *         position wasn't in a valid day or item
      */
-    private int getDayAtLocation(float x, float y) {
-        final int paddedX = (int) (x - getPaddingLeft() + 0.5f);
+    private int getItemAtLocation(int x, int y) {
+        if (mNextEnabled && mNextDrawable != null && mNextHitArea.contains(x, y)) {
+            return ITEM_ID_NEXT;
+        } else if (mPrevEnabled && mPrevDrawable != null && mPrevHitArea.contains(x, y)) {
+            return ITEM_ID_PREV;
+        }
+
+        final int paddedX = x - getPaddingLeft();
         if (paddedX < 0 || paddedX >= mPaddedWidth) {
             return -1;
         }
 
         final int headerHeight = mMonthHeight + mDayOfWeekHeight;
-        final int paddedY = (int) (y - getPaddingTop() + 0.5f);
+        final int paddedY = y - getPaddingTop();
         if (paddedY < headerHeight || paddedY >= mPaddedHeight) {
             return -1;
         }
@@ -619,47 +767,97 @@
     /**
      * Calculates the bounds of the specified day.
      *
-     * @param day the day of the month
+     * @param id the day of the month, or an item identifier
      * @param outBounds the rect to populate with bounds
      */
-    private boolean getBoundsForDay(int day, Rect outBounds) {
-        if (day < 1 || day > mDaysInMonth) {
+    private boolean getBoundsForItem(int id, Rect outBounds) {
+        if (mNextEnabled && id == ITEM_ID_NEXT) {
+            if (mNextDrawable != null) {
+                outBounds.set(mNextHitArea);
+                return true;
+            }
+        } else if (mPrevEnabled && id == ITEM_ID_PREV) {
+            if (mPrevDrawable != null) {
+                outBounds.set(mPrevHitArea);
+                return true;
+            }
+        }
+
+        if (id < 1 || id > mDaysInMonth) {
             return false;
         }
 
-        final int index = day - 1 + findDayOffset();
-        final int row = index / DAYS_IN_WEEK;
+        final int index = id - 1 + findDayOffset();
+
+        // Compute left edge.
         final int col = index % DAYS_IN_WEEK;
+        final int colWidth = mCellWidth;
+        final int left = getPaddingLeft() + col * colWidth;
 
+        // Compute top edge.
+        final int row = index / DAYS_IN_WEEK;
+        final int rowHeight = mDayHeight;
         final int headerHeight = mMonthHeight + mDayOfWeekHeight;
-        final int paddedY = row * mDayHeight + headerHeight;
-        final int paddedX = col * mPaddedWidth;
+        final int top = getPaddingTop() + headerHeight + row * rowHeight;
 
-        final int y = paddedY + getPaddingTop();
-        final int x = paddedX + getPaddingLeft();
-
-        final int cellHeight = mDayHeight;
-        final int cellWidth = mPaddedWidth / DAYS_IN_WEEK;
-        outBounds.set(x, y, (x + cellWidth), (y + cellHeight));
-
+        outBounds.set(left, top, left + colWidth, top + rowHeight);
         return true;
     }
 
     /**
+     * Called when an item is clicked.
+     *
+     * @param id the day number or item identifier
+     */
+    private boolean onItemClicked(int id, boolean animate) {
+        return onNavigationClicked(id, animate) || onDayClicked(id);
+    }
+
+    /**
      * Called when the user clicks on a day. Handles callbacks to the
      * {@link OnDayClickListener} if one is set.
      *
      * @param day the day that was clicked
      */
-    private void onDayClicked(int day) {
+    private boolean onDayClicked(int day) {
+        if (day < 0 || day > mDaysInMonth) {
+            return false;
+        }
+
         if (mOnDayClickListener != null) {
-            Calendar date = Calendar.getInstance();
+            final Calendar date = Calendar.getInstance();
             date.set(mYear, mMonth, day);
             mOnDayClickListener.onDayClick(this, date);
         }
 
         // This is a no-op if accessibility is turned off.
         mTouchHelper.sendEventForVirtualView(day, AccessibilityEvent.TYPE_VIEW_CLICKED);
+        return true;
+    }
+
+    /**
+     * Called when the user clicks on a navigation button. Handles callbacks to
+     * the {@link OnDayClickListener} if one is set.
+     *
+     * @param id the item identifier
+     */
+    private boolean onNavigationClicked(int id, boolean animate) {
+        final int direction;
+        if (id == ITEM_ID_NEXT) {
+            direction = 1;
+        } else if (id == ITEM_ID_PREV) {
+            direction = -1;
+        } else {
+            return false;
+        }
+
+        if (mOnDayClickListener != null) {
+            mOnDayClickListener.onNavigationClick(this, direction, animate);
+        }
+
+        // This is a no-op if accessibility is turned off.
+        mTouchHelper.sendEventForVirtualView(id, AccessibilityEvent.TYPE_VIEW_CLICKED);
+        return true;
     }
 
     /**
@@ -678,7 +876,7 @@
 
         @Override
         protected int getVirtualViewAt(float x, float y) {
-            final int day = getDayAtLocation(x, y);
+            final int day = getItemAtLocation((int) (x + 0.5f), (int) (y + 0.5f));
             if (day >= 0) {
                 return day;
             }
@@ -687,6 +885,14 @@
 
         @Override
         protected void getVisibleVirtualViews(IntArray virtualViewIds) {
+            if (mNextEnabled && mNextDrawable != null) {
+                virtualViewIds.add(ITEM_ID_PREV);
+            }
+
+            if (mPrevEnabled && mPrevDrawable != null) {
+                virtualViewIds.add(ITEM_ID_NEXT);
+            }
+
             for (int day = 1; day <= mDaysInMonth; day++) {
                 virtualViewIds.add(day);
             }
@@ -699,7 +905,7 @@
 
         @Override
         protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfo node) {
-            final boolean hasBounds = getBoundsForDay(virtualViewId, mTempRect);
+            final boolean hasBounds = getBoundsForItem(virtualViewId, mTempRect);
 
             if (!hasBounds) {
                 // The day is invalid, kill the node.
@@ -710,12 +916,14 @@
                 return;
             }
 
+            node.setText(getItemText(virtualViewId));
             node.setContentDescription(getItemDescription(virtualViewId));
             node.setBoundsInParent(mTempRect);
             node.addAction(AccessibilityAction.ACTION_CLICK);
 
             if (virtualViewId == mActivatedDay) {
-                node.setSelected(true);
+                // TODO: This should use activated once that's supported.
+                node.setChecked(true);
             }
 
         }
@@ -725,31 +933,45 @@
                 Bundle arguments) {
             switch (action) {
                 case AccessibilityNodeInfo.ACTION_CLICK:
-                    onDayClicked(virtualViewId);
-                    return true;
+                    return onItemClicked(virtualViewId, false);
             }
 
             return false;
         }
 
         /**
-         * Generates a description for a given time object. Since this
-         * description will be spoken, the components are ordered by descending
-         * specificity as DAY MONTH YEAR.
+         * Generates a description for a given virtual view.
          *
-         * @param day The day to generate a description for
-         * @return A description of the time object
+         * @param id the day or item identifier to generate a description for
+         * @return a description of the virtual view
          */
-        private CharSequence getItemDescription(int day) {
-            mTempCalendar.set(mYear, mMonth, day);
-            final CharSequence date = DateFormat.format(DATE_FORMAT,
-                    mTempCalendar.getTimeInMillis());
-
-            if (day == mActivatedDay) {
-                return getContext().getString(R.string.item_is_selected, date);
+        private CharSequence getItemDescription(int id) {
+            if (id == ITEM_ID_NEXT) {
+                return mNextContentDesc;
+            } else if (id == ITEM_ID_PREV) {
+                return mPrevContentDesc;
+            } else if (id >= 1 && id <= mDaysInMonth) {
+                mTempCalendar.set(mYear, mMonth, id);
+                return DateFormat.format(DATE_FORMAT, mTempCalendar.getTimeInMillis());
             }
 
-            return date;
+            return "";
+        }
+
+        /**
+         * Generates displayed text for a given virtual view.
+         *
+         * @param id the day or item identifier to generate text for
+         * @return the visible text of the virtual view
+         */
+        private CharSequence getItemText(int id) {
+            if (id == ITEM_ID_NEXT || id == ITEM_ID_PREV) {
+                return null;
+            } else if (id >= 1 && id <= mDaysInMonth) {
+                return Integer.toString(id);
+            }
+
+            return null;
         }
     }
 
@@ -758,5 +980,6 @@
      */
     public interface OnDayClickListener {
         public void onDayClick(SimpleMonthView view, Calendar day);
+        public void onNavigationClick(SimpleMonthView view, int direction, boolean animate);
     }
 }
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index bb290e7..ae779fe 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -1363,8 +1363,8 @@
     }
 
     @Override
-    public void onProvideAssistStructure(ViewAssistStructure structure, Bundle extras) {
-        super.onProvideAssistStructure(structure, extras);
+    public void onProvideAssistStructure(ViewAssistStructure structure) {
+        super.onProvideAssistStructure(structure);
         CharSequence switchText = isChecked() ? mTextOn : mTextOff;
         if (!TextUtils.isEmpty(switchText)) {
             CharSequence oldText = structure.getText();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 718ef93..9caa584 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -543,6 +543,8 @@
     private float mSpacingMult = 1.0f;
     private float mSpacingAdd = 0.0f;
 
+    private int mBreakStrategy;
+
     private int mMaximum = Integer.MAX_VALUE;
     private int mMaxMode = LINES;
     private int mMinimum = 0;
@@ -680,6 +682,7 @@
         boolean elegant = false;
         float letterSpacing = 0;
         String fontFeatureSettings = null;
+        mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
 
         final Resources.Theme theme = context.getTheme();
 
@@ -1133,6 +1136,9 @@
             case com.android.internal.R.styleable.TextView_fontFeatureSettings:
                 fontFeatureSettings = a.getString(attr);
                 break;
+
+            case com.android.internal.R.styleable.TextView_breakStrategy:
+                mBreakStrategy = a.getInt(attr, Layout.BREAK_STRATEGY_SIMPLE);
             }
         }
         a.recycle();
@@ -2960,6 +2966,35 @@
     }
 
     /**
+     * Sets the break strategy for breaking paragraphs into lines. The default value for
+     * TextView is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}, and the default value for
+     * EditText is {@link Layout#BREAK_STRATEGY_SIMPLE}, the latter to avoid the
+     * text "dancing" when being edited.
+     *
+     * @attr ref android.R.styleable#TextView_breakStrategy
+     * @see #getBreakStrategy()
+     */
+    public void setBreakStrategy(@Layout.BreakStrategy int breakStrategy) {
+        mBreakStrategy = breakStrategy;
+        if (mLayout != null) {
+            nullLayouts();
+            requestLayout();
+            invalidate();
+        }
+    }
+
+    /**
+     * @return the currently set break strategy.
+     *
+     * @attr ref android.R.styleable#TextView_breakStrategy
+     * @see #setBreakStrategy(int)
+     */
+    @Layout.BreakStrategy
+    public int getBreakStrategy() {
+        return mBreakStrategy;
+    }
+
+    /**
      * Sets font feature settings.  The format is the same as the CSS
      * font-feature-settings attribute:
      * http://dev.w3.org/csswg/css-fonts/#propdef-font-feature-settings
@@ -6492,27 +6527,25 @@
                                 hintBoring, mIncludePad, mEllipsize,
                                 ellipsisWidth);
                     }
-                } else if (shouldEllipsize) {
-                    mHintLayout = new StaticLayout(mHint,
-                                0, mHint.length(),
-                                mTextPaint, hintWidth, alignment, mTextDir, mSpacingMult,
-                                mSpacingAdd, mIncludePad, mEllipsize,
-                                ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
-                } else {
-                    mHintLayout = new StaticLayout(mHint, mTextPaint,
-                            hintWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
-                            mIncludePad);
                 }
-            } else if (shouldEllipsize) {
-                mHintLayout = new StaticLayout(mHint,
-                            0, mHint.length(),
-                            mTextPaint, hintWidth, alignment, mTextDir, mSpacingMult,
-                            mSpacingAdd, mIncludePad, mEllipsize,
-                            ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
-            } else {
-                mHintLayout = new StaticLayout(mHint, mTextPaint,
-                        hintWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
-                        mIncludePad);
+            }
+            // TODO: code duplication with makeSingleLayout()
+            if (mHintLayout == null) {
+                StaticLayout.Builder builder = StaticLayout.Builder.obtain(mHint, 0,
+                        mHint.length(), hintWidth)
+                        .setPaint(mTextPaint)
+                        .setAlignment(alignment)
+                        .setTextDir(mTextDir)
+                        .setSpacingMult(mSpacingMult)
+                        .setSpacingAdd(mSpacingAdd)
+                        .setIncludePad(mIncludePad)
+                        .setBreakStrategy(mBreakStrategy);
+                if (shouldEllipsize) {
+                    builder.setEllipsize(mEllipsize)
+                            .setEllipsizedWidth(ellipsisWidth)
+                            .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+                }
+                mHintLayout = builder.build();
             }
         }
 
@@ -6544,9 +6577,8 @@
         Layout result = null;
         if (mText instanceof Spannable) {
             result = new DynamicLayout(mText, mTransformed, mTextPaint, wantWidth,
-                    alignment, mTextDir, mSpacingMult,
-                    mSpacingAdd, mIncludePad, getKeyListener() == null ? effectiveEllipsize : null,
-                            ellipsisWidth);
+                    alignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad, mBreakStrategy,
+                    getKeyListener() == null ? effectiveEllipsize : null, ellipsisWidth);
         } else {
             if (boring == UNKNOWN_BORING) {
                 boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring);
@@ -6583,29 +6615,27 @@
                                 boring, mIncludePad, effectiveEllipsize,
                                 ellipsisWidth);
                     }
-                } else if (shouldEllipsize) {
-                    result = new StaticLayout(mTransformed,
-                            0, mTransformed.length(),
-                            mTextPaint, wantWidth, alignment, mTextDir, mSpacingMult,
-                            mSpacingAdd, mIncludePad, effectiveEllipsize,
-                            ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
-                } else {
-                    result = new StaticLayout(mTransformed, mTextPaint,
-                            wantWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
-                            mIncludePad);
                 }
-            } else if (shouldEllipsize) {
-                result = new StaticLayout(mTransformed,
-                        0, mTransformed.length(),
-                        mTextPaint, wantWidth, alignment, mTextDir, mSpacingMult,
-                        mSpacingAdd, mIncludePad, effectiveEllipsize,
-                        ellipsisWidth, mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
-            } else {
-                result = new StaticLayout(mTransformed, mTextPaint,
-                        wantWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd,
-                        mIncludePad);
             }
         }
+        if (result == null) {
+            StaticLayout.Builder builder = StaticLayout.Builder.obtain(mTransformed,
+                    0, mTransformed.length(), wantWidth)
+                    .setPaint(mTextPaint)
+                    .setAlignment(alignment)
+                    .setTextDir(mTextDir)
+                    .setSpacingMult(mSpacingMult)
+                    .setSpacingAdd(mSpacingAdd)
+                    .setIncludePad(mIncludePad)
+                    .setBreakStrategy(mBreakStrategy);
+            if (shouldEllipsize) {
+                builder.setEllipsize(effectiveEllipsize)
+                        .setEllipsizedWidth(ellipsisWidth)
+                        .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
+            }
+            // TODO: explore always setting maxLines
+            result = builder.build();
+        }
         return result;
     }
 
@@ -8576,8 +8606,8 @@
     }
 
     @Override
-    public void onProvideAssistStructure(ViewAssistStructure structure, Bundle extras) {
-        super.onProvideAssistStructure(structure, extras);
+    public void onProvideAssistStructure(ViewAssistStructure structure) {
+        super.onProvideAssistStructure(structure);
         final boolean isPassword = hasPasswordTransformationMethod();
         if (!isPassword) {
             structure.setText(getText(), getSelectionStart(), getSelectionEnd());
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 944b491..986c0f8 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Widget;
 import android.content.Context;
@@ -29,18 +30,13 @@
 import java.util.Locale;
 
 /**
- * A view for selecting the time of day, in either 24 hour or AM/PM mode. The
- * hour, each minute digit, and AM/PM (if applicable) can be conrolled by
- * vertical spinners. The hour can be entered by keyboard input. Entering in two
- * digit hours can be accomplished by hitting two digits within a timeout of
- * about a second (e.g. '1' then '2' to select 12). The minutes can be entered
- * by entering single digits. Under AM/PM mode, the user can hit 'a', 'A", 'p'
- * or 'P' to pick. For a dialog using this view, see
- * {@link android.app.TimePickerDialog}.
+ * A widget for selecting the time of day, in either 24-hour or AM/PM mode.
  * <p>
- * See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
- * guide.
- * </p>
+ * For a dialog using this view, see {@link android.app.TimePickerDialog}. See
+ * the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
+ * guide for more information.
+ *
+ * @attr ref android.R.styleable#TimePicker_timePickerMode
  */
 @Widget
 public class TimePicker extends FrameLayout {
@@ -96,44 +92,105 @@
     }
 
     /**
-     * Set the current hour.
+     * Sets the currently selected hour using 24-hour time.
+     *
+     * @param hour the hour to set, in the range (0-23)
+     * @see #getHour()
      */
-    public void setCurrentHour(Integer currentHour) {
-        mDelegate.setCurrentHour(currentHour);
+    public void setHour(int hour) {
+        mDelegate.setCurrentHour(hour);
     }
 
     /**
-     * @return The current hour in the range (0-23).
+     * Returns the currently selected hour using 24-hour time.
+     *
+     * @return the currently selected hour, in the range (0-23)
+     * @see #setHour(int)
      */
+    public int getHour() {
+        return mDelegate.getCurrentHour();
+    }
+
+    /**
+     * Sets the currently selected minute..
+     *
+     * @param minute the minute to set, in the range (0-59)
+     * @see #getMinute()
+     */
+    public void setMinute(int minute) {
+        mDelegate.setCurrentMinute(minute);
+    }
+
+    /**
+     * Returns the currently selected minute.
+     *
+     * @return the currently selected minute, in the range (0-59)
+     * @see #setMinute(int)
+     */
+    public int getMinute() {
+        return mDelegate.getCurrentMinute();
+    }
+
+    /**
+     * Sets the current hour.
+     *
+     * @deprecated Use {@link #setHour(int)}
+     */
+    @Deprecated
+    public void setCurrentHour(@NonNull Integer currentHour) {
+        setHour(currentHour);
+    }
+
+    /**
+     * @return the current hour in the range (0-23)
+     * @deprecated Use {@link #getHour()}
+     */
+    @NonNull
+    @Deprecated
     public Integer getCurrentHour() {
         return mDelegate.getCurrentHour();
     }
 
     /**
      * Set the current minute (0-59).
+     *
+     * @deprecated Use {@link #setMinute(int)}
      */
-    public void setCurrentMinute(Integer currentMinute) {
+    @Deprecated
+    public void setCurrentMinute(@NonNull Integer currentMinute) {
         mDelegate.setCurrentMinute(currentMinute);
     }
 
     /**
-     * @return The current minute.
+     * @return the current minute
+     * @deprecated Use {@link #getMinute()}
      */
+    @NonNull
+    @Deprecated
     public Integer getCurrentMinute() {
         return mDelegate.getCurrentMinute();
     }
 
     /**
-     * Set whether in 24 hour or AM/PM mode.
+     * Sets whether this widget displays time in 24-hour mode or 12-hour mode
+     * with an AM/PM picker.
      *
-     * @param is24HourView True = 24 hour mode. False = AM/PM.
+     * @param is24HourView {@code true} to display in 24-hour mode,
+     *                     {@code false} for 12-hour mode with AM/PM
+     * @see #is24HourView()
      */
-    public void setIs24HourView(Boolean is24HourView) {
+    public void setIs24HourView(@NonNull Boolean is24HourView) {
+        if (is24HourView == null) {
+            return;
+        }
+
         mDelegate.setIs24HourView(is24HourView);
     }
 
     /**
-     * @return true if this is in 24 hour view else false.
+     * @return {@code true} if this widget displays time in 24-hour mode,
+     *         {@code false} otherwise}
+     * @see #setIs24HourView(Boolean)
      */
     public boolean is24HourView() {
         return mDelegate.is24HourView();
@@ -210,13 +267,13 @@
      * for the real behavior.
      */
     interface TimePickerDelegate {
-        void setCurrentHour(Integer currentHour);
-        Integer getCurrentHour();
+        void setCurrentHour(int currentHour);
+        int getCurrentHour();
 
-        void setCurrentMinute(Integer currentMinute);
-        Integer getCurrentMinute();
+        void setCurrentMinute(int currentMinute);
+        int getCurrentMinute();
 
-        void setIs24HourView(Boolean is24HourView);
+        void setIs24HourView(boolean is24HourView);
         boolean is24HourView();
 
         void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener);
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 9fdd718..2365b48 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -16,16 +16,22 @@
 
 package android.widget;
 
+import android.annotation.Nullable;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.SpannableStringBuilder;
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
+import android.text.style.TtsSpan;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.StateSet;
 import android.util.TypedValue;
 import android.view.HapticFeedbackConstants;
 import android.view.KeyCharacterMap;
@@ -48,7 +54,6 @@
  */
 class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate implements
         RadialTimePickerView.OnValueSelectedListener {
-
     private static final String TAG = "TimePickerClockDelegate";
 
     // Index used by RadialPickerLayout
@@ -61,14 +66,16 @@
     // Also NOT a real index, just used for keyboard mode.
     private static final int ENABLE_PICKER_INDEX = 3;
 
+    private static final int[] ATTRS_TEXT_COLOR = new int[] {
+            com.android.internal.R.attr.textColor};
+    private static final int[] ATTRS_DISABLED_ALPHA = new int[] {
+            com.android.internal.R.attr.disabledAlpha};
+
     // LayoutLib relies on these constants. Change TimePickerClockDelegate_Delegate if
     // modifying these.
     static final int AM = 0;
     static final int PM = 1;
 
-    private static final boolean DEFAULT_ENABLED_STATE = true;
-    private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
-
     private static final int HOURS_IN_HALF_DAY = 12;
 
     private final View mHeaderView;
@@ -83,8 +90,7 @@
     private final String mAmText;
     private final String mPmText;
 
-    private final float mDisabledAlpha;
-
+    private boolean mIsEnabled = true;
     private boolean mAllowAutoAdvance;
     private int mInitialHourOfDay;
     private int mInitialMinute;
@@ -134,7 +140,6 @@
         final View mainView = inflater.inflate(layoutResourceId, delegator);
 
         mHeaderView = mainView.findViewById(R.id.time_header);
-        mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
 
         // Set up hour/minute labels.
         mHourView = (TextView) mainView.findViewById(R.id.hours);
@@ -147,42 +152,58 @@
         mMinuteView.setAccessibilityDelegate(
                 new ClickActionDelegate(context, R.string.select_minutes));
 
-        final int headerTimeTextAppearance = a.getResourceId(
-                R.styleable.TimePicker_headerTimeTextAppearance, 0);
-        if (headerTimeTextAppearance != 0) {
-            mHourView.setTextAppearance(context, headerTimeTextAppearance);
-            mSeparatorView.setTextAppearance(context, headerTimeTextAppearance);
-            mMinuteView.setTextAppearance(context, headerTimeTextAppearance);
-        }
-
         // Now that we have text appearances out of the way, make sure the hour
         // and minute views are correctly sized.
         mHourView.setMinWidth(computeStableWidth(mHourView, 24));
         mMinuteView.setMinWidth(computeStableWidth(mMinuteView, 60));
 
+        final SpannableStringBuilder amLabel = new SpannableStringBuilder()
+                .append(amPmStrings[0], new TtsSpan.VerbatimBuilder(amPmStrings[0]).build(), 0);
+
         // Set up AM/PM labels.
         mAmPmLayout = mainView.findViewById(R.id.ampm_layout);
         mAmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.am_label);
-        mAmLabel.setText(amPmStrings[0]);
+        mAmLabel.setText(obtainVerbatim(amPmStrings[0]));
         mAmLabel.setOnClickListener(mClickListener);
         mPmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.pm_label);
-        mPmLabel.setText(amPmStrings[1]);
+        mPmLabel.setText(obtainVerbatim(amPmStrings[1]));
         mPmLabel.setOnClickListener(mClickListener);
 
-        final int headerAmPmTextAppearance = a.getResourceId(
-                R.styleable.TimePicker_headerAmPmTextAppearance, 0);
-        if (headerAmPmTextAppearance != 0) {
-            mAmLabel.setTextAppearance(context, headerAmPmTextAppearance);
-            mPmLabel.setTextAppearance(context, headerAmPmTextAppearance);
+        // For the sake of backwards compatibility, attempt to extract the text
+        // color from the header time text appearance. If it's set, we'll let
+        // that override the "real" header text color.
+        ColorStateList headerTextColor = null;
+
+        @SuppressWarnings("deprecation")
+        final int timeHeaderTextAppearance = a.getResourceId(
+                R.styleable.TimePicker_headerTimeTextAppearance, 0);
+        if (timeHeaderTextAppearance != 0) {
+            final TypedArray textAppearance = mContext.obtainStyledAttributes(null,
+                    ATTRS_TEXT_COLOR, 0, timeHeaderTextAppearance);
+            final ColorStateList legacyHeaderTextColor = textAppearance.getColorStateList(0);
+            headerTextColor = applyLegacyColorFixes(legacyHeaderTextColor);
+            textAppearance.recycle();
+        }
+
+        if (headerTextColor == null) {
+            headerTextColor = a.getColorStateList(R.styleable.TimePicker_headerTextColor);
+        }
+
+        if (headerTextColor != null) {
+            mHourView.setTextColor(headerTextColor);
+            mSeparatorView.setTextColor(headerTextColor);
+            mMinuteView.setTextColor(headerTextColor);
+            mAmLabel.setTextColor(headerTextColor);
+            mPmLabel.setTextColor(headerTextColor);
+        }
+
+        // Set up header background, if available.
+        if (a.hasValueOrEmpty(R.styleable.TimePicker_headerBackground)) {
+            mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
         }
 
         a.recycle();
 
-        // Pull disabled alpha from theme.
-        final TypedValue outValue = new TypedValue();
-        context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
-        mDisabledAlpha = outValue.getFloat();
-
         mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById(
                 R.id.radial_picker);
 
@@ -204,6 +225,59 @@
         initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX);
     }
 
+    private static final CharSequence obtainVerbatim(String text) {
+        return new SpannableStringBuilder().append(text,
+                new TtsSpan.VerbatimBuilder(text).build(), 0);
+    }
+
+    /**
+     * The legacy text color might have been poorly defined. Ensures that it
+     * has an appropriate activated state, using the selected state if one
+     * exists or modifying the default text color otherwise.
+     *
+     * @param color a legacy text color, or {@code null}
+     * @return a color state list with an appropriate activated state, or
+     *         {@code null} if a valid activated state could not be generated
+     */
+    @Nullable
+    private ColorStateList applyLegacyColorFixes(@Nullable ColorStateList color) {
+        if (color == null || color.hasState(R.attr.state_activated)) {
+            return color;
+        }
+
+        final int activatedColor;
+        final int defaultColor;
+        if (color.hasState(R.attr.state_selected)) {
+            activatedColor = color.getColorForState(StateSet.get(
+                    StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_SELECTED), 0);
+            defaultColor = color.getColorForState(StateSet.get(
+                    StateSet.VIEW_STATE_ENABLED), 0);
+        } else {
+            activatedColor = color.getDefaultColor();
+
+            // Generate a non-activated color using the disabled alpha.
+            final TypedArray ta = mContext.obtainStyledAttributes(ATTRS_DISABLED_ALPHA);
+            final float disabledAlpha = ta.getFloat(0, 0.30f);
+            defaultColor = multiplyAlphaComponent(activatedColor, disabledAlpha);
+        }
+
+        if (activatedColor == 0 || defaultColor == 0) {
+            // We somehow failed to obtain the colors.
+            return null;
+        }
+
+        final int[][] stateSet = new int[][] {{ R.attr.state_activated }, {}};
+        final int[] colors = new int[] { activatedColor, defaultColor };
+        return new ColorStateList(stateSet, colors);
+    }
+
+    private int multiplyAlphaComponent(int color, float alphaMod) {
+        final int srcRgb = color & 0xFFFFFF;
+        final int srcAlpha = (color >> 24) & 0xFF;
+        final int dstAlpha = (int) (srcAlpha * alphaMod + 0.5f);
+        return srcRgb | (dstAlpha << 24);
+    }
+
     private static class ClickActionDelegate extends AccessibilityDelegate {
         private final AccessibilityAction mClickAction;
 
@@ -312,7 +386,7 @@
      * Set the current hour.
      */
     @Override
-    public void setCurrentHour(Integer currentHour) {
+    public void setCurrentHour(int currentHour) {
         if (mInitialHourOfDay == currentHour) {
             return;
         }
@@ -329,7 +403,7 @@
      * @return The current hour in the range (0-23).
      */
     @Override
-    public Integer getCurrentHour() {
+    public int getCurrentHour() {
         int currentHour = mRadialTimePickerView.getCurrentHour();
         if (mIs24HourView) {
             return currentHour;
@@ -348,7 +422,7 @@
      * Set the current minute (0-59).
      */
     @Override
-    public void setCurrentMinute(Integer currentMinute) {
+    public void setCurrentMinute(int currentMinute) {
         if (mInitialMinute == currentMinute) {
             return;
         }
@@ -363,7 +437,7 @@
      * @return The current minute.
      */
     @Override
-    public Integer getCurrentMinute() {
+    public int getCurrentMinute() {
         return mRadialTimePickerView.getCurrentMinute();
     }
 
@@ -373,7 +447,7 @@
      * @param is24HourView True = 24 hour mode. False = AM/PM.
      */
     @Override
-    public void setIs24HourView(Boolean is24HourView) {
+    public void setIs24HourView(boolean is24HourView) {
         if (is24HourView == mIs24HourView) {
             return;
         }
@@ -604,12 +678,12 @@
 
     private void updateAmPmLabelStates(int amOrPm) {
         final boolean isAm = amOrPm == AM;
+        mAmLabel.setActivated(isAm);
         mAmLabel.setChecked(isAm);
-        mAmLabel.setSelected(isAm);
 
         final boolean isPm = amOrPm == PM;
+        mPmLabel.setActivated(isPm);
         mPmLabel.setChecked(isPm);
-        mPmLabel.setSelected(isPm);
     }
 
     /**
@@ -769,8 +843,8 @@
             }
         }
 
-        mHourView.setSelected(index == HOUR_INDEX);
-        mMinuteView.setSelected(index == MINUTE_INDEX);
+        mHourView.setActivated(index == HOUR_INDEX);
+        mMinuteView.setActivated(index == MINUTE_INDEX);
     }
 
     private void setAmOrPm(int amOrPm) {
@@ -960,9 +1034,9 @@
             String minuteStr = (values[1] == -1) ? mDoublePlaceholderText :
                     String.format(minuteFormat, values[1]).replace(' ', mPlaceholderText);
             mHourView.setText(hourStr);
-            mHourView.setSelected(false);
+            mHourView.setActivated(false);
             mMinuteView.setText(minuteStr);
-            mMinuteView.setSelected(false);
+            mMinuteView.setActivated(false);
             if (!mIs24HourView) {
                 updateAmPmLabelStates(values[2]);
             }
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 513c55b..df6b0a9 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -279,13 +279,13 @@
     }
 
     @Override
-    public void setCurrentHour(Integer currentHour) {
+    public void setCurrentHour(int currentHour) {
         setCurrentHour(currentHour, true);
     }
 
-    private void setCurrentHour(Integer currentHour, boolean notifyTimeChanged) {
+    private void setCurrentHour(int currentHour, boolean notifyTimeChanged) {
         // why was Integer used in the first place?
-        if (currentHour == null || currentHour == getCurrentHour()) {
+        if (currentHour == getCurrentHour()) {
             return;
         }
         if (!is24HourView()) {
@@ -310,7 +310,7 @@
     }
 
     @Override
-    public Integer getCurrentHour() {
+    public int getCurrentHour() {
         int currentHour = mHourSpinner.getValue();
         if (is24HourView()) {
             return currentHour;
@@ -322,7 +322,7 @@
     }
 
     @Override
-    public void setCurrentMinute(Integer currentMinute) {
+    public void setCurrentMinute(int currentMinute) {
         if (currentMinute == getCurrentMinute()) {
             return;
         }
@@ -331,12 +331,12 @@
     }
 
     @Override
-    public Integer getCurrentMinute() {
+    public int getCurrentMinute() {
         return mMinuteSpinner.getValue();
     }
 
     @Override
-    public void setIs24HourView(Boolean is24HourView) {
+    public void setIs24HourView(boolean is24HourView) {
         if (mIs24HourView == is24HourView) {
             return;
         }
diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java
index 7bd502e..7182414 100644
--- a/core/java/android/widget/YearPickerView.java
+++ b/core/java/android/widget/YearPickerView.java
@@ -111,16 +111,12 @@
         mAdapter.setRange(min, max);
     }
 
-    public void setYearTextAppearance(int resId) {
-        mAdapter.setItemTextAppearance(resId);
-    }
-
-    public void setYearActivatedTextAppearance(int resId) {
-        mAdapter.setItemActivatedTextAppearance(resId);
-    }
-
     private static class YearAdapter extends BaseAdapter {
         private static final int ITEM_LAYOUT = R.layout.year_label_text_view;
+        private static final int ITEM_TEXT_APPEARANCE =
+                R.style.TextAppearance_Material_DatePicker_List_YearLabel;
+        private static final int ITEM_TEXT_ACTIVATED_APPEARANCE =
+                R.style.TextAppearance_Material_DatePicker_List_YearLabel_Activated;
 
         private final LayoutInflater mInflater;
 
@@ -128,9 +124,6 @@
         private int mMinYear;
         private int mCount;
 
-        private int mItemTextAppearanceResId;
-        private int mItemActivatedTextAppearanceResId;
-
         public YearAdapter(Context context) {
             mInflater = LayoutInflater.from(context);
         }
@@ -155,16 +148,6 @@
             return false;
         }
 
-        public void setItemTextAppearance(int resId) {
-            mItemTextAppearanceResId = resId;
-            notifyDataSetChanged();
-        }
-
-        public void setItemActivatedTextAppearance(int resId) {
-            mItemActivatedTextAppearanceResId = resId;
-            notifyDataSetChanged();
-        }
-
         @Override
         public int getCount() {
             return mCount;
@@ -203,10 +186,10 @@
             final boolean activated = mActivatedYear == year;
 
             final int textAppearanceResId;
-            if (activated && mItemActivatedTextAppearanceResId != 0) {
-                textAppearanceResId = mItemActivatedTextAppearanceResId;
+            if (activated && ITEM_TEXT_ACTIVATED_APPEARANCE != 0) {
+                textAppearanceResId = ITEM_TEXT_ACTIVATED_APPEARANCE;
             } else {
-                textAppearanceResId = mItemTextAppearanceResId;
+                textAppearanceResId = ITEM_TEXT_APPEARANCE;
             }
 
             final TextView v = (TextView) convertView;
diff --git a/core/java/com/android/internal/app/DumpHeapActivity.java b/core/java/com/android/internal/app/DumpHeapActivity.java
index 7e70b0c..0ce501e 100644
--- a/core/java/com/android/internal/app/DumpHeapActivity.java
+++ b/core/java/com/android/internal/app/DumpHeapActivity.java
@@ -17,13 +17,16 @@
 package com.android.internal.app;
 
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
 import android.content.ClipData;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.DebugUtils;
+import android.util.Slog;
 
 /**
  * This activity is displayed when the system has collected a heap dump from
@@ -34,6 +37,8 @@
     public static final String KEY_PROCESS = "process";
     /** The size limit the process reached */
     public static final String KEY_SIZE = "size";
+    /** Optional name of package to directly launch */
+    public static final String KEY_DIRECT_LAUNCH = "direct_launch";
 
     // Broadcast action to determine when to delete the current dump heap data.
     public static final String ACTION_DELETE_DUMPHEAP = "com.android.server.am.DELETE_DUMPHEAP";
@@ -54,6 +59,28 @@
 
         mProcess = getIntent().getStringExtra(KEY_PROCESS);
         mSize = getIntent().getLongExtra(KEY_SIZE, 0);
+
+        String directLaunch = getIntent().getStringExtra(KEY_DIRECT_LAUNCH);
+        if (directLaunch != null) {
+            Intent intent = new Intent(ActivityManager.ACTION_REPORT_HEAP_LIMIT);
+            intent.setPackage(directLaunch);
+            ClipData clip = ClipData.newUri(getContentResolver(), "Heap Dump", JAVA_URI);
+            intent.setClipData(clip);
+            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            intent.setType(clip.getDescription().getMimeType(0));
+            intent.putExtra(Intent.EXTRA_STREAM, JAVA_URI);
+            try {
+                startActivity(intent);
+                scheduleDelete();
+                mHandled = true;
+                finish();
+                return;
+            } catch (ActivityNotFoundException e) {
+                Slog.i("DumpHeapActivity", "Unable to direct launch to " + directLaunch
+                        + ": " + e.getMessage());
+            }
+        }
+
         AlertDialog.Builder b = new AlertDialog.Builder(this,
                 android.R.style.Theme_Material_Light_Dialog_Alert);
         b.setTitle(com.android.internal.R.string.dump_heap_title);
@@ -71,9 +98,7 @@
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 mHandled = true;
-                Intent broadcast = new Intent(ACTION_DELETE_DUMPHEAP);
-                broadcast.putExtra(EXTRA_DELAY_DELETE, true);
-                sendBroadcast(broadcast);
+                scheduleDelete();
                 Intent intent = new Intent(Intent.ACTION_SEND);
                 ClipData clip = ClipData.newUri(getContentResolver(), "Heap Dump", JAVA_URI);
                 intent.setClipData(clip);
@@ -88,6 +113,12 @@
         mDialog = b.show();
     }
 
+    void scheduleDelete() {
+        Intent broadcast = new Intent(ACTION_DELETE_DUMPHEAP);
+        broadcast.putExtra(EXTRA_DELAY_DELETE, true);
+        sendBroadcast(broadcast);
+    }
+
     @Override
     protected void onStop() {
         super.onStop();
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 6450d52..d149c5b9 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -16,9 +16,11 @@
 
 package com.android.internal.app;
 
+import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Bundle;
 
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
 import android.hardware.soundtrigger.SoundTrigger;
@@ -80,4 +82,28 @@
      */
     int stopRecognition(in IVoiceInteractionService service, int keyphraseId,
             in IRecognitionStatusCallback callback);
+
+    /**
+     * @return the component name for the currently active voice interaction service
+     */
+    ComponentName getActiveServiceComponentName();
+
+    /**
+     * Shows the session for the currently active service. Used to start a new session from system
+     * affordances.
+     *
+     * @param showCallback callback to be notified when the session was shown
+     */
+    void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback);
+
+    /**
+     * Indicates whether there is a voice session running (but not necessarily showing).
+     */
+    boolean isSessionRunning();
+
+    /**
+     * Indicates whether the currently active voice interaction service is capable of handling the
+     * assist gesture.
+     */
+    boolean activeServiceSupportsAssistGesture();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl
similarity index 74%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl
index 272c321..15fa89b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+package com.android.internal.app;
 
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
+oneway interface IVoiceInteractionSessionShowCallback {
+    void onFailed();
+    void onShown();
 }
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index 1f0bb76..4efefa9 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -246,9 +246,8 @@
             IActivityManager am = ActivityManagerNative.getDefault();
             Configuration config = am.getConfiguration();
 
-            // Will set userSetLocale to indicate this isn't some passing default - the user
-            // wants this remembered
             config.setLocale(locale);
+            config.userSetLocale = true;
 
             am.updateConfiguration(config);
             // Trigger the dirty bit for the Settings Provider.
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 3ceea9d..6b35f3f 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -604,9 +604,10 @@
         if ((mAlwaysUseOption || mAdapter.hasFilteredItem()) && mAdapter.mOrigResolveList != null) {
             // Build a reasonable intent filter, based on what matched.
             IntentFilter filter = new IntentFilter();
+            String action = intent.getAction();
 
-            if (intent.getAction() != null) {
-                filter.addAction(intent.getAction());
+            if (action != null) {
+                filter.addAction(action);
             }
             Set<String> categories = intent.getCategories();
             if (categories != null) {
@@ -688,8 +689,30 @@
                     if (r.match > bestMatch) bestMatch = r.match;
                 }
                 if (alwaysCheck) {
-                    getPackageManager().addPreferredActivity(filter, bestMatch, set,
-                            intent.getComponent());
+                    PackageManager pm = getPackageManager();
+
+                    // Set the preferred Activity
+                    pm.addPreferredActivity(filter, bestMatch, set, intent.getComponent());
+
+                    // Update Domain Verification status
+                    int userId = getUserId();
+                    ComponentName cn = intent.getComponent();
+                    String packageName = cn.getPackageName();
+                    String dataScheme = (data != null) ? data.getScheme() : null;
+
+                    boolean isHttpOrHttps = (dataScheme != null) &&
+                            (dataScheme.equals(IntentFilter.SCHEME_HTTP) ||
+                            dataScheme.equals(IntentFilter.SCHEME_HTTPS));
+
+                    boolean isViewAction = (action != null) && action.equals(Intent.ACTION_VIEW);
+                    boolean hasCategoryBrowsable = (categories != null) &&
+                            categories.contains(Intent.CATEGORY_BROWSABLE);
+
+                    if (isHttpOrHttps && isViewAction && hasCategoryBrowsable) {
+                        pm.updateIntentVerificationStatus(packageName,
+                                PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS,
+                                userId);
+                    }
                 } else {
                     try {
                         AppGlobals.getPackageManager().setLastChosenActivity(intent,
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index 6158a7b..083d6c7 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -238,6 +238,7 @@
 
     long requestFullBackupTime();
     int performFullBackup(in PackageInfo targetPackage, in ParcelFileDescriptor socket);
+    int checkFullBackupSize(long size);
     int sendBackupData(int numBytes);
     void cancelFullBackup();
 
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index 7bdb4be..255f1fd 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -25,15 +25,16 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageParser.PackageLite;
 import android.os.Environment;
-import android.os.Environment.UserEnvironment;
 import android.os.FileUtils;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.UserHandle;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageResultCode;
+import android.os.storage.StorageVolume;
+import android.os.storage.VolumeInfo;
+import android.util.ArraySet;
 import android.util.Log;
 
 import libcore.io.IoUtils;
@@ -335,6 +336,94 @@
 
     /**
      * Given a requested {@link PackageInfo#installLocation} and calculated
+     * install size, pick the actual volume to install the app. Only considers
+     * internal and private volumes, and prefers to keep an existing package on
+     * its current volume.
+     *
+     * @return the {@link VolumeInfo#fsUuid} to install onto, or {@code null}
+     *         for internal storage.
+     */
+    public static String resolveInstallVolume(Context context, String packageName,
+            int installLocation, long sizeBytes) throws IOException {
+        // TODO: handle existing apps installed in ASEC; currently assumes
+        // they'll end up back on internal storage
+        ApplicationInfo existingInfo = null;
+        try {
+            existingInfo = context.getPackageManager().getApplicationInfo(packageName,
+                    PackageManager.GET_UNINSTALLED_PACKAGES);
+        } catch (NameNotFoundException ignored) {
+        }
+
+        final StorageManager storageManager = context.getSystemService(StorageManager.class);
+        final boolean fitsOnInternal = fitsOnInternal(context, sizeBytes);
+
+        final ArraySet<String> allCandidates = new ArraySet<>();
+        VolumeInfo bestCandidate = null;
+        long bestCandidateAvailBytes = Long.MIN_VALUE;
+        for (VolumeInfo vol : storageManager.getVolumes()) {
+            if (vol.type == VolumeInfo.TYPE_PRIVATE && vol.state == VolumeInfo.STATE_MOUNTED) {
+                final long availBytes = storageManager.getStorageBytesUntilLow(new File(vol.path));
+                if (availBytes >= sizeBytes) {
+                    allCandidates.add(vol.fsUuid);
+                }
+                if (availBytes >= bestCandidateAvailBytes) {
+                    bestCandidate = vol;
+                    bestCandidateAvailBytes = availBytes;
+                }
+            }
+        }
+
+        // System apps always forced to internal storage
+        if (existingInfo != null && existingInfo.isSystemApp()) {
+            installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
+        }
+
+        // If app expresses strong desire for internal space, honor it
+        if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
+            if (fitsOnInternal) {
+                return null;
+            } else {
+                throw new IOException("Requested internal only, but not enough space");
+            }
+        }
+
+        // If app already exists somewhere, prefer to stay on that volume
+        if (existingInfo != null) {
+            if (existingInfo.volumeUuid == null && fitsOnInternal) {
+                return null;
+            }
+            if (allCandidates.contains(existingInfo.volumeUuid)) {
+                return existingInfo.volumeUuid;
+            }
+        }
+
+        // We're left with either preferring external or auto, so just pick
+        // volume with most space
+        if (bestCandidate != null) {
+            return bestCandidate.fsUuid;
+        } else if (fitsOnInternal) {
+            return null;
+        } else {
+            throw new IOException("No special requests, but no room anywhere");
+        }
+    }
+
+    public static boolean fitsOnInternal(Context context, long sizeBytes) {
+        final StorageManager storage = context.getSystemService(StorageManager.class);
+        final File target = Environment.getDataDirectory();
+        return (sizeBytes <= storage.getStorageBytesUntilLow(target));
+    }
+
+    public static boolean fitsOnExternal(Context context, long sizeBytes) {
+        final StorageManager storage = context.getSystemService(StorageManager.class);
+        final StorageVolume primary = storage.getPrimaryVolume();
+        return (sizeBytes > 0) && !primary.isEmulated()
+                && Environment.MEDIA_MOUNTED.equals(primary.getState())
+                && sizeBytes <= storage.getStorageBytesUntilLow(primary.getPathFile());
+    }
+
+    /**
+     * Given a requested {@link PackageInfo#installLocation} and calculated
      * install size, pick the actual location to install the app.
      */
     public static int resolveInstallLocation(Context context, String packageName,
@@ -363,6 +452,7 @@
         } else if (installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
             // When app is already installed, prefer same medium
             if (existingInfo != null) {
+                // TODO: distinguish if this is external ASEC
                 if ((existingInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                     prefer = RECOMMEND_INSTALL_EXTERNAL;
                 } else {
@@ -377,30 +467,21 @@
             checkBoth = false;
         }
 
-        final boolean emulated = Environment.isExternalStorageEmulated();
-        final StorageManager storage = StorageManager.from(context);
-
         boolean fitsOnInternal = false;
         if (checkBoth || prefer == RECOMMEND_INSTALL_INTERNAL) {
-            final File target = Environment.getDataDirectory();
-            fitsOnInternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
+            fitsOnInternal = fitsOnInternal(context, sizeBytes);
         }
 
         boolean fitsOnExternal = false;
-        if (!emulated && (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL)) {
-            final File target = new UserEnvironment(UserHandle.USER_OWNER)
-                    .getExternalStorageDirectory();
-            // External is only an option when size is known
-            if (sizeBytes > 0) {
-                fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
-            }
+        if (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL) {
+            fitsOnExternal = fitsOnExternal(context, sizeBytes);
         }
 
         if (prefer == RECOMMEND_INSTALL_INTERNAL) {
             if (fitsOnInternal) {
                 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
             }
-        } else if (!emulated && prefer == RECOMMEND_INSTALL_EXTERNAL) {
+        } else if (prefer == RECOMMEND_INSTALL_EXTERNAL) {
             if (fitsOnExternal) {
                 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
             }
@@ -409,22 +490,12 @@
         if (checkBoth) {
             if (fitsOnInternal) {
                 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
-            } else if (!emulated && fitsOnExternal) {
+            } else if (fitsOnExternal) {
                 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
             }
         }
 
-        /*
-         * If they requested to be on the external media by default, return that
-         * the media was unavailable. Otherwise, indicate there was insufficient
-         * storage space available.
-         */
-        if (!emulated && (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL)
-                && !Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
-            return PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE;
-        } else {
-            return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
-        }
+        return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
     }
 
     public static long calculateInstalledSize(PackageLite pkg, boolean isForwardLocked,
diff --git a/core/java/com/android/internal/logging/EventLogTags.logtags b/core/java/com/android/internal/logging/EventLogTags.logtags
new file mode 100644
index 0000000..870d20d
--- /dev/null
+++ b/core/java/com/android/internal/logging/EventLogTags.logtags
@@ -0,0 +1,7 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.internal.logging;
+
+# interaction logs
+524287 sysui_view_visibility (category|1|5),(visible|1|6)
+524288 sysui_action (category|1|5)
diff --git a/core/java/com/android/internal/logging/MetricsConstants.java b/core/java/com/android/internal/logging/MetricsConstants.java
new file mode 100644
index 0000000..e5cba84
--- /dev/null
+++ b/core/java/com/android/internal/logging/MetricsConstants.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.logging;
+
+/**
+ * Constants for mestrics logs.
+ *
+ * @hide
+ */
+public interface MetricsConstants {
+    // These constants must match those in the analytic pipeline.
+    public static final int ACCESSIBILITY = 2;
+    public static final int ACCESSIBILITY_CAPTION_PROPERTIES = 3;
+    public static final int ACCESSIBILITY_SERVICE = 4;
+    public static final int ACCESSIBILITY_TOGGLE_DALTONIZER = 5;
+    public static final int ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6;
+    public static final int ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7;
+    public static final int ACCOUNT = 8;
+    public static final int ACCOUNTS_ACCOUNT_SYNC = 9;
+    public static final int ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10;
+    public static final int ACCOUNTS_MANAGE_ACCOUNTS = 11;
+    public static final int APN = 12;
+    public static final int APN_EDITOR = 13;
+    public static final int APPLICATION = 16;
+    public static final int APPLICATIONS_APP_LAUNCH = 17;
+    public static final int APPLICATIONS_APP_PERMISSION = 18;
+    public static final int APPLICATIONS_APP_STORAGE = 19;
+    public static final int APPLICATIONS_INSTALLED_APP_DETAILS = 20;
+    public static final int APPLICATIONS_PROCESS_STATS_DETAIL = 21;
+    public static final int APPLICATIONS_PROCESS_STATS_MEM_DETAIL = 22;
+    public static final int APPLICATIONS_PROCESS_STATS_UI = 23;
+    public static final int APP_OPS_DETAILS = 14;
+    public static final int APP_OPS_SUMMARY = 15;
+    public static final int BLUETOOTH = 24;
+    public static final int BLUETOOTH_DEVICE_PICKER = 25;
+    public static final int BLUETOOTH_DEVICE_PROFILES = 26;
+    public static final int CHOOSE_LOCK_GENERIC = 27;
+    public static final int CHOOSE_LOCK_PASSWORD = 28;
+    public static final int CHOOSE_LOCK_PATTERN = 29;
+    public static final int CONFIRM_LOCK_PASSWORD = 30;
+    public static final int CONFIRM_LOCK_PATTERN = 31;
+    public static final int CRYPT_KEEPER = 32;
+    public static final int CRYPT_KEEPER_CONFIRM = 33;
+    public static final int DASHBOARD_SEARCH_RESULTS = 34;
+    public static final int DASHBOARD_SUMMARY = 35;
+    public static final int DATA_USAGE = 36;
+    public static final int DATA_USAGE_SUMMARY = 37;
+    public static final int DATE_TIME = 38;
+    public static final int DEVELOPMENT = 39;
+    public static final int DEVICEINFO = 40;
+    public static final int DEVICEINFO_IMEI_INFORMATION = 41;
+    public static final int DEVICEINFO_MEMORY = 42;
+    public static final int DEVICEINFO_SIM_STATUS = 43;
+    public static final int DEVICEINFO_STATUS = 44;
+    public static final int DEVICEINFO_USB = 45;
+    public static final int DISPLAY = 46;
+    public static final int DREAM = 47;
+    public static final int ENCRYPTION = 48;
+    public static final int FINGERPRINT = 49;
+    public static final int FINGERPRINT_ENROLL = 50;
+    public static final int FUELGAUGE_BATTERY_HISTORY_DETAIL = 51;
+    public static final int FUELGAUGE_BATTERY_SAVER = 52;
+    public static final int FUELGAUGE_POWER_USAGE_DETAIL = 53;
+    public static final int FUELGAUGE_POWER_USAGE_SUMMARY = 54;
+    public static final int HOME = 55;
+    public static final int ICC_LOCK = 56;
+    public static final int INPUTMETHOD_KEYBOARD = 58;
+    public static final int INPUTMETHOD_LANGUAGE = 57;
+    public static final int INPUTMETHOD_SPELL_CHECKERS = 59;
+    public static final int INPUTMETHOD_SUBTYPE_ENABLER = 60;
+    public static final int INPUTMETHOD_USER_DICTIONARY = 61;
+    public static final int INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62;
+    public static final int LOCATION = 63;
+    public static final int LOCATION_MODE = 64;
+    public static final int MAIN_SETTINGS = 1;
+    public static final int MANAGE_APPLICATIONS = 65;
+    public static final int MASTER_CLEAR = 66;
+    public static final int MASTER_CLEAR_CONFIRM = 67;
+    public static final int NET_DATA_USAGE_METERED = 68;
+    public static final int NFC_BEAM = 69;
+    public static final int NFC_PAYMENT = 70;
+    public static final int NOTIFICATION = 71;
+    public static final int NOTIFICATION_APP_NOTIFICATION = 72;
+    public static final int NOTIFICATION_OTHER_SOUND = 73;
+    public static final int NOTIFICATION_REDACTION = 74;
+    public static final int NOTIFICATION_STATION = 75;
+    public static final int NOTIFICATION_ZEN_MODE = 76;
+    public static final int OWNER_INFO = 77;
+    public static final int PRINT_JOB_SETTINGS = 78;
+    public static final int PRINT_SERVICE_SETTINGS = 79;
+    public static final int PRINT_SETTINGS = 80;
+    public static final int PRIVACY = 81;
+    public static final int PROXY_SELECTOR = 82;
+    public static final int QS_AIRPLANEMODE = 112;
+    public static final int QS_BLUETOOTH = 113;
+    public static final int QS_CAST = 114;
+    public static final int QS_CELLULAR = 115;
+    public static final int QS_COLORINVERSION = 116;
+    public static final int QS_DATAUSAGEDETAIL = 117;
+    public static final int QS_DND = 118;
+    public static final int QS_FLASHLIGHT = 119;
+    public static final int QS_HOTSPOT = 120;
+    public static final int QS_INTENT = 121;
+    public static final int QS_LOCATION = 122;
+    public static final int QS_PANEL = 111;
+    public static final int QS_ROTATIONLOCK = 123;
+    public static final int QS_USERDETAIL = 125;
+    public static final int QS_USERDETAILITE = 124;
+    public static final int QS_WIFI = 126;
+    public static final int RESET_NETWORK = 83;
+    public static final int RESET_NETWORK_CONFIRM = 84;
+    public static final int RUNNING_SERVICE_DETAILS = 85;
+    public static final int SCREEN_PINNING = 86;
+    public static final int SECURITY = 87;
+    public static final int SIM = 88;
+    public static final int TESTING = 89;
+    public static final int TETHER = 90;
+    public static final int TRUSTED_CREDENTIALS = 92;
+    public static final int TRUST_AGENT = 91;
+    public static final int TTS_ENGINE_SETTINGS = 93;
+    public static final int TTS_TEXT_TO_SPEECH = 94;
+    public static final int TYPE_UNKNOWN = 0;
+    public static final int USAGE_ACCESS = 95;
+    public static final int USER = 96;
+    public static final int USERS_APP_RESTRICTIONS = 97;
+    public static final int USER_DETAILS = 98;
+    public static final int VIEW_UNKNOWN = 0;
+    public static final int VOICE_INPUT = 99;
+    public static final int VPN = 100;
+    public static final int WALLPAPER_TYPE = 101;
+    public static final int WFD_WIFI_DISPLAY = 102;
+    public static final int WIFI = 103;
+    public static final int WIFI_ADVANCED = 104;
+    public static final int WIFI_APITEST = 107;
+    public static final int WIFI_CALLING = 105;
+    public static final int WIFI_INFO = 108;
+    public static final int WIFI_P2P = 109;
+    public static final int WIFI_SAVED_ACCESS_POINTS = 106;
+    public static final int WIRELESS = 110;
+}
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
new file mode 100644
index 0000000..1038543
--- /dev/null
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -0,0 +1,67 @@
+/*
+ * 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.internal.logging;
+
+
+import android.content.Context;
+import android.os.Build;
+
+/**
+ * Log all the things.
+ *
+ * @hide
+ */
+public class MetricsLogger implements MetricsConstants {
+    // These constants are temporary, they should migrate to MetricsConstants.
+    public static final int APPLICATIONS_ADVANCED = 132;
+    public static final int LOCATION_SCANNING = 133;
+    public static final int MANAGE_APPLICATIONS_ALL = 134;
+    public static final int MANAGE_APPLICATIONS_NOTIFICATIONS = 135;
+
+    public static final int ACTION_WIFI_ADD_NETWORK = 136;
+    public static final int ACTION_WIFI_CONNECT = 137;
+    public static final int ACTION_WIFI_FORCE_SCAN = 138;
+    public static final int ACTION_WIFI_FORGET = 139;
+    public static final int ACTION_WIFI_OFF = 140;
+    public static final int ACTION_WIFI_ON = 141;
+
+    public static final int MANAGE_PERMISSIONS = 142;
+    public static final int NOTIFICATION_ZEN_MODE_PRIORITY = 143;
+    public static final int NOTIFICATION_ZEN_MODE_AUTOMATION = 144;
+
+    public static final int MANAGE_DOMAIN_URLS = 143;
+
+    public static void visible(Context context, int category) throws IllegalArgumentException {
+        if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
+            throw new IllegalArgumentException("Must define metric category");
+        }
+        EventLogTags.writeSysuiViewVisibility(category, 100);
+    }
+
+    public static void hidden(Context context, int category) {
+        if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
+            throw new IllegalArgumentException("Must define metric category");
+        }
+        EventLogTags.writeSysuiViewVisibility(category, 0);
+    }
+
+    public static void action(Context context, int category) {
+        if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
+            throw new IllegalArgumentException("Must define metric category");
+        }
+        EventLogTags.writeSysuiAction(category);
+    }
+}
diff --git a/core/java/com/android/internal/midi/EventScheduler.java b/core/java/com/android/internal/midi/EventScheduler.java
new file mode 100644
index 0000000..7b9a48c
--- /dev/null
+++ b/core/java/com/android/internal/midi/EventScheduler.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.midi;
+
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * Store arbitrary timestamped events using a Long timestamp.
+ * Only one Thread can write into the buffer.
+ * And only one Thread can read from the buffer.
+ */
+public class EventScheduler {
+    private static final long NANOS_PER_MILLI = 1000000;
+
+    private final Object mLock = new Object();
+    private SortedMap<Long, FastEventQueue> mEventBuffer;
+    private FastEventQueue mEventPool = null;
+    private int mMaxPoolSize = 200;
+    private boolean mClosed;
+
+    public EventScheduler() {
+        mEventBuffer = new TreeMap<Long, FastEventQueue>();
+    }
+
+    // If we keep at least one node in the list then it can be atomic
+    // and non-blocking.
+    private class FastEventQueue {
+        // One thread takes from the beginning of the list.
+        volatile SchedulableEvent mFirst;
+        // A second thread returns events to the end of the list.
+        volatile SchedulableEvent mLast;
+        volatile long mEventsAdded;
+        volatile long mEventsRemoved;
+
+        FastEventQueue(SchedulableEvent event) {
+            mFirst = event;
+            mLast = mFirst;
+            mEventsAdded = 1;
+            mEventsRemoved = 0;
+        }
+
+        int size() {
+            return (int)(mEventsAdded - mEventsRemoved);
+        }
+
+        /**
+         * Do not call this unless there is more than one event
+         * in the list.
+         * @return first event in the list
+         */
+        public SchedulableEvent remove() {
+            // Take first event.
+            mEventsRemoved++;
+            SchedulableEvent event = mFirst;
+            mFirst = event.mNext;
+            return event;
+        }
+
+        /**
+         * @param event
+         */
+        public void add(SchedulableEvent event) {
+            event.mNext = null;
+            mLast.mNext = event;
+            mLast = event;
+            mEventsAdded++;
+        }
+    }
+
+    /**
+     * Base class for events that can be stored in the EventScheduler.
+     */
+    public static class SchedulableEvent {
+        private long mTimestamp;
+        private SchedulableEvent mNext = null;
+
+        /**
+         * @param timestamp
+         */
+        public SchedulableEvent(long timestamp) {
+            mTimestamp = timestamp;
+        }
+
+        /**
+         * @return timestamp
+         */
+        public long getTimestamp() {
+            return mTimestamp;
+        }
+
+        /**
+         * The timestamp should not be modified when the event is in the
+         * scheduling buffer.
+         */
+        public void setTimestamp(long timestamp) {
+            mTimestamp = timestamp;
+        }
+    }
+
+    /**
+     * Get an event from the pool.
+     * Always leave at least one event in the pool.
+     * @return event or null
+     */
+    public SchedulableEvent removeEventfromPool() {
+        SchedulableEvent event = null;
+        if (mEventPool != null && (mEventPool.size() > 1)) {
+            event = mEventPool.remove();
+        }
+        return event;
+    }
+
+    /**
+     * Return events to a pool so they can be reused.
+     *
+     * @param event
+     */
+    public void addEventToPool(SchedulableEvent event) {
+        if (mEventPool == null) {
+            mEventPool = new FastEventQueue(event);
+        // If we already have enough items in the pool then just
+        // drop the event. This prevents unbounded memory leaks.
+        } else if (mEventPool.size() < mMaxPoolSize) {
+            mEventPool.add(event);
+        }
+    }
+
+    /**
+     * Add an event to the scheduler. Events with the same time will be
+     * processed in order.
+     *
+     * @param event
+     */
+    public void add(SchedulableEvent event) {
+        synchronized (mLock) {
+            FastEventQueue list = mEventBuffer.get(event.getTimestamp());
+            if (list == null) {
+                long lowestTime = mEventBuffer.isEmpty() ? Long.MAX_VALUE
+                        : mEventBuffer.firstKey();
+                list = new FastEventQueue(event);
+                mEventBuffer.put(event.getTimestamp(), list);
+                // If the event we added is earlier than the previous earliest
+                // event then notify any threads waiting for the next event.
+                if (event.getTimestamp() < lowestTime) {
+                    mLock.notify();
+                }
+            } else {
+                list.add(event);
+            }
+        }
+    }
+
+    private SchedulableEvent removeNextEventLocked(long lowestTime) {
+        SchedulableEvent event;
+        FastEventQueue list = mEventBuffer.get(lowestTime);
+        // Remove list from tree if this is the last node.
+        if ((list.size() == 1)) {
+            mEventBuffer.remove(lowestTime);
+        }
+        event = list.remove();
+        return event;
+    }
+
+    /**
+     * Check to see if any scheduled events are ready to be processed.
+     *
+     * @param timestamp
+     * @return next event or null if none ready
+     */
+    public SchedulableEvent getNextEvent(long time) {
+        SchedulableEvent event = null;
+        synchronized (mLock) {
+            if (!mEventBuffer.isEmpty()) {
+                long lowestTime = mEventBuffer.firstKey();
+                // Is it time for this list to be processed?
+                if (lowestTime <= time) {
+                    event = removeNextEventLocked(lowestTime);
+                }
+            }
+        }
+        // Log.i(TAG, "getNextEvent: event = " + event);
+        return event;
+    }
+
+    /**
+     * Return the next available event or wait until there is an event ready to
+     * be processed. This method assumes that the timestamps are in nanoseconds
+     * and that the current time is System.nanoTime().
+     *
+     * @return event
+     * @throws InterruptedException
+     */
+    public SchedulableEvent waitNextEvent() throws InterruptedException {
+        SchedulableEvent event = null;
+        synchronized (mLock) {
+            while (!mClosed) {
+                long millisToWait = Integer.MAX_VALUE;
+                if (!mEventBuffer.isEmpty()) {
+                    long now = System.nanoTime();
+                    long lowestTime = mEventBuffer.firstKey();
+                    // Is it time for the earliest list to be processed?
+                    if (lowestTime <= now) {
+                        event = removeNextEventLocked(lowestTime);
+                        break;
+                    } else {
+                        // Figure out how long to sleep until next event.
+                        long nanosToWait = lowestTime - now;
+                        // Add 1 millisecond so we don't wake up before it is
+                        // ready.
+                        millisToWait = 1 + (nanosToWait / NANOS_PER_MILLI);
+                        // Clip 64-bit value to 32-bit max.
+                        if (millisToWait > Integer.MAX_VALUE) {
+                            millisToWait = Integer.MAX_VALUE;
+                        }
+                    }
+                }
+                mLock.wait((int) millisToWait);
+            }
+        }
+        return event;
+    }
+
+    public void close() {
+        synchronized (mLock) {
+            mClosed = true;
+            mLock.notify();
+        }
+    }
+}
diff --git a/core/java/com/android/internal/midi/MidiConstants.java b/core/java/com/android/internal/midi/MidiConstants.java
new file mode 100644
index 0000000..87552e4
--- /dev/null
+++ b/core/java/com/android/internal/midi/MidiConstants.java
@@ -0,0 +1,88 @@
+/*
+ * 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.internal.midi;
+
+/**
+ * MIDI related constants and static methods.
+ */
+public class MidiConstants {
+    public static final byte STATUS_COMMAND_MASK = (byte) 0xF0;
+    public static final byte STATUS_CHANNEL_MASK = (byte) 0x0F;
+
+    // Channel voice messages.
+    public static final byte STATUS_NOTE_OFF = (byte) 0x80;
+    public static final byte STATUS_NOTE_ON = (byte) 0x90;
+    public static final byte STATUS_POLYPHONIC_AFTERTOUCH = (byte) 0xA0;
+    public static final byte STATUS_CONTROL_CHANGE = (byte) 0xB0;
+    public static final byte STATUS_PROGRAM_CHANGE = (byte) 0xC0;
+    public static final byte STATUS_CHANNEL_PRESSURE = (byte) 0xD0;
+    public static final byte STATUS_PITCH_BEND = (byte) 0xE0;
+
+    // System Common Messages.
+    public static final byte STATUS_SYSTEM_EXCLUSIVE = (byte) 0xF0;
+    public static final byte STATUS_MIDI_TIME_CODE = (byte) 0xF1;
+    public static final byte STATUS_SONG_POSITION = (byte) 0xF2;
+    public static final byte STATUS_SONG_SELECT = (byte) 0xF3;
+    public static final byte STATUS_TUNE_REQUEST = (byte) 0xF6;
+    public static final byte STATUS_END_SYSEX = (byte) 0xF7;
+
+    // System Real-Time Messages
+    public static final byte STATUS_TIMING_CLOCK = (byte) 0xF8;
+    public static final byte STATUS_START = (byte) 0xFA;
+    public static final byte STATUS_CONTINUE = (byte) 0xFB;
+    public static final byte STATUS_STOP = (byte) 0xFC;
+    public static final byte STATUS_ACTIVE_SENSING = (byte) 0xFE;
+    public static final byte STATUS_RESET = (byte) 0xFF;
+
+    /** Number of bytes in a message nc from 8c to Ec */
+    public final static int CHANNEL_BYTE_LENGTHS[] = { 3, 3, 3, 3, 2, 2, 3 };
+
+    /** Number of bytes in a message Fn from F0 to FF */
+    public final static int SYSTEM_BYTE_LENGTHS[] = { 1, 2, 3, 2, 1, 1, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1 };
+
+    /********************************************************************/
+
+    public static int getBytesPerMessage(int command) {
+        if ((command < 0x80) || (command > 0xFF)) {
+            return 0;
+        } else if (command >= 0xF0) {
+            return SYSTEM_BYTE_LENGTHS[command & 0x0F];
+        } else {
+            return CHANNEL_BYTE_LENGTHS[(command >> 4) - 8];
+        }
+    }
+
+    /**
+     * @param msg
+     * @param offset
+     * @param count
+     * @return true if the entire message is ActiveSensing commands
+     */
+    public static boolean isAllActiveSensing(byte[] msg, int offset,
+            int count) {
+        // Count bytes that are not active sensing.
+        int goodBytes = 0;
+        for (int i = 0; i < count; i++) {
+            byte b = msg[offset + i];
+            if (b != MidiConstants.STATUS_ACTIVE_SENSING) {
+                goodBytes++;
+            }
+        }
+        return (goodBytes == 0);
+    }
+}
diff --git a/media/java/android/media/midi/MidiDispatcher.java b/core/java/com/android/internal/midi/MidiDispatcher.java
similarity index 73%
rename from media/java/android/media/midi/MidiDispatcher.java
rename to core/java/com/android/internal/midi/MidiDispatcher.java
index 0868346..377bc68 100644
--- a/media/java/android/media/midi/MidiDispatcher.java
+++ b/core/java/com/android/internal/midi/MidiDispatcher.java
@@ -14,19 +14,20 @@
  * limitations under the License.
  */
 
-package android.media.midi;
+package com.android.internal.midi;
+
+import android.media.midi.MidiReceiver;
+import android.media.midi.MidiSender;
 
 import java.io.IOException;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
- * Utility class for dispatching MIDI data to a list of {@link MidiReceiver}s.
- * This class subclasses {@link MidiReceiver} and dispatches any data it receives
+ * Utility class for dispatching MIDI data to a list of {@link android.media.midi.MidiReceiver}s.
+ * This class subclasses {@link android.media.midi.MidiReceiver} and dispatches any data it receives
  * to its receiver list. Any receivers that throw an exception upon receiving data will
  * be automatically removed from the receiver list, but no IOException will be returned
- * from the dispatcher's {@link #onReceive} in that case.
- *
- * @hide
+ * from the dispatcher's {@link android.media.midi.MidiReceiver#onReceive} in that case.
  */
 public final class MidiDispatcher extends MidiReceiver {
 
@@ -35,7 +36,7 @@
 
     private final MidiSender mSender = new MidiSender() {
         /**
-         * Called to connect a {@link MidiReceiver} to the sender
+         * Called to connect a {@link android.media.midi.MidiReceiver} to the sender
          *
          * @param receiver the receiver to connect
          */
@@ -44,7 +45,7 @@
         }
 
         /**
-         * Called to disconnect a {@link MidiReceiver} from the sender
+         * Called to disconnect a {@link android.media.midi.MidiReceiver} from the sender
          *
          * @param receiver the receiver to disconnect
          */
@@ -54,7 +55,7 @@
     };
 
     /**
-     * Returns the number of {@link MidiReceiver}s this dispatcher contains.
+     * Returns the number of {@link android.media.midi.MidiReceiver}s this dispatcher contains.
      * @return the number of receivers
      */
     public int getReceiverCount() {
@@ -62,7 +63,8 @@
     }
 
     /**
-     * Returns a {@link MidiSender} which is used to add and remove {@link MidiReceiver}s
+     * Returns a {@link android.media.midi.MidiSender} which is used to add and remove
+     * {@link android.media.midi.MidiReceiver}s
      * to the dispatcher's receiver list.
      * @return the dispatcher's MidiSender
      */
diff --git a/core/java/com/android/internal/midi/MidiEventScheduler.java b/core/java/com/android/internal/midi/MidiEventScheduler.java
new file mode 100644
index 0000000..42d70f6
--- /dev/null
+++ b/core/java/com/android/internal/midi/MidiEventScheduler.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.midi;
+
+import android.media.midi.MidiReceiver;
+
+import java.io.IOException;
+
+/**
+ * Add MIDI Events to an EventScheduler
+ */
+public class MidiEventScheduler extends EventScheduler {
+    private static final String TAG = "MidiEventScheduler";
+    // Maintain a pool of scheduled events to reduce memory allocation.
+    // This pool increases performance by about 14%.
+    private final static int POOL_EVENT_SIZE = 16;
+
+    private final MidiReceiver[] mReceivers;
+
+    private class SchedulingReceiver extends MidiReceiver {
+        private final int mPortNumber;
+
+        public SchedulingReceiver(int portNumber) {
+            mPortNumber = portNumber;
+        }
+
+        /**
+         * Store these bytes in the EventScheduler to be delivered at the specified
+         * time.
+         */
+        @Override
+        public void onReceive(byte[] msg, int offset, int count, long timestamp)
+                throws IOException {
+            MidiEvent event = createScheduledEvent(msg, offset, count, timestamp);
+            if (event != null) {
+                event.portNumber = mPortNumber;
+                add(event);
+            }
+        }
+    }
+
+    public static class MidiEvent extends SchedulableEvent {
+        public int portNumber;
+        public int count = 0;
+        public byte[] data;
+
+        private MidiEvent(int count) {
+            super(0);
+            data = new byte[count];
+        }
+
+        private MidiEvent(byte[] msg, int offset, int count, long timestamp) {
+            super(timestamp);
+            data = new byte[count];
+            System.arraycopy(msg, offset, data, 0, count);
+            this.count = count;
+        }
+
+        @Override
+        public String toString() {
+            String text = "Event: ";
+            for (int i = 0; i < count; i++) {
+                text += data[i] + ", ";
+            }
+            return text;
+        }
+    }
+
+    public MidiEventScheduler() {
+        this(0);
+    }
+
+    public MidiEventScheduler(int portCount) {
+        mReceivers = new MidiReceiver[portCount];
+        for (int i = 0; i < portCount; i++) {
+            mReceivers[i] = new SchedulingReceiver(i);
+        }
+    }
+
+    /**
+     * Create an event that contains the message.
+     */
+    private MidiEvent createScheduledEvent(byte[] msg, int offset, int count,
+            long timestamp) {
+        MidiEvent event;
+        if (count > POOL_EVENT_SIZE) {
+            event = new MidiEvent(msg, offset, count, timestamp);
+        } else {
+            event = (MidiEvent) removeEventfromPool();
+            if (event == null) {
+                event = new MidiEvent(POOL_EVENT_SIZE);
+            }
+            System.arraycopy(msg, offset, event.data, 0, count);
+            event.count = count;
+            event.setTimestamp(timestamp);
+        }
+        return event;
+    }
+
+    /**
+     * Return events to a pool so they can be reused.
+     *
+     * @param event
+     */
+    @Override
+    public void addEventToPool(SchedulableEvent event) {
+        // Make sure the event is suitable for the pool.
+        if (event instanceof MidiEvent) {
+            MidiEvent midiEvent = (MidiEvent) event;
+            if (midiEvent.data.length == POOL_EVENT_SIZE) {
+                super.addEventToPool(event);
+            }
+        }
+    }
+
+    /**
+     * This MidiReceiver will write date to the scheduling buffer.
+     * @return the MidiReceiver
+     */
+    public MidiReceiver getReceiver() {
+        return mReceivers[0];
+    }
+
+    /**
+     * This MidiReceiver will write date to the scheduling buffer.
+     * @return the MidiReceiver
+     */
+    public MidiReceiver getReceiver(int portNumber) {
+        return mReceivers[portNumber];
+    }
+
+}
diff --git a/core/java/com/android/internal/midi/MidiFramer.java b/core/java/com/android/internal/midi/MidiFramer.java
new file mode 100644
index 0000000..53d71bb
--- /dev/null
+++ b/core/java/com/android/internal/midi/MidiFramer.java
@@ -0,0 +1,92 @@
+/*
+ * 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.internal.midi;
+
+import android.media.midi.MidiReceiver;
+
+import java.io.IOException;
+
+/**
+ * Convert stream of bytes to discrete messages.
+ *
+ * Parses the incoming bytes and then posts individual messages to the receiver
+ * specified in the constructor. Short messages of 1-3 bytes will be complete.
+ * System Exclusive messages may be posted in pieces.
+ *
+ * Resolves Running Status and
+ * interleaved System Real-Time messages.
+ */
+public class MidiFramer extends MidiReceiver {
+
+    public String TAG = "MidiFramer";
+    private MidiReceiver mReceiver;
+    private byte[] mBuffer = new byte[3];
+    private int mCount;
+    private int mRunningStatus;
+    private int mNeeded;
+
+    public MidiFramer(MidiReceiver receiver) {
+        mReceiver = receiver;
+    }
+
+    public static String formatMidiData(byte[] data, int offset, int count) {
+        String text = "MIDI+" + offset + " : ";
+        for (int i = 0; i < count; i++) {
+            text += String.format("0x%02X, ", data[offset + i]);
+        }
+        return text;
+    }
+
+    /*
+     * @see android.midi.MidiReceiver#onPost(byte[], int, int, long)
+     */
+    @Override
+    public void onReceive(byte[] data, int offset, int count, long timestamp)
+            throws IOException {
+        // Log.i(TAG, formatMidiData(data, offset, count));
+        for (int i = 0; i < count; i++) {
+            int b = data[offset] & 0xFF;
+            if (b >= 0x80) { // status byte?
+                if (b < 0xF0) { // channel message?
+                    mRunningStatus = (byte) b;
+                    mCount = 1;
+                    mNeeded = MidiConstants.getBytesPerMessage(b) - 1;
+                } else if (b < 0xF8) { // system common?
+                    mBuffer[0] = (byte) b;
+                    mRunningStatus = 0;
+                    mCount = 1;
+                    mNeeded = MidiConstants.getBytesPerMessage(b) - 1;
+                } else { // real-time?
+                    // Single byte message interleaved with other data.
+                    mReceiver.sendWithTimestamp(data, offset, 1, timestamp);
+                }
+            } else { // data byte
+                mBuffer[mCount++] = (byte) b;
+                if (--mNeeded == 0) {
+                    if (mRunningStatus != 0) {
+                        mBuffer[0] = (byte) mRunningStatus;
+                    }
+                    mReceiver.sendWithTimestamp(mBuffer, 0, mCount, timestamp);
+                    mNeeded = MidiConstants.getBytesPerMessage(mBuffer[0]) - 1;
+                    mCount = 1;
+                }
+            }
+            ++offset;
+        }
+    }
+
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 65a970a..05ed3ab 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -16,18 +16,14 @@
 
 package com.android.internal.os;
 
-import static android.net.NetworkStats.UID_ALL;
-import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
-
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
-import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.NetworkStats;
-import android.net.wifi.IWifiManager;
 import android.net.wifi.WifiActivityEnergyInfo;
 import android.net.wifi.WifiManager;
 import android.os.BadParcelableException;
@@ -42,8 +38,6 @@
 import android.os.ParcelFormatException;
 import android.os.Parcelable;
 import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.WorkSource;
@@ -65,13 +59,14 @@
 import android.util.Xml;
 import android.view.Display;
 
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.net.NetworkStatsFactory;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
 import com.android.internal.util.XmlUtils;
+import com.android.server.NetworkManagementSocketTagger;
+import libcore.util.EmptyArray;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -109,7 +104,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 120 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 123 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -132,6 +127,9 @@
     static final int MSG_REPORT_POWER_CHANGE = 2;
     static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
 
+    private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
+    private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
+
     public interface BatteryCallback {
         public void batteryNeedsCpuUpdate();
         public void batteryPowerChanged(boolean onBattery);
@@ -160,7 +158,12 @@
         }
     }
 
+    public interface ExternalStatsSync {
+        void scheduleSync();
+    }
+
     public final MyHandler mHandler;
+    private final ExternalStatsSync mExternalSync;
 
     private BatteryCallback mCallback;
 
@@ -310,6 +313,9 @@
     boolean mPowerSaveModeEnabled;
     StopwatchTimer mPowerSaveModeEnabledTimer;
 
+    boolean mDeviceIdling;
+    StopwatchTimer mDeviceIdlingTimer;
+
     boolean mDeviceIdleModeEnabled;
     StopwatchTimer mDeviceIdleModeEnabledTimer;
 
@@ -327,7 +333,7 @@
 
     int mPhoneSignalStrengthBin = -1;
     int mPhoneSignalStrengthBinRaw = -1;
-    final StopwatchTimer[] mPhoneSignalStrengthsTimer = 
+    final StopwatchTimer[] mPhoneSignalStrengthsTimer =
             new StopwatchTimer[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
 
     StopwatchTimer mPhoneSignalScanningTimer;
@@ -414,6 +420,7 @@
     int mMinDischargeStepLevel;
     final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
     final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
+    ArrayList<PackageChange> mDailyPackageChanges;
 
     int mLastChargeStepLevel;
     int mMaxChargeStepLevel;
@@ -441,18 +448,17 @@
     private int mLoadedNumConnectivityChange;
     private int mUnpluggedNumConnectivityChange;
 
+    private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
+
     /*
      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
      */
-    private final HashMap<String, SamplingTimer> mKernelWakelockStats =
-            new HashMap<String, SamplingTimer>();
+    private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
 
     public Map<String, ? extends Timer> getKernelWakelockStats() {
         return mKernelWakelockStats;
     }
 
-    private static int sKernelWakelockUpdateVersion = 0;
-
     String mLastWakeupReason = null;
     long mLastWakeupUptimeMs = 0;
     private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
@@ -461,56 +467,12 @@
         return mWakeupReasonStats;
     }
 
-    private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
-        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING|                // 0: name
-                              Process.PROC_QUOTES,
-        Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 1: count
-        Process.PROC_TAB_TERM,
-        Process.PROC_TAB_TERM,
-        Process.PROC_TAB_TERM,
-        Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 5: totalTime
-    };
-
-    private static final int[] WAKEUP_SOURCES_FORMAT = new int[] {
-        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE|
-                              Process.PROC_OUT_LONG,                  // 1: count
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
-        Process.PROC_TAB_TERM|Process.PROC_COMBINE
-                             |Process.PROC_OUT_LONG,                  // 6: totalTime
-    };
-
-    private final String[] mProcWakelocksName = new String[3];
-    private final long[] mProcWakelocksData = new long[3];
-
-    /*
-     * Used as a buffer for reading in data from /proc/wakelocks before it is processed and added
-     * to mKernelWakelockStats.
-     */
-    private final Map<String, KernelWakelockStats> mProcWakelockFileStats =
-            new HashMap<String, KernelWakelockStats>();
-
-    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
-    private NetworkStats mCurMobileSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
-    private NetworkStats mLastMobileSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
-    private NetworkStats mCurWifiSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
-    private NetworkStats mLastWifiSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
-    private NetworkStats mTmpNetworkStats;
-    private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
-
-    @GuardedBy("this")
-    private String[] mMobileIfaces = new String[0];
-    @GuardedBy("this")
-    private String[] mWifiIfaces = new String[0];
-
     public BatteryStatsImpl() {
         mFile = null;
         mCheckinFile = null;
         mDailyFile = null;
         mHandler = null;
+        mExternalSync = null;
         clearHistoryLocked();
     }
 
@@ -520,7 +482,7 @@
     }
 
     static class TimeBase {
-        private final ArrayList<TimeBaseObs> mObservers = new ArrayList<TimeBaseObs>();
+        private final ArrayList<TimeBaseObs> mObservers = new ArrayList<>();
 
         private long mUptime;
         private long mRealtime;
@@ -1775,147 +1737,6 @@
         return timer;
     }
 
-    private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
-
-        FileInputStream is;
-        byte[] buffer = new byte[32*1024];
-        int len;
-        boolean wakeup_sources;
-
-        try {
-            try {
-                is = new FileInputStream("/d/wakeup_sources");
-                wakeup_sources = true;
-            } catch (java.io.FileNotFoundException e) {
-                try {
-                    is = new FileInputStream("/proc/wakelocks");
-                    wakeup_sources = false;
-                } catch (java.io.FileNotFoundException e2) {
-                    return null;
-                }
-            }
-
-            len = is.read(buffer);
-            is.close();
-        } catch (java.io.IOException e) {
-            return null;
-        }
-
-        if (len > 0) {
-            if (len >= buffer.length) {
-                Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length);
-            }
-            int i;
-            for (i=0; i<len; i++) {
-                if (buffer[i] == '\0') {
-                    len = i;
-                    break;
-                }
-            }
-        }
-
-        return parseProcWakelocks(buffer, len, wakeup_sources);
-    }
-
-    private final Map<String, KernelWakelockStats> parseProcWakelocks(
-            byte[] wlBuffer, int len, boolean wakeup_sources) {
-        String name;
-        int count;
-        long totalTime;
-        int startIndex;
-        int endIndex;
-        int numUpdatedWlNames = 0;
-
-        // Advance past the first line.
-        int i;
-        for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++);
-        startIndex = endIndex = i + 1;
-
-        synchronized(this) {
-            Map<String, KernelWakelockStats> m = mProcWakelockFileStats;
-
-            sKernelWakelockUpdateVersion++;
-            while (endIndex < len) {
-                for (endIndex=startIndex;
-                        endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
-                        endIndex++);
-                endIndex++; // endIndex is an exclusive upper bound.
-                // Don't go over the end of the buffer, Process.parseProcLine might
-                // write to wlBuffer[endIndex]
-                if (endIndex >= (len - 1) ) {
-                    return m;
-                }
-
-                String[] nameStringArray = mProcWakelocksName;
-                long[] wlData = mProcWakelocksData;
-                // Stomp out any bad characters since this is from a circular buffer
-                // A corruption is seen sometimes that results in the vm crashing
-                // This should prevent crashes and the line will probably fail to parse
-                for (int j = startIndex; j < endIndex; j++) {
-                    if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?';
-                }
-                boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex,
-                        wakeup_sources ? WAKEUP_SOURCES_FORMAT :
-                                         PROC_WAKELOCKS_FORMAT,
-                        nameStringArray, wlData, null);
-
-                name = nameStringArray[0];
-                count = (int) wlData[1];
-
-                if (wakeup_sources) {
-                        // convert milliseconds to microseconds
-                        totalTime = wlData[2] * 1000;
-                } else {
-                        // convert nanoseconds to microseconds with rounding.
-                        totalTime = (wlData[2] + 500) / 1000;
-                }
-
-                if (parsed && name.length() > 0) {
-                    if (!m.containsKey(name)) {
-                        m.put(name, new KernelWakelockStats(count, totalTime,
-                                sKernelWakelockUpdateVersion));
-                        numUpdatedWlNames++;
-                    } else {
-                        KernelWakelockStats kwlStats = m.get(name);
-                        if (kwlStats.mVersion == sKernelWakelockUpdateVersion) {
-                            kwlStats.mCount += count;
-                            kwlStats.mTotalTime += totalTime;
-                        } else {
-                            kwlStats.mCount = count;
-                            kwlStats.mTotalTime = totalTime;
-                            kwlStats.mVersion = sKernelWakelockUpdateVersion;
-                            numUpdatedWlNames++;
-                        }
-                    }
-                }
-                startIndex = endIndex;
-            }
-
-            if (m.size() != numUpdatedWlNames) {
-                // Don't report old data.
-                Iterator<KernelWakelockStats> itr = m.values().iterator();
-                while (itr.hasNext()) {
-                    if (itr.next().mVersion != sKernelWakelockUpdateVersion) {
-                        itr.remove();
-                    }
-                }
-            }
-            return m;
-        }
-    }
-
-    private class KernelWakelockStats {
-        public int mCount;
-        public long mTotalTime;
-        public int mVersion;
-
-        KernelWakelockStats(int count, long totalTime, int version) {
-            mCount = count;
-            mTotalTime = totalTime;
-            mVersion = version;
-        }
-    }
-
     /*
      * Get the KernelWakelockTimer associated with name, and create a new one if one
      * doesn't already exist.
@@ -3387,7 +3208,7 @@
                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
             } else {
                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
-                updateNetworkActivityLocked(NET_UPDATE_MOBILE, realElapsedRealtimeMs);
+                updateMobileRadioStateLocked(realElapsedRealtimeMs);
                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
             }
         }
@@ -3417,9 +3238,26 @@
     }
 
     public void noteDeviceIdleModeLocked(boolean enabled, boolean fromActive, boolean fromMotion) {
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long uptime = SystemClock.uptimeMillis();
+        boolean nowIdling = enabled;
+        if (mDeviceIdling && !enabled && !fromActive && !fromMotion) {
+            // We don't go out of general idling mode until explicitly taken out of
+            // device idle through going active or significant motion.
+            nowIdling = true;
+        }
+        if (mDeviceIdling != nowIdling) {
+            mDeviceIdling = nowIdling;
+            int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
+            mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
+            mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
+            if (enabled) {
+                mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
+            } else {
+                mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
+            }
+        }
         if (mDeviceIdleModeEnabled != enabled) {
-            final long elapsedRealtime = SystemClock.elapsedRealtime();
-            final long uptime = SystemClock.uptimeMillis();
             mDeviceIdleModeEnabled = enabled;
             if (fromMotion) {
                 addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SIGNIFICANT_MOTION,
@@ -3449,7 +3287,11 @@
         final long uptime = SystemClock.uptimeMillis();
         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED,
                 pkgName, versionCode);
-        mNumConnectivityChange++;
+        PackageChange pc = new PackageChange();
+        pc.mPackageName = pkgName;
+        pc.mUpdate = true;
+        pc.mVersionCode = versionCode;
+        addPackageChange(pc);
     }
 
     public void notePackageUninstalledLocked(String pkgName) {
@@ -3457,7 +3299,17 @@
         final long uptime = SystemClock.uptimeMillis();
         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED,
                 pkgName, 0);
-        mNumConnectivityChange++;
+        PackageChange pc = new PackageChange();
+        pc.mPackageName = pkgName;
+        pc.mUpdate = true;
+        addPackageChange(pc);
+    }
+
+    private void addPackageChange(PackageChange pc) {
+        if (mDailyPackageChanges == null) {
+            mDailyPackageChanges = new ArrayList<>();
+        }
+        mDailyPackageChanges.add(pc);
     }
 
     public void notePhoneOnLocked() {
@@ -3694,6 +3546,7 @@
             addHistoryRecordLocked(elapsedRealtime, uptime);
             mWifiOn = true;
             mWifiOnTimer.startRunningLocked(elapsedRealtime);
+            scheduleSyncExternalStatsLocked();
         }
     }
 
@@ -3707,6 +3560,7 @@
             addHistoryRecordLocked(elapsedRealtime, uptime);
             mWifiOn = false;
             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
+            scheduleSyncExternalStatsLocked();
         }
     }
 
@@ -3869,6 +3723,7 @@
                 int uid = mapUid(ws.get(i));
                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
             }
+            scheduleSyncExternalStatsLocked();
         } else {
             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
         }
@@ -3907,6 +3762,7 @@
                 int uid = mapUid(ws.get(i));
                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
             }
+            scheduleSyncExternalStatsLocked();
         } else {
             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
         }
@@ -3921,6 +3777,7 @@
             }
             mWifiState = wifiState;
             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
+            scheduleSyncExternalStatsLocked();
         }
     }
 
@@ -3992,6 +3849,7 @@
             addHistoryRecordLocked(elapsedRealtime, uptime);
             mBluetoothOn = true;
             mBluetoothOnTimer.startRunningLocked(elapsedRealtime);
+            scheduleSyncExternalStatsLocked();
         }
     }
 
@@ -4005,6 +3863,7 @@
             addHistoryRecordLocked(elapsedRealtime, uptime);
             mBluetoothOn = false;
             mBluetoothOnTimer.stopRunningLocked(elapsedRealtime);
+            scheduleSyncExternalStatsLocked();
         }
     }
 
@@ -4031,6 +3890,7 @@
             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime, uptime);
+            scheduleSyncExternalStatsLocked();
         }
         mWifiFullLockNesting++;
         getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime);
@@ -4046,6 +3906,7 @@
             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime, uptime);
+            scheduleSyncExternalStatsLocked();
         }
         getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime);
     }
@@ -4103,6 +3964,7 @@
             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime, uptime);
+            scheduleSyncExternalStatsLocked();
         }
         mWifiMulticastNesting++;
         getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime);
@@ -4118,6 +3980,7 @@
             if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime, uptime);
+            scheduleSyncExternalStatsLocked();
         }
         getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime);
     }
@@ -4225,7 +4088,8 @@
         // During device boot, qtaguid isn't enabled until after the inital
         // loading of battery stats. Now that they're enabled, take our initial
         // snapshot for future delta calculation.
-        updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
+        updateMobileRadioStateLocked(SystemClock.elapsedRealtime());
+        updateWifiStateLocked(null);
     }
 
     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
@@ -4262,6 +4126,14 @@
         return mDeviceIdleModeEnabledTimer.getCountLocked(which);
     }
 
+    @Override public long getDeviceIdlingTime(long elapsedRealtimeUs, int which) {
+        return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+    }
+
+    @Override public int getDeviceIdlingCount(int which) {
+        return mDeviceIdlingTimer.getCountLocked(which);
+    }
+
     @Override public int getNumConnectivityChange(int which) {
         int val = mNumConnectivityChange;
         if (which == STATS_CURRENT) {
@@ -4564,17 +4436,17 @@
         }
 
         @Override
-        public Map<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
+        public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
             return mWakelockStats.getMap();
         }
 
         @Override
-        public Map<String, ? extends BatteryStats.Timer> getSyncStats() {
+        public ArrayMap<String, ? extends BatteryStats.Timer> getSyncStats() {
             return mSyncStats.getMap();
         }
 
         @Override
-        public Map<String, ? extends BatteryStats.Timer> getJobStats() {
+        public ArrayMap<String, ? extends BatteryStats.Timer> getJobStats() {
             return mJobStats.getMap();
         }
 
@@ -4584,12 +4456,12 @@
         }
 
         @Override
-        public Map<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
+        public ArrayMap<String, ? extends BatteryStats.Uid.Proc> getProcessStats() {
             return mProcessStats;
         }
 
         @Override
-        public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
+        public ArrayMap<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
             return mPackageStats;
         }
 
@@ -5907,7 +5779,7 @@
                     Slog.w(TAG, "File corrupt: too many excessive power entries " + N);
                     return false;
                 }
-                
+
                 mExcessivePower = new ArrayList<ExcessivePower>();
                 for (int i=0; i<N; i++) {
                     ExcessivePower ew = new ExcessivePower();
@@ -6110,40 +5982,20 @@
          */
         public final class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
             /**
-             * Number of times this package has done something that could wake up the
-             * device from sleep.
+             * Number of times wakeup alarms have occurred for this app.
              */
-            int mWakeups;
-
-            /**
-             * Number of things that could wake up the device loaded from a
-             * previous save.
-             */
-            int mLoadedWakeups;
-
-            /**
-             * Number of things that could wake up the device as of the
-             * last run.
-             */
-            int mLastWakeups;
-
-            /**
-             * Number of things that could wake up the device as of the
-             * last run.
-             */
-            int mUnpluggedWakeups;
+            ArrayMap<String, Counter> mWakeupAlarms = new ArrayMap<>();
 
             /**
              * The statics we have collected for this package's services.
              */
-            final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>();
+            final ArrayMap<String, Serv> mServiceStats = new ArrayMap<>();
 
             Pkg() {
                 mOnBatteryScreenOffTimeBase.add(this);
             }
 
             public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
-                mUnpluggedWakeups = mWakeups;
             }
 
             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
@@ -6154,10 +6006,12 @@
             }
 
             void readFromParcelLocked(Parcel in) {
-                mWakeups = in.readInt();
-                mLoadedWakeups = in.readInt();
-                mLastWakeups = 0;
-                mUnpluggedWakeups = in.readInt();
+                int numWA = in.readInt();
+                mWakeupAlarms.clear();
+                for (int i=0; i<numWA; i++) {
+                    String tag = in.readString();
+                    mWakeupAlarms.put(tag, new Counter(mOnBatteryTimeBase, in));
+                }
 
                 int numServs = in.readInt();
                 mServiceStats.clear();
@@ -6171,34 +6025,39 @@
             }
 
             void writeToParcelLocked(Parcel out) {
-                out.writeInt(mWakeups);
-                out.writeInt(mLoadedWakeups);
-                out.writeInt(mUnpluggedWakeups);
+                int numWA = mWakeupAlarms.size();
+                out.writeInt(numWA);
+                for (int i=0; i<numWA; i++) {
+                    out.writeString(mWakeupAlarms.keyAt(i));
+                    mWakeupAlarms.valueAt(i).writeToParcel(out);
+                }
 
-                out.writeInt(mServiceStats.size());
-                for (Map.Entry<String, Uid.Pkg.Serv> servEntry : mServiceStats.entrySet()) {
-                    out.writeString(servEntry.getKey());
-                    Uid.Pkg.Serv serv = servEntry.getValue();
-
+                final int NS = mServiceStats.size();
+                out.writeInt(NS);
+                for (int i=0; i<NS; i++) {
+                    out.writeString(mServiceStats.keyAt(i));
+                    Uid.Pkg.Serv serv = mServiceStats.valueAt(i);
                     serv.writeToParcelLocked(out);
                 }
             }
 
             @Override
-            public Map<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
-                return mServiceStats;
+            public ArrayMap<String, ? extends BatteryStats.Counter> getWakeupAlarmStats() {
+                return mWakeupAlarms;
+            }
+
+            public void noteWakeupAlarmLocked(String tag) {
+                Counter c = mWakeupAlarms.get(tag);
+                if (c == null) {
+                    c = new Counter(mOnBatteryTimeBase);
+                    mWakeupAlarms.put(tag, c);
+                }
+                c.stepAtomic();
             }
 
             @Override
-            public int getWakeups(int which) {
-                int val = mWakeups;
-                if (which == STATS_CURRENT) {
-                    val -= mLoadedWakeups;
-                } else if (which == STATS_SINCE_UNPLUGGED) {
-                    val -= mUnpluggedWakeups;
-                }
-
-                return val;
+            public ArrayMap<String, ? extends BatteryStats.Uid.Pkg.Serv> getServiceStats() {
+                return mServiceStats;
             }
 
             /**
@@ -6440,14 +6299,6 @@
                 }
             }
 
-            public BatteryStatsImpl getBatteryStats() {
-                return BatteryStatsImpl.this;
-            }
-
-            public void incWakeupsLocked() {
-                mWakeups++;
-            }
-
             final Serv newServiceStatsLocked() {
                 return new Serv();
             }
@@ -6706,7 +6557,7 @@
         }
     }
 
-    public BatteryStatsImpl(File systemDir, Handler handler) {
+    public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
         if (systemDir != null) {
             mFile = new JournaledFile(new File(systemDir, "batterystats.bin"),
                     new File(systemDir, "batterystats.bin.tmp"));
@@ -6715,6 +6566,7 @@
         }
         mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
         mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
+        mExternalSync = externalSync;
         mHandler = new MyHandler(handler.getLooper());
         mStartCount++;
         mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase);
@@ -6724,6 +6576,7 @@
         mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase);
         mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
         mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase);
+        mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase);
         mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null,
@@ -6786,6 +6639,7 @@
         mCheckinFile = null;
         mDailyFile = null;
         mHandler = null;
+        mExternalSync = null;
         clearHistoryLocked();
         readFromParcel(p);
     }
@@ -6849,6 +6703,11 @@
                     mDailyChargeStepTracker.mNumStepDurations,
                     mDailyChargeStepTracker.mStepDurations);
         }
+        if (mDailyPackageChanges != null) {
+            hasData = true;
+            item.mPackageChanges = mDailyPackageChanges;
+            mDailyPackageChanges = null;
+        }
         mDailyDischargeStepTracker.init();
         mDailyChargeStepTracker.init();
         updateDailyDeadlineLocked();
@@ -6899,6 +6758,21 @@
             out.attribute(null, "end", Long.toString(dit.mEndTime));
             writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
             writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
+            if (dit.mPackageChanges != null) {
+                for (int j=0; j<dit.mPackageChanges.size(); j++) {
+                    PackageChange pc = dit.mPackageChanges.get(j);
+                    if (pc.mUpdate) {
+                        out.startTag(null, "upd");
+                        out.attribute(null, "pkg", pc.mPackageName);
+                        out.attribute(null, "ver", Integer.toString(pc.mVersionCode));
+                        out.endTag(null, "upd");
+                    } else {
+                        out.startTag(null, "rem");
+                        out.attribute(null, "pkg", pc.mPackageName);
+                        out.endTag(null, "rem");
+                    }
+                }
+            }
             out.endTag(null, "item");
         }
         out.endTag(null, "daily-items");
@@ -7011,6 +6885,26 @@
                 readDailyItemTagDetailsLocked(parser, dit, false, "dis");
             } else if (tagName.equals("chg")) {
                 readDailyItemTagDetailsLocked(parser, dit, true, "chg");
+            } else if (tagName.equals("upd")) {
+                if (dit.mPackageChanges == null) {
+                    dit.mPackageChanges = new ArrayList<>();
+                }
+                PackageChange pc = new PackageChange();
+                pc.mUpdate = true;
+                pc.mPackageName = parser.getAttributeValue(null, "pkg");
+                String verStr = parser.getAttributeValue(null, "ver");
+                pc.mVersionCode = verStr != null ? Integer.parseInt(verStr) : 0;
+                dit.mPackageChanges.add(pc);
+                XmlUtils.skipCurrentTag(parser);
+            } else if (tagName.equals("rem")) {
+                if (dit.mPackageChanges == null) {
+                    dit.mPackageChanges = new ArrayList<>();
+                }
+                PackageChange pc = new PackageChange();
+                pc.mUpdate = false;
+                pc.mPackageName = parser.getAttributeValue(null, "pkg");
+                dit.mPackageChanges.add(pc);
+                XmlUtils.skipCurrentTag(parser);
             } else {
                 Slog.w(TAG, "Unknown element under <item>: "
                         + parser.getName());
@@ -7295,6 +7189,7 @@
         mInteractiveTimer.reset(false);
         mPowerSaveModeEnabledTimer.reset(false);
         mDeviceIdleModeEnabledTimer.reset(false);
+        mDeviceIdlingTimer.reset(false);
         mPhoneOnTimer.reset(false);
         mAudioOnTimer.reset(false);
         mVideoOnTimer.reset(false);
@@ -7416,21 +7311,233 @@
             mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
         }
     }
-    
+
     public void pullPendingStateUpdatesLocked() {
-        updateKernelWakelocksLocked();
-        updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
-        // TODO(adamlesinski): enable when bluedroid stops deadlocking. b/19248786
-        // updateBluetoothControllerActivityLocked();
-        // TODO(adamlesinski): disabled to avoid deadlock. Need to change how external
-        // data is pulled/accessed from BatteryStats. b/19729960
-        // updateWifiControllerActivityLocked();
         if (mOnBatteryInternal) {
             final boolean screenOn = mScreenState == Display.STATE_ON;
             updateDischargeScreenLevelsLocked(screenOn, screenOn);
         }
     }
 
+    private String[] mMobileIfaces = EmptyArray.STRING;
+    private String[] mWifiIfaces = EmptyArray.STRING;
+
+    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
+
+    private static final int NETWORK_STATS_LAST = 0;
+    private static final int NETWORK_STATS_NEXT = 1;
+    private static final int NETWORK_STATS_DELTA = 2;
+
+    private final NetworkStats[] mMobileNetworkStats = new NetworkStats[] {
+            new NetworkStats(SystemClock.elapsedRealtime(), 50),
+            new NetworkStats(SystemClock.elapsedRealtime(), 50),
+            new NetworkStats(SystemClock.elapsedRealtime(), 50)
+    };
+
+    private final NetworkStats[] mWifiNetworkStats = new NetworkStats[] {
+            new NetworkStats(SystemClock.elapsedRealtime(), 50),
+            new NetworkStats(SystemClock.elapsedRealtime(), 50),
+            new NetworkStats(SystemClock.elapsedRealtime(), 50)
+    };
+
+    /**
+     * Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer
+     * as a buffer of NetworkStats objects to cycle through when computing deltas.
+     */
+    private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces,
+                                                    NetworkStats[] networkStatsBuffer)
+            throws IOException {
+        if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED,
+                false)) {
+            return null;
+        }
+
+        final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL,
+                ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]);
+        networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats,
+                networkStatsBuffer[NETWORK_STATS_LAST], null, null,
+                networkStatsBuffer[NETWORK_STATS_DELTA]);
+        networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST];
+        networkStatsBuffer[NETWORK_STATS_LAST] = stats;
+        return networkStatsBuffer[NETWORK_STATS_DELTA];
+    }
+
+    /**
+     * Distribute WiFi energy info and network traffic to apps.
+     * @param info The energy information from the WiFi controller.
+     */
+    public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
+        final NetworkStats delta;
+        try {
+            delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats);
+        } catch (IOException e) {
+            Slog.wtf(TAG, "Failed to get wifi network stats", e);
+            return;
+        }
+
+        if (!mOnBatteryInternal) {
+            return;
+        }
+
+        if (delta != null) {
+            final int size = delta.size();
+            for (int i = 0; i < size; i++) {
+                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
+
+                if (DEBUG) {
+                    Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
+                            + " tx=" + entry.txBytes);
+                }
+
+                if (entry.rxBytes == 0 || entry.txBytes == 0) {
+                    continue;
+                }
+
+                final Uid u = getUidStatsLocked(mapUid(entry.uid));
+                u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
+                        entry.rxPackets);
+                u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
+                        entry.txPackets);
+
+                mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
+                        entry.rxBytes);
+                mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
+                        entry.txBytes);
+                mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
+                        entry.rxPackets);
+                mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
+                        entry.txPackets);
+            }
+        }
+
+        if (info != null) {
+            // Update WiFi controller stats.
+            mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
+                    info.getControllerRxTimeMillis());
+            mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
+                    info.getControllerTxTimeMillis());
+            mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
+                    info.getControllerIdleTimeMillis());
+            mWifiActivityCounters[CONTROLLER_ENERGY].addCountLocked(
+                    info.getControllerEnergyUsed());
+        }
+    }
+
+    /**
+     * Distribute Cell radio energy info and network traffic to apps.
+     */
+    public void updateMobileRadioStateLocked(long elapsedRealtimeMs) {
+        final NetworkStats delta;
+
+        try {
+            delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats);
+        } catch (IOException e) {
+            Slog.wtf(TAG, "Failed to get mobile network stats", e);
+            return;
+        }
+
+        if (delta == null || !mOnBatteryInternal) {
+            return;
+        }
+
+        long radioTime = mMobileRadioActivePerAppTimer.checkpointRunningLocked(elapsedRealtimeMs);
+        long totalPackets = delta.getTotalPackets();
+
+        final int size = delta.size();
+        for (int i = 0; i < size; i++) {
+            final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
+
+            if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
+
+            final Uid u = getUidStatsLocked(mapUid(entry.uid));
+            u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
+                    entry.rxPackets);
+            u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
+                    entry.txPackets);
+
+            if (radioTime > 0) {
+                // Distribute total radio active time in to this app.
+                long appPackets = entry.rxPackets + entry.txPackets;
+                long appRadioTime = (radioTime*appPackets)/totalPackets;
+                u.noteMobileRadioActiveTimeLocked(appRadioTime);
+                // Remove this app from the totals, so that we don't lose any time
+                // due to rounding.
+                radioTime -= appRadioTime;
+                totalPackets -= appPackets;
+            }
+
+            mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
+                    entry.rxBytes);
+            mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
+                    entry.txBytes);
+            mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
+                    entry.rxPackets);
+            mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
+                    entry.txPackets);
+        }
+
+        if (radioTime > 0) {
+            // Whoops, there is some radio time we can't blame on an app!
+            mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
+            mMobileRadioActiveUnknownCount.addCountLocked(1);
+        }
+    }
+
+    /**
+     * Distribute Bluetooth energy info and network traffic to apps.
+     * @param info The energy information from the bluetooth controller.
+     */
+    public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
+        if (info != null && mOnBatteryInternal) {
+            mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
+                    info.getControllerRxTimeMillis());
+            mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
+                    info.getControllerTxTimeMillis());
+            mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
+                    info.getControllerIdleTimeMillis());
+            mBluetoothActivityCounters[CONTROLLER_ENERGY].addCountLocked(
+                    info.getControllerEnergyUsed());
+        }
+    }
+
+    /**
+     * Read and distribute kernel wake lock use across apps.
+     */
+    public void updateKernelWakelocksLocked() {
+        final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats(
+                mTmpWakelockStats);
+        if (wakelockStats == null) {
+            // Not crashing might make board bringup easier.
+            Slog.w(TAG, "Couldn't get kernel wake lock stats");
+            return;
+        }
+
+        for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
+            String name = ent.getKey();
+            KernelWakelockStats.Entry kws = ent.getValue();
+
+            SamplingTimer kwlt = mKernelWakelockStats.get(name);
+            if (kwlt == null) {
+                kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase,
+                        true /* track reported val */);
+                mKernelWakelockStats.put(name, kwlt);
+            }
+            kwlt.updateCurrentReportedCount(kws.mCount);
+            kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
+            kwlt.setUpdateVersion(kws.mVersion);
+        }
+
+        if (wakelockStats.size() != mKernelWakelockStats.size()) {
+            // Set timers to stale if they didn't appear in /proc/wakelocks this time.
+            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
+                SamplingTimer st = ent.getValue();
+                if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) {
+                    st.setStale();
+                }
+            }
+        }
+    }
+
     void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
             final int oldStatus, final int level) {
         boolean doWrite = false;
@@ -7584,340 +7691,132 @@
         }
     }
 
+    private void scheduleSyncExternalStatsLocked() {
+        if (mExternalSync != null) {
+            mExternalSync.scheduleSync();
+        }
+    }
+
     // This should probably be exposed in the API, though it's not critical
-    private static final int BATTERY_PLUGGED_NONE = 0;
+    public static final int BATTERY_PLUGGED_NONE = 0;
 
-    public void setBatteryState(int status, int health, int plugType, int level,
+    public void setBatteryStateLocked(int status, int health, int plugType, int level,
             int temp, int volt) {
-        synchronized(this) {
-            final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
-            final long uptime = SystemClock.uptimeMillis();
-            final long elapsedRealtime = SystemClock.elapsedRealtime();
-            if (!mHaveBatteryLevel) {
-                mHaveBatteryLevel = true;
-                // We start out assuming that the device is plugged in (not
-                // on battery).  If our first report is now that we are indeed
-                // plugged in, then twiddle our state to correctly reflect that
-                // since we won't be going through the full setOnBattery().
-                if (onBattery == mOnBattery) {
-                    if (onBattery) {
-                        mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
-                    } else {
-                        mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
-                    }
-                }
-                mHistoryCur.batteryStatus = (byte)status;
-                mHistoryCur.batteryLevel = (byte)level;
-                mMaxChargeStepLevel = mMinDischargeStepLevel =
-                        mLastChargeStepLevel = mLastDischargeStepLevel = level;
-            } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
-                recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
-            }
-            int oldStatus = mHistoryCur.batteryStatus;
-            if (onBattery) {
-                mDischargeCurrentLevel = level;
-                if (!mRecordingHistory) {
-                    mRecordingHistory = true;
-                    startRecordingHistory(elapsedRealtime, uptime, true);
-                }
-            } else if (level < 96) {
-                if (!mRecordingHistory) {
-                    mRecordingHistory = true;
-                    startRecordingHistory(elapsedRealtime, uptime, true);
-                }
-            }
-            mCurrentBatteryLevel = level;
-            if (mDischargePlugLevel < 0) {
-                mDischargePlugLevel = level;
-            }
-            if (onBattery != mOnBattery) {
-                mHistoryCur.batteryLevel = (byte)level;
-                mHistoryCur.batteryStatus = (byte)status;
-                mHistoryCur.batteryHealth = (byte)health;
-                mHistoryCur.batteryPlugType = (byte)plugType;
-                mHistoryCur.batteryTemperature = (short)temp;
-                mHistoryCur.batteryVoltage = (char)volt;
-                setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
-            } else {
-                boolean changed = false;
-                if (mHistoryCur.batteryLevel != level) {
-                    mHistoryCur.batteryLevel = (byte)level;
-                    changed = true;
-                }
-                if (mHistoryCur.batteryStatus != status) {
-                    mHistoryCur.batteryStatus = (byte)status;
-                    changed = true;
-                }
-                if (mHistoryCur.batteryHealth != health) {
-                    mHistoryCur.batteryHealth = (byte)health;
-                    changed = true;
-                }
-                if (mHistoryCur.batteryPlugType != plugType) {
-                    mHistoryCur.batteryPlugType = (byte)plugType;
-                    changed = true;
-                }
-                if (temp >= (mHistoryCur.batteryTemperature+10)
-                        || temp <= (mHistoryCur.batteryTemperature-10)) {
-                    mHistoryCur.batteryTemperature = (short)temp;
-                    changed = true;
-                }
-                if (volt > (mHistoryCur.batteryVoltage+20)
-                        || volt < (mHistoryCur.batteryVoltage-20)) {
-                    mHistoryCur.batteryVoltage = (char)volt;
-                    changed = true;
-                }
-                if (changed) {
-                    addHistoryRecordLocked(elapsedRealtime, uptime);
-                }
-                long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
-                        | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
-                        | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
+        final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
+        final long uptime = SystemClock.uptimeMillis();
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        if (!mHaveBatteryLevel) {
+            mHaveBatteryLevel = true;
+            // We start out assuming that the device is plugged in (not
+            // on battery).  If our first report is now that we are indeed
+            // plugged in, then twiddle our state to correctly reflect that
+            // since we won't be going through the full setOnBattery().
+            if (onBattery == mOnBattery) {
                 if (onBattery) {
-                    if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
-                        mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
-                                modeBits, elapsedRealtime);
-                        mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
-                                modeBits, elapsedRealtime);
-                        mLastDischargeStepLevel = level;
-                        mMinDischargeStepLevel = level;
-                        mInitStepMode = mCurStepMode;
-                        mModStepMode = 0;
-                    }
+                    mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
                 } else {
-                    if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
-                        mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
-                                modeBits, elapsedRealtime);
-                        mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
-                                modeBits, elapsedRealtime);
-                        mLastChargeStepLevel = level;
-                        mMaxChargeStepLevel = level;
-                        mInitStepMode = mCurStepMode;
-                        mModStepMode = 0;
-                    }
+                    mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
                 }
             }
-            if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
-                // We don't record history while we are plugged in and fully charged.
-                // The next time we are unplugged, history will be cleared.
-                mRecordingHistory = DEBUG;
+            mHistoryCur.batteryStatus = (byte)status;
+            mHistoryCur.batteryLevel = (byte)level;
+            mMaxChargeStepLevel = mMinDischargeStepLevel =
+                    mLastChargeStepLevel = mLastDischargeStepLevel = level;
+        } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
+            recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
+        }
+        int oldStatus = mHistoryCur.batteryStatus;
+        if (onBattery) {
+            mDischargeCurrentLevel = level;
+            if (!mRecordingHistory) {
+                mRecordingHistory = true;
+                startRecordingHistory(elapsedRealtime, uptime, true);
+            }
+        } else if (level < 96) {
+            if (!mRecordingHistory) {
+                mRecordingHistory = true;
+                startRecordingHistory(elapsedRealtime, uptime, true);
             }
         }
-    }
-
-    public void updateKernelWakelocksLocked() {
-        Map<String, KernelWakelockStats> m = readKernelWakelockStats();
-
-        if (m == null) {
-            // Not crashing might make board bringup easier.
-            Slog.w(TAG, "Couldn't get kernel wake lock stats");
-            return;
+        mCurrentBatteryLevel = level;
+        if (mDischargePlugLevel < 0) {
+            mDischargePlugLevel = level;
         }
+        if (onBattery != mOnBattery) {
+            mHistoryCur.batteryLevel = (byte)level;
+            mHistoryCur.batteryStatus = (byte)status;
+            mHistoryCur.batteryHealth = (byte)health;
+            mHistoryCur.batteryPlugType = (byte)plugType;
+            mHistoryCur.batteryTemperature = (short)temp;
+            mHistoryCur.batteryVoltage = (char)volt;
+            setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
+        } else {
+            boolean changed = false;
+            if (mHistoryCur.batteryLevel != level) {
+                mHistoryCur.batteryLevel = (byte)level;
+                changed = true;
 
-        for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) {
-            String name = ent.getKey();
-            KernelWakelockStats kws = ent.getValue();
-
-            SamplingTimer kwlt = mKernelWakelockStats.get(name);
-            if (kwlt == null) {
-                kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase,
-                        true /* track reported val */);
-                mKernelWakelockStats.put(name, kwlt);
+                // TODO(adamlesinski): Schedule the creation of a HistoryStepDetails record
+                // which will pull external stats.
+                scheduleSyncExternalStatsLocked();
             }
-            kwlt.updateCurrentReportedCount(kws.mCount);
-            kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
-            kwlt.setUpdateVersion(sKernelWakelockUpdateVersion);
-        }
-
-        if (m.size() != mKernelWakelockStats.size()) {
-            // Set timers to stale if they didn't appear in /proc/wakelocks this time.
-            for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
-                SamplingTimer st = ent.getValue();
-                if (st.getUpdateVersion() != sKernelWakelockUpdateVersion) {
-                    st.setStale();
+            if (mHistoryCur.batteryStatus != status) {
+                mHistoryCur.batteryStatus = (byte)status;
+                changed = true;
+            }
+            if (mHistoryCur.batteryHealth != health) {
+                mHistoryCur.batteryHealth = (byte)health;
+                changed = true;
+            }
+            if (mHistoryCur.batteryPlugType != plugType) {
+                mHistoryCur.batteryPlugType = (byte)plugType;
+                changed = true;
+            }
+            if (temp >= (mHistoryCur.batteryTemperature+10)
+                    || temp <= (mHistoryCur.batteryTemperature-10)) {
+                mHistoryCur.batteryTemperature = (short)temp;
+                changed = true;
+            }
+            if (volt > (mHistoryCur.batteryVoltage+20)
+                    || volt < (mHistoryCur.batteryVoltage-20)) {
+                mHistoryCur.batteryVoltage = (char)volt;
+                changed = true;
+            }
+            if (changed) {
+                addHistoryRecordLocked(elapsedRealtime, uptime);
+            }
+            long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
+                    | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
+                    | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
+            if (onBattery) {
+                if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
+                    mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
+                            modeBits, elapsedRealtime);
+                    mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
+                            modeBits, elapsedRealtime);
+                    mLastDischargeStepLevel = level;
+                    mMinDischargeStepLevel = level;
+                    mInitStepMode = mCurStepMode;
+                    mModStepMode = 0;
+                }
+            } else {
+                if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
+                    mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
+                            modeBits, elapsedRealtime);
+                    mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
+                            modeBits, elapsedRealtime);
+                    mLastChargeStepLevel = level;
+                    mMaxChargeStepLevel = level;
+                    mInitStepMode = mCurStepMode;
+                    mModStepMode = 0;
                 }
             }
         }
-    }
-
-    static final int NET_UPDATE_MOBILE = 1<<0;
-    static final int NET_UPDATE_WIFI = 1<<1;
-    static final int NET_UPDATE_ALL = 0xffff;
-
-    private void updateNetworkActivityLocked(int which, long elapsedRealtimeMs) {
-        if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return;
-
-        if ((which&NET_UPDATE_MOBILE) != 0 && mMobileIfaces.length > 0) {
-            final NetworkStats snapshot;
-            final NetworkStats last = mCurMobileSnapshot;
-            try {
-                snapshot = mNetworkStatsFactory.readNetworkStatsDetail(UID_ALL,
-                        mMobileIfaces, NetworkStats.TAG_NONE, mLastMobileSnapshot);
-            } catch (IOException e) {
-                Log.wtf(TAG, "Failed to read mobile network stats", e);
-                return;
-            }
-
-            mCurMobileSnapshot = snapshot;
-            mLastMobileSnapshot = last;
-
-            if (mOnBatteryInternal) {
-                final NetworkStats delta = NetworkStats.subtract(snapshot, last,
-                        null, null, mTmpNetworkStats);
-                mTmpNetworkStats = delta;
-
-                long radioTime = mMobileRadioActivePerAppTimer.checkpointRunningLocked(
-                        elapsedRealtimeMs);
-                long totalPackets = delta.getTotalPackets();
-
-                final int size = delta.size();
-                for (int i = 0; i < size; i++) {
-                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
-
-                    if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
-
-                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
-                    u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
-                            entry.rxPackets);
-                    u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
-                            entry.txPackets);
-
-                    if (radioTime > 0) {
-                        // Distribute total radio active time in to this app.
-                        long appPackets = entry.rxPackets + entry.txPackets;
-                        long appRadioTime = (radioTime*appPackets)/totalPackets;
-                        u.noteMobileRadioActiveTimeLocked(appRadioTime);
-                        // Remove this app from the totals, so that we don't lose any time
-                        // due to rounding.
-                        radioTime -= appRadioTime;
-                        totalPackets -= appPackets;
-                    }
-
-                    mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                            entry.rxBytes);
-                    mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                            entry.txBytes);
-                    mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                            entry.rxPackets);
-                    mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                            entry.txPackets);
-                }
-
-                if (radioTime > 0) {
-                    // Whoops, there is some radio time we can't blame on an app!
-                    mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
-                    mMobileRadioActiveUnknownCount.addCountLocked(1);
-                }
-            }
+        if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
+            // We don't record history while we are plugged in and fully charged.
+            // The next time we are unplugged, history will be cleared.
+            mRecordingHistory = DEBUG;
         }
-
-        if ((which&NET_UPDATE_WIFI) != 0 && mWifiIfaces.length > 0) {
-            final NetworkStats snapshot;
-            final NetworkStats last = mCurWifiSnapshot;
-            try {
-                snapshot = mNetworkStatsFactory.readNetworkStatsDetail(UID_ALL,
-                        mWifiIfaces, NetworkStats.TAG_NONE, mLastWifiSnapshot);
-            } catch (IOException e) {
-                Log.wtf(TAG, "Failed to read wifi network stats", e);
-                return;
-            }
-
-            mCurWifiSnapshot = snapshot;
-            mLastWifiSnapshot = last;
-
-            if (mOnBatteryInternal) {
-                final NetworkStats delta = NetworkStats.subtract(snapshot, last,
-                        null, null, mTmpNetworkStats);
-                mTmpNetworkStats = delta;
-
-                final int size = delta.size();
-                for (int i = 0; i < size; i++) {
-                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
-
-                    if (DEBUG) {
-                        final NetworkStats.Entry cur = snapshot.getValues(i, null);
-                        Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
-                                + " tx=" + entry.txBytes + ", cur rx=" + cur.rxBytes
-                                + " tx=" + cur.txBytes);
-                    }
-
-                    if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
-
-                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
-                    u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
-                            entry.rxPackets);
-                    u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
-                            entry.txPackets);
-
-                    mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
-                            entry.rxBytes);
-                    mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
-                            entry.txBytes);
-                    mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
-                            entry.rxPackets);
-                    mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
-                            entry.txPackets);
-                }
-            }
-        }
-    }
-
-    private void updateBluetoothControllerActivityLocked() {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        if (adapter == null) {
-            return;
-        }
-
-        // We read the data even if we are not on battery. Each read clears
-        // the previous data, so we must always read to make sure the
-        // data is for the current interval.
-        BluetoothActivityEnergyInfo info = adapter.getControllerActivityEnergyInfo(
-                BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED);
-        if (info == null || !info.isValid() || !mOnBatteryInternal) {
-            // Bad info or we are not on battery.
-            return;
-        }
-
-        mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
-                info.getControllerRxTimeMillis());
-        mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
-                info.getControllerTxTimeMillis());
-        mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
-                info.getControllerIdleTimeMillis());
-        mBluetoothActivityCounters[CONTROLLER_ENERGY].addCountLocked(
-                info.getControllerEnergyUsed());
-    }
-
-    private void updateWifiControllerActivityLocked() {
-        IWifiManager wifiManager = IWifiManager.Stub.asInterface(
-                ServiceManager.getService(Context.WIFI_SERVICE));
-        if (wifiManager == null) {
-            return;
-        }
-
-        WifiActivityEnergyInfo info;
-        try {
-            // We read the data even if we are not on battery. Each read clears
-            // the previous data, so we must always read to make sure the
-            // data is for the current interval.
-            info = wifiManager.reportActivityInfo();
-        } catch (RemoteException e) {
-            // Nothing to report, WiFi is dead.
-            return;
-        }
-
-        if (info == null || !info.isValid() || !mOnBatteryInternal) {
-            // Bad info or we are not on battery.
-            return;
-        }
-
-        mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
-                info.getControllerRxTimeMillis());
-        mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
-                info.getControllerTxTimeMillis());
-        mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
-                info.getControllerIdleTimeMillis());
-        mWifiActivityCounters[CONTROLLER_ENERGY].addCountLocked(
-                info.getControllerEnergyUsed());
     }
 
     public long getAwakeTimeBattery() {
@@ -8083,6 +7982,11 @@
         return mDailyChargeStepTracker;
     }
 
+    @Override
+    public ArrayList<PackageChange> getDailyPackageChanges() {
+        return mDailyPackageChanges;
+    }
+
     long getBatteryUptimeLocked() {
         return mOnBatteryTimeBase.getUptime(SystemClock.uptimeMillis() * 1000);
     }
@@ -8583,6 +8487,20 @@
         mChargeStepTracker.readFromParcel(in);
         mDailyDischargeStepTracker.readFromParcel(in);
         mDailyChargeStepTracker.readFromParcel(in);
+        int NPKG = in.readInt();
+        if (NPKG > 0) {
+            mDailyPackageChanges = new ArrayList<>(NPKG);
+            while (NPKG > 0) {
+                NPKG--;
+                PackageChange pc = new PackageChange();
+                pc.mPackageName = in.readString();
+                pc.mUpdate = in.readInt() != 0;
+                pc.mVersionCode = in.readInt();
+                mDailyPackageChanges.add(pc);
+            }
+        } else {
+            mDailyPackageChanges = null;
+        }
         mDailyStartTime = in.readLong();
         mNextMinDailyDeadline = in.readLong();
         mNextMaxDailyDeadline = in.readLong();
@@ -8599,6 +8517,7 @@
         mPhoneOn = false;
         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
         mDeviceIdleModeEnabledTimer.readSummaryFromParcelLocked(in);
+        mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
         mPhoneOnTimer.readSummaryFromParcelLocked(in);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
@@ -8833,7 +8752,18 @@
             for (int ip = 0; ip < NP; ip++) {
                 String pkgName = in.readString();
                 Uid.Pkg p = u.getPackageStatsLocked(pkgName);
-                p.mWakeups = p.mLoadedWakeups = in.readInt();
+                final int NWA = in.readInt();
+                if (NWA > 1000) {
+                    Slog.w(TAG, "File corrupt: too many wakeup alarms " + NWA);
+                    return;
+                }
+                p.mWakeupAlarms.clear();
+                for (int iwa=0; iwa<NWA; iwa++) {
+                    String tag = in.readString();
+                    Counter c = new Counter(mOnBatteryTimeBase);
+                    c.readSummaryFromParcelLocked(in);
+                    p.mWakeupAlarms.put(tag, c);
+                }
                 NS = in.readInt();
                 if (NS > 1000) {
                     Slog.w(TAG, "File corrupt: too many services " + NS);
@@ -8890,6 +8820,18 @@
         mChargeStepTracker.writeToParcel(out);
         mDailyDischargeStepTracker.writeToParcel(out);
         mDailyChargeStepTracker.writeToParcel(out);
+        if (mDailyPackageChanges != null) {
+            final int NPKG = mDailyPackageChanges.size();
+            out.writeInt(NPKG);
+            for (int i=0; i<NPKG; i++) {
+                PackageChange pc = mDailyPackageChanges.get(i);
+                out.writeString(pc.mPackageName);
+                out.writeInt(pc.mUpdate ? 1 : 0);
+                out.writeInt(pc.mVersionCode);
+            }
+        } else {
+            out.writeInt(0);
+        }
         out.writeLong(mDailyStartTime);
         out.writeLong(mNextMinDailyDeadline);
         out.writeLong(mNextMaxDailyDeadline);
@@ -8901,6 +8843,7 @@
         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mDeviceIdleModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+        mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -9145,20 +9088,22 @@
                     : u.mPackageStats.entrySet()) {
                     out.writeString(ent.getKey());
                     Uid.Pkg ps = ent.getValue();
-                    out.writeInt(ps.mWakeups);
+                    final int NWA = ps.mWakeupAlarms.size();
+                    out.writeInt(NWA);
+                    for (int iwa=0; iwa<NWA; iwa++) {
+                        out.writeString(ps.mWakeupAlarms.keyAt(iwa));
+                        ps.mWakeupAlarms.valueAt(iwa).writeSummaryFromParcelLocked(out);
+                    }
                     NS = ps.mServiceStats.size();
                     out.writeInt(NS);
-                    if (NS > 0) {
-                        for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent
-                                : ps.mServiceStats.entrySet()) {
-                            out.writeString(sent.getKey());
-                            BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue();
-                            long time = ss.getStartTimeToNowLocked(
-                                    mOnBatteryTimeBase.getUptime(NOW_SYS));
-                            out.writeLong(time);
-                            out.writeInt(ss.mStarts);
-                            out.writeInt(ss.mLaunches);
-                        }
+                    for (int is=0; is<NS; is++) {
+                        out.writeString(ps.mServiceStats.keyAt(is));
+                        BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is);
+                        long time = ss.getStartTimeToNowLocked(
+                                mOnBatteryTimeBase.getUptime(NOW_SYS));
+                        out.writeLong(time);
+                        out.writeInt(ss.mStarts);
+                        out.writeInt(ss.mLaunches);
                     }
                 }
             }
@@ -9201,6 +9146,7 @@
         mPhoneOn = false;
         mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
         mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase, in);
+        mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase, in);
         mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
@@ -9367,6 +9313,7 @@
         mInteractiveTimer.writeToParcel(out, uSecRealtime);
         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
         mDeviceIdleModeEnabledTimer.writeToParcel(out, uSecRealtime);
+        mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
             mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
@@ -9507,6 +9454,8 @@
             mPowerSaveModeEnabledTimer.logState(pr, "  ");
             pr.println("*** Device idle mode timer:");
             mDeviceIdleModeEnabledTimer.logState(pr, "  ");
+            pr.println("*** Device idling timer:");
+            mDeviceIdlingTimer.logState(pr, "  ");
             pr.println("*** Phone timer:");
             mPhoneOnTimer.logState(pr, "  ");
             for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
index 433a54b..a4cdf19 100644
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ b/core/java/com/android/internal/os/InstallerConnection.java
@@ -91,11 +91,11 @@
     }
 
     public int dexopt(String apkPath, int uid, boolean isPublic, String instructionSet) {
-        return dexopt(apkPath, uid, isPublic, "*", instructionSet, false, false);
+        return dexopt(apkPath, uid, isPublic, "*", instructionSet, false, false, null);
     }
 
     public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
-            String instructionSet, boolean vmSafeMode, boolean debuggable) {
+            String instructionSet, boolean vmSafeMode, boolean debuggable, String outputPath) {
         StringBuilder builder = new StringBuilder("dexopt");
         builder.append(' ');
         builder.append(apkPath);
@@ -108,6 +108,8 @@
         builder.append(instructionSet);
         builder.append(vmSafeMode ? " 1" : " 0");
         builder.append(debuggable ? " 1" : " 0");
+        builder.append(' ');
+        builder.append(outputPath != null ? outputPath : "!");
         return execute(builder.toString());
     }
 
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
new file mode 100644
index 0000000..768d586
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -0,0 +1,192 @@
+/*
+ * 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.internal.os;
+
+import android.os.Process;
+import android.util.Slog;
+
+import java.io.FileInputStream;
+import java.util.Iterator;
+
+/**
+ * Reads and parses wakelock stats from the kernel (/proc/wakelocks).
+ */
+public class KernelWakelockReader {
+    private static final String TAG = "KernelWakelockReader";
+    private static int sKernelWakelockUpdateVersion = 0;
+    private static final String sWakelockFile = "/proc/wakelocks";
+    private static final String sWakeupSourceFile = "/d/wakeup_sources";
+
+    private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
+        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING|                // 0: name
+                              Process.PROC_QUOTES,
+        Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 1: count
+        Process.PROC_TAB_TERM,
+        Process.PROC_TAB_TERM,
+        Process.PROC_TAB_TERM,
+        Process.PROC_TAB_TERM|Process.PROC_OUT_LONG,                  // 5: totalTime
+    };
+
+    private static final int[] WAKEUP_SOURCES_FORMAT = new int[] {
+        Process.PROC_TAB_TERM|Process.PROC_OUT_STRING,                // 0: name
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE|
+                              Process.PROC_OUT_LONG,                  // 1: count
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE,
+        Process.PROC_TAB_TERM|Process.PROC_COMBINE
+                             |Process.PROC_OUT_LONG,                  // 6: totalTime
+    };
+
+    private final String[] mProcWakelocksName = new String[3];
+    private final long[] mProcWakelocksData = new long[3];
+
+    /**
+     * Reads kernel wakelock stats and updates the staleStats with the new information.
+     * @param staleStats Existing object to update.
+     * @return the updated data.
+     */
+    public final KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) {
+        byte[] buffer = new byte[32*1024];
+        int len;
+        boolean wakeup_sources;
+
+        try {
+            FileInputStream is;
+            try {
+                is = new FileInputStream(sWakeupSourceFile);
+                wakeup_sources = true;
+            } catch (java.io.FileNotFoundException e) {
+                try {
+                    is = new FileInputStream(sWakelockFile);
+                    wakeup_sources = false;
+                } catch (java.io.FileNotFoundException e2) {
+                    return null;
+                }
+            }
+
+            len = is.read(buffer);
+            is.close();
+        } catch (java.io.IOException e) {
+            return null;
+        }
+
+        if (len > 0) {
+            if (len >= buffer.length) {
+                Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length);
+            }
+            int i;
+            for (i=0; i<len; i++) {
+                if (buffer[i] == '\0') {
+                    len = i;
+                    break;
+                }
+            }
+        }
+        return parseProcWakelocks(buffer, len, wakeup_sources, staleStats);
+    }
+
+    /**
+     * Reads the wakelocks and updates the staleStats with the new information.
+     */
+    private KernelWakelockStats parseProcWakelocks(byte[] wlBuffer, int len, boolean wakeup_sources,
+                                                   final KernelWakelockStats staleStats) {
+        String name;
+        int count;
+        long totalTime;
+        int startIndex;
+        int endIndex;
+        int numUpdatedWlNames = 0;
+
+        // Advance past the first line.
+        int i;
+        for (i = 0; i < len && wlBuffer[i] != '\n' && wlBuffer[i] != '\0'; i++);
+        startIndex = endIndex = i + 1;
+
+        synchronized(this) {
+            sKernelWakelockUpdateVersion++;
+            while (endIndex < len) {
+                for (endIndex=startIndex;
+                        endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
+                        endIndex++);
+                endIndex++; // endIndex is an exclusive upper bound.
+                // Don't go over the end of the buffer, Process.parseProcLine might
+                // write to wlBuffer[endIndex]
+                if (endIndex >= (len - 1) ) {
+                    return staleStats;
+                }
+
+                String[] nameStringArray = mProcWakelocksName;
+                long[] wlData = mProcWakelocksData;
+                // Stomp out any bad characters since this is from a circular buffer
+                // A corruption is seen sometimes that results in the vm crashing
+                // This should prevent crashes and the line will probably fail to parse
+                for (int j = startIndex; j < endIndex; j++) {
+                    if ((wlBuffer[j] & 0x80) != 0) wlBuffer[j] = (byte) '?';
+                }
+                boolean parsed = Process.parseProcLine(wlBuffer, startIndex, endIndex,
+                        wakeup_sources ? WAKEUP_SOURCES_FORMAT :
+                                         PROC_WAKELOCKS_FORMAT,
+                        nameStringArray, wlData, null);
+
+                name = nameStringArray[0];
+                count = (int) wlData[1];
+
+                if (wakeup_sources) {
+                        // convert milliseconds to microseconds
+                        totalTime = wlData[2] * 1000;
+                } else {
+                        // convert nanoseconds to microseconds with rounding.
+                        totalTime = (wlData[2] + 500) / 1000;
+                }
+
+                if (parsed && name.length() > 0) {
+                    if (!staleStats.containsKey(name)) {
+                        staleStats.put(name, new KernelWakelockStats.Entry(count, totalTime,
+                                sKernelWakelockUpdateVersion));
+                        numUpdatedWlNames++;
+                    } else {
+                        KernelWakelockStats.Entry kwlStats = staleStats.get(name);
+                        if (kwlStats.mVersion == sKernelWakelockUpdateVersion) {
+                            kwlStats.mCount += count;
+                            kwlStats.mTotalTime += totalTime;
+                        } else {
+                            kwlStats.mCount = count;
+                            kwlStats.mTotalTime = totalTime;
+                            kwlStats.mVersion = sKernelWakelockUpdateVersion;
+                            numUpdatedWlNames++;
+                        }
+                    }
+                }
+                startIndex = endIndex;
+            }
+
+            if (staleStats.size() != numUpdatedWlNames) {
+                // Don't report old data.
+                Iterator<KernelWakelockStats.Entry> itr = staleStats.values().iterator();
+                while (itr.hasNext()) {
+                    if (itr.next().mVersion != sKernelWakelockUpdateVersion) {
+                        itr.remove();
+                    }
+                }
+            }
+
+            staleStats.kernelWakelockVersion = sKernelWakelockUpdateVersion;
+            return staleStats;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/KernelWakelockStats.java b/core/java/com/android/internal/os/KernelWakelockStats.java
new file mode 100644
index 0000000..144ea00
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelWakelockStats.java
@@ -0,0 +1,37 @@
+/*
+ * 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.internal.os;
+
+import java.util.HashMap;
+
+/**
+ * Kernel wakelock stats object.
+ */
+public class KernelWakelockStats extends HashMap<String, KernelWakelockStats.Entry> {
+    public static class Entry {
+        public int mCount;
+        public long mTotalTime;
+        public int mVersion;
+
+        Entry(int count, long totalTime, int version) {
+            mCount = count;
+            mTotalTime = totalTime;
+            mVersion = version;
+        }
+    }
+
+    int kernelWakelockVersion;
+}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 8674a21..75b6446 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -41,15 +41,10 @@
     /** enable the JIT compiler */
     public static final int DEBUG_ENABLE_JIT         = 1 << 5;
 
-
     /** No external storage should be mounted. */
     public static final int MOUNT_EXTERNAL_NONE = 0;
-    /** Single-user external storage should be mounted. */
-    public static final int MOUNT_EXTERNAL_SINGLEUSER = 1;
-    /** Multi-user external storage should be mounted. */
-    public static final int MOUNT_EXTERNAL_MULTIUSER = 2;
-    /** All multi-user external storage should be mounted. */
-    public static final int MOUNT_EXTERNAL_MULTIUSER_ALL = 3;
+    /** Default user-specific external storage should be mounted. */
+    public static final int MOUNT_EXTERNAL_DEFAULT = 1;
 
     private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
 
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 4d405b2..9106ccd 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -514,10 +514,8 @@
                                 "Duplicate arg specified");
                     }
                     niceName = arg.substring(arg.indexOf('=') + 1);
-                } else if (arg.equals("--mount-external-multiuser")) {
-                    mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
-                } else if (arg.equals("--mount-external-multiuser-all")) {
-                    mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
+                } else if (arg.equals("--mount-external-default")) {
+                    mountExternal = Zygote.MOUNT_EXTERNAL_DEFAULT;
                 } else if (arg.equals("--query-abi-list")) {
                     abiListQuery = true;
                 } else if (arg.startsWith("--instruction-set=")) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 49d565d..70f7b72 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -32,6 +32,7 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructPollfd;
+import android.text.Hyphenator;
 import android.util.EventLog;
 import android.util.Log;
 import android.webkit.WebViewFactory;
@@ -182,6 +183,7 @@
         preloadResources();
         preloadOpenGL();
         preloadSharedLibraries();
+        preloadTextResources();
         // Ask the WebViewFactory to do any initialization that must run in the zygote process,
         // for memory sharing purposes.
         WebViewFactory.prepareWebViewInZygote();
@@ -201,6 +203,10 @@
         }
     }
 
+    private static void preloadTextResources() {
+        Hyphenator.init();
+    }
+
     /**
      * Performs Zygote process initialization. Loads and initializes
      * commonly used classes.
diff --git a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
index a529923..1d0511f 100644
--- a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
+++ b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
@@ -4,18 +4,12 @@
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
-import android.os.Environment;
 import android.os.IBinder;
 import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.storage.IMountService;
-import android.os.storage.StorageEventListener;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
-import android.util.Log;
+import android.util.Slog;
 import android.view.WindowManager;
 import android.widget.Toast;
 
@@ -24,8 +18,7 @@
 /**
  * Takes care of unmounting and formatting external storage.
  */
-public class ExternalStorageFormatter extends Service
-        implements DialogInterface.OnCancelListener {
+public class ExternalStorageFormatter extends Service {
     static final String TAG = "ExternalStorageFormatter";
 
     public static final String FORMAT_ONLY = "com.android.internal.os.storage.FORMAT_ONLY";
@@ -33,16 +26,10 @@
 
     public static final String EXTRA_ALWAYS_RESET = "always_reset";
 
-    // If non-null, the volume to format. Otherwise, will use the default external storage directory
-    private StorageVolume mStorageVolume;
-
     public static final ComponentName COMPONENT_NAME
             = new ComponentName("android", ExternalStorageFormatter.class.getName());
 
-    // Access using getMountService()
-    private IMountService mMountService = null;
-
-    private StorageManager mStorageManager = null;
+    private StorageManager mStorageManager;
 
     private PowerManager.WakeLock mWakeLock;
 
@@ -52,24 +39,11 @@
     private boolean mAlwaysReset = false;
     private String mReason = null;
 
-    StorageEventListener mStorageListener = new StorageEventListener() {
-        @Override
-        public void onStorageStateChanged(String path, String oldState, String newState) {
-            Log.i(TAG, "Received storage state changed notification that " +
-                    path + " changed state from " + oldState +
-                    " to " + newState);
-            updateProgressState();
-        }
-    };
-
     @Override
     public void onCreate() {
         super.onCreate();
 
-        if (mStorageManager == null) {
-            mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
-            mStorageManager.registerListener(mStorageListener);
-        }
+        mStorageManager = getSystemService(StorageManager.class);
 
         mWakeLock = ((PowerManager)getSystemService(Context.POWER_SERVICE))
                 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ExternalStorageFormatter");
@@ -86,28 +60,74 @@
         }
 
         mReason = intent.getStringExtra(Intent.EXTRA_REASON);
-        mStorageVolume = intent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
-
-        if (mProgressDialog == null) {
-            mProgressDialog = new ProgressDialog(this);
-            mProgressDialog.setIndeterminate(true);
-            mProgressDialog.setCancelable(true);
-            mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-            if (!mAlwaysReset) {
-                mProgressDialog.setOnCancelListener(this);
-            }
-            updateProgressState();
-            mProgressDialog.show();
+        StorageVolume userVol = intent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
+        if (userVol == null) {
+            Slog.w(TAG, "Missing explicit storage volume; assuming default");
+            userVol = mStorageManager.getPrimaryVolume();
         }
 
+        final String volumeId = userVol.getId();
+
+        mProgressDialog = new ProgressDialog(this);
+        mProgressDialog.setIndeterminate(true);
+        mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        mProgressDialog.setMessage(getText(R.string.progress_unmounting));
+        mProgressDialog.show();
+
+        new FormatTask(volumeId).start();
+
         return Service.START_REDELIVER_INTENT;
     }
 
+    private class FormatTask extends Thread {
+        private final String mVolumeId;
+
+        public FormatTask(String volumeId) {
+            mVolumeId = volumeId;
+        }
+
+        @Override
+        public void run() {
+            boolean success = false;
+            try {
+                mStorageManager.format(mVolumeId);
+                success = true;
+            } catch (Exception e) {
+                Slog.w(TAG, "Failed to format", e);
+                Toast.makeText(ExternalStorageFormatter.this,
+                        R.string.format_error, Toast.LENGTH_LONG).show();
+            }
+            if (success) {
+                if (mFactoryReset) {
+                    Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
+                    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                    intent.putExtra(Intent.EXTRA_REASON, mReason);
+                    sendBroadcast(intent);
+                    // Intent handling is asynchronous -- assume it will happen soon.
+                    stopSelf();
+                    return;
+                }
+            }
+            // If we didn't succeed, or aren't doing a full factory
+            // reset, then it is time to remount the storage.
+            if (!success && mAlwaysReset) {
+                Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
+                intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                intent.putExtra(Intent.EXTRA_REASON, mReason);
+                sendBroadcast(intent);
+            } else {
+                try {
+                    mStorageManager.mount(mVolumeId);
+                } catch (Exception e) {
+                    Slog.w(TAG, "Failed to mount", e);
+                }
+            }
+            stopSelf();
+        }
+    }
+
     @Override
     public void onDestroy() {
-        if (mStorageManager != null) {
-            mStorageManager.unregisterListener(mStorageListener);
-        }
         if (mProgressDialog != null) {
             mProgressDialog.dismiss();
         }
@@ -119,137 +139,4 @@
     public IBinder onBind(Intent intent) {
         return null;
     }
-
-    @Override
-    public void onCancel(DialogInterface dialog) {
-        IMountService mountService = getMountService();
-        String extStoragePath = mStorageVolume == null ?
-                Environment.getLegacyExternalStorageDirectory().toString() :
-                mStorageVolume.getPath();
-        try {
-            mountService.mountVolume(extStoragePath);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed talking with mount service", e);
-        }
-        stopSelf();
-    }
-
-    void fail(int msg) {
-        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
-        if (mAlwaysReset) {
-            Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
-            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-            intent.putExtra(Intent.EXTRA_REASON, mReason);
-            sendBroadcast(intent);
-        }
-        stopSelf();
-    }
-
-    void updateProgressState() {
-        String status = mStorageVolume == null ?
-                Environment.getExternalStorageState() :
-                mStorageManager.getVolumeState(mStorageVolume.getPath());
-        if (Environment.MEDIA_MOUNTED.equals(status)
-                || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status)) {
-            updateProgressDialog(R.string.progress_unmounting);
-            IMountService mountService = getMountService();
-            final String extStoragePath = mStorageVolume == null ?
-                    Environment.getLegacyExternalStorageDirectory().toString() :
-                    mStorageVolume.getPath();
-            try {
-                // Remove encryption mapping if this is an unmount for a factory reset.
-                mountService.unmountVolume(extStoragePath, true, mFactoryReset);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with mount service", e);
-            }
-        } else if (Environment.MEDIA_NOFS.equals(status)
-                || Environment.MEDIA_UNMOUNTED.equals(status)
-                || Environment.MEDIA_UNMOUNTABLE.equals(status)) {
-            updateProgressDialog(R.string.progress_erasing);
-            final IMountService mountService = getMountService();
-            final String extStoragePath = mStorageVolume == null ?
-                    Environment.getLegacyExternalStorageDirectory().toString() :
-                    mStorageVolume.getPath();
-            if (mountService != null) {
-                new Thread() {
-                    @Override
-                    public void run() {
-                        boolean success = false;
-                        try {
-                            mountService.formatVolume(extStoragePath);
-                            success = true;
-                        } catch (Exception e) {
-                            Toast.makeText(ExternalStorageFormatter.this,
-                                    R.string.format_error, Toast.LENGTH_LONG).show();
-                        }
-                        if (success) {
-                            if (mFactoryReset) {
-                                Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
-                                intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-                                intent.putExtra(Intent.EXTRA_REASON, mReason);
-                                sendBroadcast(intent);
-                                // Intent handling is asynchronous -- assume it will happen soon.
-                                stopSelf();
-                                return;
-                            }
-                        }
-                        // If we didn't succeed, or aren't doing a full factory
-                        // reset, then it is time to remount the storage.
-                        if (!success && mAlwaysReset) {
-                            Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
-                            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-                            intent.putExtra(Intent.EXTRA_REASON, mReason);
-                            sendBroadcast(intent);
-                        } else {
-                            try {
-                                mountService.mountVolume(extStoragePath);
-                            } catch (RemoteException e) {
-                                Log.w(TAG, "Failed talking with mount service", e);
-                            }
-                        }
-                        stopSelf();
-                        return;
-                    }
-                }.start();
-            } else {
-                Log.w(TAG, "Unable to locate IMountService");
-            }
-        } else if (Environment.MEDIA_BAD_REMOVAL.equals(status)) {
-            fail(R.string.media_bad_removal);
-        } else if (Environment.MEDIA_CHECKING.equals(status)) {
-            fail(R.string.media_checking);
-        } else if (Environment.MEDIA_REMOVED.equals(status)) {
-            fail(R.string.media_removed);
-        } else if (Environment.MEDIA_SHARED.equals(status)) {
-            fail(R.string.media_shared);
-        } else {
-            fail(R.string.media_unknown_state);
-            Log.w(TAG, "Unknown storage state: " + status);
-            stopSelf();
-        }
-    }
-
-    public void updateProgressDialog(int msg) {
-        if (mProgressDialog == null) {
-            mProgressDialog = new ProgressDialog(this);
-            mProgressDialog.setIndeterminate(true);
-            mProgressDialog.setCancelable(false);
-            mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-            mProgressDialog.show();
-        }
-
-        mProgressDialog.setMessage(getText(msg));
-    }
-
-    IMountService getMountService() {
-        if (mMountService == null) {
-            IBinder service = ServiceManager.getService("mount");
-            if (service != null) {
-                mMountService = IMountService.Stub.asInterface(service);
-            } else {
-                Log.e(TAG, "Can't get mount service");
-            }
-        }
-        return mMountService;
-    }
 }
diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java
index c153904..7d56e9e 100644
--- a/core/java/com/android/internal/util/ImageUtils.java
+++ b/core/java/com/android/internal/util/ImageUtils.java
@@ -17,10 +17,13 @@
 package com.android.internal.util;
 
 import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 
 /**
  * Utility class for image analysis and processing.
@@ -117,4 +120,40 @@
                 && Math.abs(r - b) < TOLERANCE
                 && Math.abs(g - b) < TOLERANCE;
     }
+
+    /**
+     * Convert a drawable to a bitmap, scaled to fit within maxWidth and maxHeight.
+     */
+    public static Bitmap buildScaledBitmap(Drawable drawable, int maxWidth,
+            int maxHeight) {
+        if (drawable == null) {
+            return null;
+        }
+        int originalWidth = drawable.getIntrinsicWidth();
+        int originalHeight = drawable.getIntrinsicHeight();
+
+        if ((originalWidth <= maxWidth) && (originalHeight <= maxHeight) &&
+                (drawable instanceof BitmapDrawable)) {
+            return ((BitmapDrawable) drawable).getBitmap();
+        }
+        if (originalHeight <= 0 || originalWidth <= 0) {
+            return null;
+        }
+
+        // create a new bitmap, scaling down to fit the max dimensions of
+        // a large notification icon if necessary
+        float ratio = Math.min((float) maxWidth / (float) originalWidth,
+                (float) maxHeight / (float) originalHeight);
+        ratio = Math.min(1.0f, ratio);
+        int scaledWidth = (int) (ratio * originalWidth);
+        int scaledHeight = (int) (ratio * originalHeight);
+        Bitmap result = Bitmap.createBitmap(scaledWidth, scaledHeight, Config.ARGB_8888);
+
+        // and paint our app bitmap on it
+        Canvas canvas = new Canvas(result);
+        drawable.setBounds(0, 0, scaledWidth, scaledHeight);
+        drawable.draw(canvas);
+
+        return result;
+    }
 }
diff --git a/core/java/com/android/internal/util/IndentingPrintWriter.java b/core/java/com/android/internal/util/IndentingPrintWriter.java
index 6fddd09..f1add27 100644
--- a/core/java/com/android/internal/util/IndentingPrintWriter.java
+++ b/core/java/com/android/internal/util/IndentingPrintWriter.java
@@ -18,6 +18,7 @@
 
 import java.io.PrintWriter;
 import java.io.Writer;
+import java.util.Arrays;
 
 /**
  * Lightweight wrapper around {@link PrintWriter} that automatically indents
@@ -68,6 +69,10 @@
         print(key + "=" + String.valueOf(value) + " ");
     }
 
+    public void printPair(String key, Object[] value) {
+        print(key + "=" + Arrays.toString(value) + " ");
+    }
+
     public void printHexPair(String key, int value) {
         print(key + "=0x" + Integer.toHexString(value) + " ");
     }
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index d9ebc25..a106f48 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -52,6 +52,7 @@
     public static final int BASE_WIFI_RTT_SERVICE                                   = 0x00027300;
     public static final int BASE_WIFI_PASSPOINT_MANAGER                             = 0x00028000;
     public static final int BASE_WIFI_PASSPOINT_SERVICE                             = 0x00028100;
+    public static final int BASE_WIFI_LOGGER                                        = 0x00028300;
     public static final int BASE_DHCP                                               = 0x00030000;
     public static final int BASE_DATA_CONNECTION                                    = 0x00040000;
     public static final int BASE_DATA_CONNECTION_AC                                 = 0x00041000;
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
new file mode 100644
index 0000000..be9945d
--- /dev/null
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -0,0 +1,596 @@
+/*
+ * 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.internal.widget;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
+
+import com.android.internal.R;
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A floating toolbar for showing contextual menu items.
+ * This view shows as many menu item buttons as can fit in the horizontal toolbar and the
+ * the remaining menu items in a vertical overflow view when the overflow button is clicked.
+ * The horizontal toolbar morphs into the vertical overflow view.
+ */
+public final class FloatingToolbar {
+
+    private static final MenuItem.OnMenuItemClickListener NO_OP_MENUITEM_CLICK_LISTENER =
+            new MenuItem.OnMenuItemClickListener() {
+                @Override
+                public boolean onMenuItemClick(MenuItem item) {
+                    return false;
+                }
+            };
+
+    private final Context mContext;
+    private final FloatingToolbarPopup mPopup;
+    private final ViewGroup mMenuItemButtonsContainer;
+    private final View.OnClickListener mMenuItemButtonOnClickListener =
+            new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (v.getTag() instanceof MenuItem) {
+                        mMenuItemClickListener.onMenuItemClick((MenuItem) v.getTag());
+                        mPopup.dismiss();
+                    }
+                }
+            };
+
+    private final Rect mContentRect = new Rect();
+    private final Point mCoordinates = new Point();
+
+    private Menu mMenu;
+    private List<CharSequence> mShowingTitles = new ArrayList<CharSequence>();
+    private MenuItem.OnMenuItemClickListener mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER;
+    private View mOpenOverflowButton;
+
+    private int mSuggestedWidth;
+
+    /**
+     * Initializes a floating toolbar.
+     */
+    public FloatingToolbar(Context context, Window window) {
+        mContext = Preconditions.checkNotNull(context);
+        mPopup = new FloatingToolbarPopup(Preconditions.checkNotNull(window.getDecorView()));
+        mMenuItemButtonsContainer = createMenuButtonsContainer(context);
+    }
+
+    /**
+     * Sets the menu to be shown in this floating toolbar.
+     * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the
+     * toolbar.
+     */
+    public FloatingToolbar setMenu(Menu menu) {
+        mMenu = Preconditions.checkNotNull(menu);
+        return this;
+    }
+
+    /**
+     * Sets the custom listener for invocation of menu items in this floating
+     * toolbar.
+     */
+    public FloatingToolbar setOnMenuItemClickListener(
+            MenuItem.OnMenuItemClickListener menuItemClickListener) {
+        if (menuItemClickListener != null) {
+            mMenuItemClickListener = menuItemClickListener;
+        } else {
+            mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER;
+        }
+        return this;
+    }
+
+    /**
+     * Sets the content rectangle. This is the area of the interesting content that this toolbar
+     * should avoid obstructing.
+     * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the
+     * toolbar.
+     */
+    public FloatingToolbar setContentRect(Rect rect) {
+        mContentRect.set(Preconditions.checkNotNull(rect));
+        return this;
+    }
+
+    /**
+     * Sets the suggested width of this floating toolbar.
+     * The actual width will be about this size but there are no guarantees that it will be exactly
+     * the suggested width.
+     * NOTE: Call {@link #updateLayout()} or {@link #show()} to effect visual changes to the
+     * toolbar.
+     */
+    public FloatingToolbar setSuggestedWidth(int suggestedWidth) {
+        mSuggestedWidth = suggestedWidth;
+        return this;
+    }
+
+    /**
+     * Shows this floating toolbar.
+     */
+    public FloatingToolbar show() {
+        List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu);
+        if (hasContentChanged(menuItems) || hasWidthChanged()) {
+            mPopup.dismiss();
+            layoutMenuItemButtons(menuItems);
+            mShowingTitles = getMenuItemTitles(menuItems);
+        }
+        refreshCoordinates();
+        mPopup.updateCoordinates(mCoordinates.x, mCoordinates.y);
+        if (!mPopup.isShowing()) {
+            mPopup.show(mCoordinates.x, mCoordinates.y);
+        }
+        return this;
+    }
+
+    /**
+     * Updates this floating toolbar to reflect recent position and view updates.
+     * NOTE: This method is a no-op if the toolbar isn't showing.
+     */
+    public FloatingToolbar updateLayout() {
+        if (mPopup.isShowing()) {
+            // show() performs all the logic we need here.
+            show();
+        }
+        return this;
+    }
+
+    /**
+     * Dismisses this floating toolbar.
+     */
+    public void dismiss() {
+        mPopup.dismiss();
+    }
+
+    /**
+     * Returns {@code true} if this popup is currently showing. {@code false} otherwise.
+     */
+    public boolean isShowing() {
+        return mPopup.isShowing();
+    }
+
+    /**
+     * Refreshes {@link #mCoordinates} with values based on {@link #mContentRect}.
+     */
+    private void refreshCoordinates() {
+        int popupWidth = mPopup.getWidth();
+        int popupHeight = mPopup.getHeight();
+        if (!mPopup.isShowing()) {
+            // Popup isn't yet shown, get estimated size from the menu item buttons container.
+            mMenuItemButtonsContainer.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+            popupWidth = mMenuItemButtonsContainer.getMeasuredWidth();
+            popupHeight = mMenuItemButtonsContainer.getMeasuredHeight();
+        }
+        int x = mContentRect.centerX() - popupWidth / 2;
+        int y;
+        if (shouldDisplayAtTopOfContent()) {
+            y = mContentRect.top - popupHeight;
+        } else {
+            y = mContentRect.bottom;
+        }
+        mCoordinates.set(x, y);
+    }
+
+    /**
+     * Returns true if this floating toolbar's menu items have been reordered or changed.
+     */
+    private boolean hasContentChanged(List<MenuItem> menuItems) {
+        return !mShowingTitles.equals(getMenuItemTitles(menuItems));
+    }
+
+    /**
+     * Returns true if there is a significant change in width of the toolbar.
+     */
+    private boolean hasWidthChanged() {
+        int actualWidth = mPopup.getWidth();
+        int difference = Math.abs(actualWidth - mSuggestedWidth);
+        return difference > (actualWidth * 0.2);
+    }
+
+    /**
+     * Returns true if the preferred positioning of the toolbar is above the content rect.
+     */
+    private boolean shouldDisplayAtTopOfContent() {
+        return mContentRect.top - getMinimumOverflowHeight(mContext) > 0;
+    }
+
+    /**
+     * Returns the visible and enabled menu items in the specified menu.
+     * This method is recursive.
+     */
+    private List<MenuItem> getVisibleAndEnabledMenuItems(Menu menu) {
+        List<MenuItem> menuItems = new ArrayList<MenuItem>();
+        for (int i = 0; (menu != null) && (i < menu.size()); i++) {
+            MenuItem menuItem = menu.getItem(i);
+            if (menuItem.isVisible() && menuItem.isEnabled()) {
+                Menu subMenu = menuItem.getSubMenu();
+                if (subMenu != null) {
+                    menuItems.addAll(getVisibleAndEnabledMenuItems(subMenu));
+                } else {
+                    menuItems.add(menuItem);
+                }
+            }
+        }
+        return menuItems;
+    }
+
+    private List<CharSequence> getMenuItemTitles(List<MenuItem> menuItems) {
+        List<CharSequence> titles = new ArrayList<CharSequence>();
+        for (MenuItem menuItem : menuItems) {
+            titles.add(menuItem.getTitle());
+        }
+        return titles;
+    }
+
+    private void layoutMenuItemButtons(List<MenuItem> menuItems) {
+        final int toolbarWidth = getAdjustedToolbarWidth(mContext, mSuggestedWidth)
+                // Reserve space for the "open overflow" button.
+                - getEstimatedOpenOverflowButtonWidth(mContext);
+
+        int availableWidth = toolbarWidth;
+        LinkedList<MenuItem> remainingMenuItems = new LinkedList<MenuItem>(menuItems);
+
+        mMenuItemButtonsContainer.removeAllViews();
+
+        boolean isFirstItem = true;
+        while (!remainingMenuItems.isEmpty()) {
+            final MenuItem menuItem = remainingMenuItems.peek();
+            Button menuItemButton = createMenuItemButton(mContext, menuItem);
+
+            // Adding additional left padding for the first button to even out button spacing.
+            if (isFirstItem) {
+                menuItemButton.setPadding(
+                        2 * menuItemButton.getPaddingLeft(),
+                        menuItemButton.getPaddingTop(),
+                        menuItemButton.getPaddingRight(),
+                        menuItemButton.getPaddingBottom());
+                isFirstItem = false;
+            }
+
+            // Adding additional right padding for the last button to even out button spacing.
+            if (remainingMenuItems.size() == 1) {
+                menuItemButton.setPadding(
+                        menuItemButton.getPaddingLeft(),
+                        menuItemButton.getPaddingTop(),
+                        2 * menuItemButton.getPaddingRight(),
+                        menuItemButton.getPaddingBottom());
+            }
+
+            menuItemButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+            int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth);
+            if (menuItemButtonWidth <= availableWidth) {
+                menuItemButton.setTag(menuItem);
+                menuItemButton.setOnClickListener(mMenuItemButtonOnClickListener);
+                mMenuItemButtonsContainer.addView(menuItemButton);
+                menuItemButton.getLayoutParams().width = menuItemButtonWidth;
+                availableWidth -= menuItemButtonWidth;
+                remainingMenuItems.pop();
+            } else {
+                // The "open overflow" button launches the vertical overflow from the
+                // floating toolbar.
+                createOpenOverflowButtonIfNotExists();
+                mMenuItemButtonsContainer.addView(mOpenOverflowButton);
+                break;
+            }
+        }
+        mPopup.setContentView(mMenuItemButtonsContainer);
+    }
+
+    /**
+     * Creates and returns the button that opens the vertical overflow.
+     */
+    private void createOpenOverflowButtonIfNotExists() {
+        mOpenOverflowButton = (ImageButton) LayoutInflater.from(mContext)
+                .inflate(R.layout.floating_popup_open_overflow_button, null);
+        mOpenOverflowButton.setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        // Open the overflow.
+                    }
+                });
+    }
+
+    /**
+     * Creates and returns a floating toolbar menu buttons container.
+     */
+    private static ViewGroup createMenuButtonsContainer(Context context) {
+        return (ViewGroup) LayoutInflater.from(context)
+                .inflate(R.layout.floating_popup_container, null);
+    }
+
+    /**
+     * Creates and returns a menu button for the specified menu item.
+     */
+    private static Button createMenuItemButton(Context context, MenuItem menuItem) {
+        Button menuItemButton = (Button) LayoutInflater.from(context)
+                .inflate(R.layout.floating_popup_menu_button, null);
+        menuItemButton.setText(menuItem.getTitle());
+        menuItemButton.setContentDescription(menuItem.getTitle());
+        return menuItemButton;
+    }
+
+    private static int getMinimumOverflowHeight(Context context) {
+        return context.getResources().
+                getDimensionPixelSize(R.dimen.floating_toolbar_minimum_overflow_height);
+    }
+
+    private static int getEstimatedOpenOverflowButtonWidth(Context context) {
+        return context.getResources()
+                .getDimensionPixelSize(R.dimen.floating_toolbar_menu_button_minimum_width);
+    }
+
+    private static int getAdjustedToolbarWidth(Context context, int width) {
+        if (width <= 0 || width > getScreenWidth(context)) {
+            width = context.getResources()
+                    .getDimensionPixelSize(R.dimen.floating_toolbar_default_width);
+        }
+        return width;
+    }
+
+    /**
+     * Returns the device's screen width.
+     */
+    public static int getScreenWidth(Context context) {
+        return context.getResources().getDisplayMetrics().widthPixels;
+    }
+
+    /**
+     * Returns the device's screen height.
+     */
+    public static int getScreenHeight(Context context) {
+        return context.getResources().getDisplayMetrics().heightPixels;
+    }
+
+
+    /**
+     * A popup window used by the floating toolbar.
+     */
+    private static final class FloatingToolbarPopup {
+
+        private final View mParent;
+        private final PopupWindow mPopupWindow;
+        private final ViewGroup mContentContainer;
+        private final Animator.AnimatorListener mOnDismissEnd =
+                new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mPopupWindow.dismiss();
+                        mDismissAnimating = false;
+                    }
+                };
+        private final AnimatorSet mGrowFadeInFromBottomAnimation;
+        private final AnimatorSet mShrinkFadeOutFromBottomAnimation;
+
+        private boolean mDismissAnimating;
+
+        /**
+         * Initializes a new floating bar popup.
+         *
+         * @param parent  A parent view to get the {@link View#getWindowToken()} token from.
+         */
+        public FloatingToolbarPopup(View parent) {
+            mParent = Preconditions.checkNotNull(parent);
+            mContentContainer = createContentContainer(parent.getContext());
+            mPopupWindow = createPopupWindow(mContentContainer);
+            mGrowFadeInFromBottomAnimation = createGrowFadeInFromBottom(mContentContainer);
+            mShrinkFadeOutFromBottomAnimation =
+                    createShrinkFadeOutFromBottomAnimation(mContentContainer, mOnDismissEnd);
+        }
+
+        /**
+         * Shows this popup at the specified coordinates.
+         * The specified coordinates may be adjusted to make sure the popup is entirely on-screen.
+         * If this popup is already showing, this will be a no-op.
+         */
+        public void show(int x, int y) {
+            if (isShowing()) {
+                updateCoordinates(x, y);
+                return;
+            }
+
+            mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, 0, 0);
+            positionOnScreen(x, y);
+            growFadeInFromBottom();
+
+            mDismissAnimating = false;
+        }
+
+        /**
+         * Gets rid of this popup. If the popup isn't currently showing, this will be a no-op.
+         */
+        public void dismiss() {
+            if (!isShowing()) {
+                return;
+            }
+
+            if (mDismissAnimating) {
+                // This window is already dismissing. Don't restart the animation.
+                return;
+            }
+            mDismissAnimating = true;
+            shrinkFadeOutFromBottom();
+        }
+
+        /**
+         * Returns {@code true} if this popup is currently showing. {@code false} otherwise.
+         */
+        public boolean isShowing() {
+            return mPopupWindow.isShowing() && !mDismissAnimating;
+        }
+
+        /**
+         * Updates the coordinates of this popup.
+         * The specified coordinates may be adjusted to make sure the popup is entirely on-screen.
+         */
+        public void updateCoordinates(int x, int y) {
+            if (isShowing()) {
+                positionOnScreen(x, y);
+            }
+        }
+
+        /**
+         * Sets the content of this popup.
+         */
+        public void setContentView(View view) {
+            Preconditions.checkNotNull(view);
+            mContentContainer.removeAllViews();
+            mContentContainer.addView(view);
+        }
+
+        /**
+         * Returns the width of this popup.
+         */
+        public int getWidth() {
+            return mContentContainer.getWidth();
+        }
+
+        /**
+         * Returns the height of this popup.
+         */
+        public int getHeight() {
+            return mContentContainer.getHeight();
+        }
+
+        /**
+         * Returns the context this popup is running in.
+         */
+        public Context getContext() {
+            return mContentContainer.getContext();
+        }
+
+        private void positionOnScreen(int x, int y) {
+            if (getWidth() == 0) {
+                // content size is yet to be measured.
+                mContentContainer.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+            }
+            x = clamp(x, 0, getScreenWidth(getContext()) - getWidth());
+            y = clamp(y, 0, getScreenHeight(getContext()) - getHeight());
+
+            // Position the view w.r.t. the window.
+            mContentContainer.setX(x);
+            mContentContainer.setY(y);
+        }
+
+        /**
+         * Performs the "grow and fade in from the bottom" animation on the floating popup.
+         */
+        private void growFadeInFromBottom() {
+            setPivot();
+            mGrowFadeInFromBottomAnimation.start();
+        }
+
+        /**
+         * Performs the "shrink and fade out from bottom" animation on the floating popup.
+         */
+        private void shrinkFadeOutFromBottom() {
+            setPivot();
+            mShrinkFadeOutFromBottomAnimation.start();
+        }
+
+        /**
+         * Sets the popup content container's pivot.
+         */
+        private void setPivot() {
+            mContentContainer.setPivotX(mContentContainer.getMeasuredWidth() / 2);
+            mContentContainer.setPivotY(mContentContainer.getMeasuredHeight());
+        }
+
+        private static ViewGroup createContentContainer(Context context) {
+            return (ViewGroup) LayoutInflater.from(context)
+                    .inflate(R.layout.floating_popup_container, null);
+        }
+
+        private static PopupWindow createPopupWindow(View content) {
+            ViewGroup popupContentHolder = new LinearLayout(content.getContext());
+            PopupWindow popupWindow = new PopupWindow(popupContentHolder);
+            popupWindow.setAnimationStyle(0);
+            popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+            popupWindow.setWidth(getScreenWidth(content.getContext()));
+            popupWindow.setHeight(getScreenHeight(content.getContext()));
+            content.setLayoutParams(new ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+            popupContentHolder.addView(content);
+            return popupWindow;
+        }
+
+        /**
+         * Creates a "grow and fade in from the bottom" animation for the specified view.
+         *
+         * @param view  The view to animate
+         */
+        private static AnimatorSet createGrowFadeInFromBottom(View view) {
+            AnimatorSet growFadeInFromBottomAnimation =  new AnimatorSet();
+            growFadeInFromBottomAnimation.playTogether(
+                    ObjectAnimator.ofFloat(view, View.SCALE_X, 0.5f, 1).setDuration(125),
+                    ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.5f, 1).setDuration(125),
+                    ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(75));
+            return growFadeInFromBottomAnimation;
+        }
+
+        /**
+         * Creates a "shrink and fade out from bottom" animation for the specified view.
+         *
+         * @param view  The view to animate
+         * @param listener  The animation listener
+         */
+        private static AnimatorSet createShrinkFadeOutFromBottomAnimation(
+                View view, Animator.AnimatorListener listener) {
+            AnimatorSet shrinkFadeOutFromBottomAnimation =  new AnimatorSet();
+            shrinkFadeOutFromBottomAnimation.playTogether(
+                    ObjectAnimator.ofFloat(view, View.SCALE_Y, 1, 0.5f).setDuration(125),
+                    ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0).setDuration(75));
+            shrinkFadeOutFromBottomAnimation.setStartDelay(150);
+            shrinkFadeOutFromBottomAnimation.addListener(listener);
+            return shrinkFadeOutFromBottomAnimation;
+        }
+
+        /**
+         * Returns value, restricted to the range min->max (inclusive).
+         * If maximum is less than minimum, the result is undefined.
+         *
+         * @param value  The value to clamp.
+         * @param minimum  The minimum value in the range.
+         * @param maximum  The maximum value in the range. Must not be less than minimum.
+         */
+        private static int clamp(int value, int minimum, int maximum) {
+            return Math.max(minimum, Math.min(value, maximum));
+        }
+    }
+}
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 8018942..8d66191 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -42,6 +42,7 @@
 import android.view.ViewParent;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.accessibility.AccessibilityRecord;
 import android.view.animation.Interpolator;
 import android.widget.EdgeEffect;
@@ -371,8 +372,6 @@
         mCloseEnough = (int) (CLOSE_ENOUGH * density);
         mDefaultGutterSize = (int) (DEFAULT_GUTTER_SIZE * density);
 
-        setAccessibilityDelegate(new MyAccessibilityDelegate());
-
         if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
@@ -2695,29 +2694,6 @@
     }
 
     @Override
-    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-        // Dispatch scroll events from this ViewPager.
-        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
-            return super.dispatchPopulateAccessibilityEvent(event);
-        }
-
-        // Dispatch all other accessibility events from the current page.
-        final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            final View child = getChildAt(i);
-            if (child.getVisibility() == VISIBLE) {
-                final ItemInfo ii = infoForChild(child);
-                if (ii != null && ii.position == mCurItem &&
-                        child.dispatchPopulateAccessibilityEvent(event)) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    @Override
     protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
         return new LayoutParams();
     }
@@ -2737,60 +2713,63 @@
         return new LayoutParams(getContext(), attrs);
     }
 
-    class MyAccessibilityDelegate extends AccessibilityDelegate {
 
-        @Override
-        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
-            super.onInitializeAccessibilityEvent(host, event);
-            event.setClassName(ViewPager.class.getName());
-            final AccessibilityRecord record = AccessibilityRecord.obtain();
-            record.setScrollable(canScroll());
-            if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED
-                    && mAdapter != null) {
-                record.setItemCount(mAdapter.getCount());
-                record.setFromIndex(mCurItem);
-                record.setToIndex(mCurItem);
-            }
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+
+        event.setClassName(ViewPager.class.getName());
+        event.setScrollable(canScroll());
+
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED && mAdapter != null) {
+            event.setItemCount(mAdapter.getCount());
+            event.setFromIndex(mCurItem);
+            event.setToIndex(mCurItem);
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+
+        info.setClassName(ViewPager.class.getName());
+        info.setScrollable(canScroll());
+
+        if (canScrollHorizontally(1)) {
+            info.addAction(AccessibilityAction.ACTION_SCROLL_FORWARD);
         }
 
-        @Override
-        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
-            super.onInitializeAccessibilityNodeInfo(host, info);
-            info.setClassName(ViewPager.class.getName());
-            info.setScrollable(canScroll());
-            if (canScrollHorizontally(1)) {
-                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
-            }
-            if (canScrollHorizontally(-1)) {
-                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
-            }
+        if (canScrollHorizontally(-1)) {
+            info.addAction(AccessibilityAction.ACTION_SCROLL_BACKWARD);
+        }
+    }
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle args) {
+        if (super.performAccessibilityAction(action, args)) {
+            return true;
         }
 
-        @Override
-        public boolean performAccessibilityAction(View host, int action, Bundle args) {
-            if (super.performAccessibilityAction(host, action, args)) {
-                return true;
-            }
-            switch (action) {
-                case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
-                    if (canScrollHorizontally(1)) {
-                        setCurrentItem(mCurItem + 1);
-                        return true;
-                    }
-                } return false;
-                case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
-                    if (canScrollHorizontally(-1)) {
-                        setCurrentItem(mCurItem - 1);
-                        return true;
-                    }
-                } return false;
-            }
-            return false;
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
+                if (canScrollHorizontally(1)) {
+                    setCurrentItem(mCurItem + 1);
+                    return true;
+                }
+                return false;
+            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
+                if (canScrollHorizontally(-1)) {
+                    setCurrentItem(mCurItem - 1);
+                    return true;
+                }
+                return false;
         }
 
-        private boolean canScroll() {
-            return (mAdapter != null) && (mAdapter.getCount() > 1);
-        }
+        return false;
+    }
+
+    private boolean canScroll() {
+        return mAdapter != null && mAdapter.getCount() > 1;
     }
 
     private class PagerObserver extends DataSetObserver {
diff --git a/core/java/com/android/server/backup/PreferredActivityBackupHelper.java b/core/java/com/android/server/backup/PreferredActivityBackupHelper.java
new file mode 100644
index 0000000..6ac0d89
--- /dev/null
+++ b/core/java/com/android/server/backup/PreferredActivityBackupHelper.java
@@ -0,0 +1,175 @@
+/*
+ * 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.backup;
+
+import android.app.AppGlobals;
+import android.app.backup.BackupDataInputStream;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupHelper;
+import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.org.bouncycastle.util.Arrays;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class PreferredActivityBackupHelper implements BackupHelper {
+    private static final String TAG = "PreferredBackup";
+    private static final boolean DEBUG = true;
+
+    // current schema of the backup state blob
+    private static final int STATE_VERSION = 1;
+
+    // key under which the preferred-activity state blob is committed to backup
+    private static final String KEY_PREFERRED = "preferred-activity";
+
+    final Context mContext;
+
+    public PreferredActivityBackupHelper(Context context) {
+        mContext = context;
+    }
+
+    // The fds passed here are shared among all helpers, so we mustn't close them
+    private void writeState(ParcelFileDescriptor stateFile, byte[] payload) {
+        try {
+            FileOutputStream fos = new FileOutputStream(stateFile.getFileDescriptor());
+
+            // We explicitly don't close 'out' because we must not close the backing fd.
+            // The FileOutputStream will not close it implicitly.
+            @SuppressWarnings("resource")
+            DataOutputStream out = new DataOutputStream(fos);
+
+            out.writeInt(STATE_VERSION);
+            if (payload == null) {
+                out.writeInt(0);
+            } else {
+                out.writeInt(payload.length);
+                out.write(payload);
+            }
+        } catch (IOException e) {
+            Slog.e(TAG, "Unable to write updated state", e);
+        }
+    }
+
+    private byte[] readState(ParcelFileDescriptor oldStateFd) {
+        FileInputStream fis = new FileInputStream(oldStateFd.getFileDescriptor());
+        BufferedInputStream bis = new BufferedInputStream(fis);
+
+        @SuppressWarnings("resource")
+        DataInputStream in = new DataInputStream(bis);
+
+        byte[] oldState = null;
+        try {
+            int version = in.readInt();
+            if (version == STATE_VERSION) {
+                int size = in.readInt();
+                if (size > 0) {
+                    if (size > 200*1024) {
+                        Slog.w(TAG, "Suspiciously large state blog; ignoring.  N=" + size);
+                    } else {
+                        // size looks okay; make the return buffer and fill it
+                        oldState = new byte[size];
+                        in.read(oldState);
+                    }
+                }
+            } else {
+                Slog.w(TAG, "Prior state from unrecognized version " + version);
+            }
+        } catch (EOFException e) {
+            // Empty file is expected on first backup,  so carry on. If the state
+            // is truncated we just treat it the same way.
+            oldState = null;
+        } catch (Exception e) {
+            Slog.w(TAG, "Error examing prior backup state " + e.getMessage());
+            oldState = null;
+        }
+
+        return oldState;
+    }
+
+    @Override
+    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+            ParcelFileDescriptor newState) {
+        byte[] payload = null;
+        try {
+            byte[] oldPayload = readState(oldState);
+
+            IPackageManager pm = AppGlobals.getPackageManager();
+            byte[] newPayload = pm.getPreferredActivityBackup(UserHandle.USER_OWNER);
+            if (!Arrays.areEqual(oldPayload, newPayload)) {
+                if (DEBUG) {
+                    Slog.i(TAG, "State has changed => writing new preferred app payload");
+                }
+                data.writeEntityHeader(KEY_PREFERRED, newPayload.length);
+                data.writeEntityData(newPayload, newPayload.length);
+            } else {
+                if (DEBUG) {
+                    Slog.i(TAG, "No change to state => not writing to wire");
+                }
+            }
+
+            // Always need to re-record the state, even if nothing changed
+            payload = newPayload;
+        } catch (Exception e) {
+            // On failures we'll wind up committing a zero-size state payload.  This is
+            // a forward-safe situation because we know we commit the entire new payload
+            // on prior-state mismatch.
+            Slog.w(TAG, "Unable to record preferred activities", e);
+        } finally {
+            writeState(newState, payload);
+        }
+    }
+
+    @Override
+    public void restoreEntity(BackupDataInputStream data) {
+        IPackageManager pm = AppGlobals.getPackageManager();
+        try {
+            byte[] payload = new byte[data.size()];
+            data.read(payload);
+            if (DEBUG) {
+                Slog.i(TAG, "Restoring preferred activities; size=" + payload.length);
+            }
+            pm.restorePreferredActivities(payload, UserHandle.USER_OWNER);
+        } catch (Exception e) {
+            Slog.e(TAG, "Exception reading restore data", e);
+        }
+    }
+
+    @Override
+    public void writeNewStateDescription(ParcelFileDescriptor newState) {
+        writeState(newState, null);
+    }
+
+}
diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java
index b5f2f37..19d9e29 100644
--- a/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -16,7 +16,6 @@
 
 package com.android.server.backup;
 
-
 import android.app.ActivityManagerNative;
 import android.app.IWallpaperManager;
 import android.app.backup.BackupDataInput;
@@ -43,6 +42,13 @@
 public class SystemBackupAgent extends BackupAgentHelper {
     private static final String TAG = "SystemBackupAgent";
 
+    // Names of the helper tags within the dataset.  Changing one of these names will
+    // break the ability to restore from datasets that predate the change.
+    private static final String WALLPAPER_HELPER = "wallpaper";
+    private static final String RECENTS_HELPER = "recents";
+    private static final String SYNC_SETTINGS_HELPER = "account_sync_settings";
+    private static final String PREFERRED_HELPER = "preferred_activities";
+
     // These paths must match what the WallpaperManagerService uses.  The leaf *_FILENAME
     // are also used in the full-backup file format, so must not change unless steps are
     // taken to support the legacy backed-up datasets.
@@ -84,10 +90,10 @@
                 Slog.e(TAG, "Couldn't get wallpaper name\n" + re);
             }
         }
-        addHelper("wallpaper", new WallpaperBackupHelper(SystemBackupAgent.this, files, keys));
-        addHelper("recents", new RecentsBackupHelper(SystemBackupAgent.this));
-        addHelper("account_sync_settings",
-                new AccountSyncSettingsBackupHelper(SystemBackupAgent.this));
+        addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this, files, keys));
+        addHelper(RECENTS_HELPER, new RecentsBackupHelper(this));
+        addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
+        addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper(this));
 
         super.onBackup(oldState, data, newState);
     }
@@ -104,24 +110,24 @@
         // steps during restore; the restore will happen properly when the individual
         // files are restored piecemeal.
         FullBackup.backupToTar(getPackageName(), FullBackup.ROOT_TREE_TOKEN, null,
-                WALLPAPER_INFO_DIR, WALLPAPER_INFO, output.getData());
+                WALLPAPER_INFO_DIR, WALLPAPER_INFO, output);
         FullBackup.backupToTar(getPackageName(), FullBackup.ROOT_TREE_TOKEN, null,
-                WALLPAPER_IMAGE_DIR, WALLPAPER_IMAGE, output.getData());
+                WALLPAPER_IMAGE_DIR, WALLPAPER_IMAGE, output);
     }
 
     @Override
     public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
             throws IOException {
         // On restore, we also support a previous data schema "system_files"
-        addHelper("wallpaper", new WallpaperBackupHelper(SystemBackupAgent.this,
+        addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this,
                 new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO },
                 new String[] { WALLPAPER_IMAGE_KEY, WALLPAPER_INFO_KEY} ));
-        addHelper("system_files", new WallpaperBackupHelper(SystemBackupAgent.this,
+        addHelper("system_files", new WallpaperBackupHelper(this,
                 new String[] { WALLPAPER_IMAGE },
                 new String[] { WALLPAPER_IMAGE_KEY} ));
-        addHelper("recents", new RecentsBackupHelper(SystemBackupAgent.this));
-        addHelper("account_sync_settings",
-                new AccountSyncSettingsBackupHelper(SystemBackupAgent.this));
+        addHelper(RECENTS_HELPER, new RecentsBackupHelper(this));
+        addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
+        addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper(this));
 
         try {
             super.onRestore(data, appVersionCode, newState);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 84568e4..cd117eb1 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -151,7 +151,6 @@
     android_util_FileObserver.cpp \
     android/opengl/poly_clip.cpp.arm \
     android/opengl/util.cpp \
-    android_server_FingerprintManager.cpp \
     android_server_NetworkManagementSocketTagger.cpp \
     android_server_Watchdog.cpp \
     android_ddm_DdmHandleNativeHeap.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 34de6c5..88f0697 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -552,12 +552,19 @@
     char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
     char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
     char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
+    char cachePruneBuf[sizeof("-Xzygote-max-boot-retry=")-1 + PROPERTY_VALUE_MAX];
     char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
     char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
     char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
     char dex2oatXmxFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
     char dex2oatCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
     char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
+    char dex2oatThreadsBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];
+    char dex2oatThreadsImageBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];
+    char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
+    char dex2oat_isa_variant[sizeof("--instruction-set-variant=") -1 + PROPERTY_VALUE_MAX];
+    char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
+    char dex2oat_isa_features[sizeof("--instruction-set-features=") -1 + PROPERTY_VALUE_MAX];
     char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];
     char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
     char extraOptsBuf[PROPERTY_VALUE_MAX];
@@ -733,6 +740,46 @@
         parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf,
                             "--compiler-filter=", "-Xcompiler-option");
     }
+    parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option");
+    parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j",
+                        "-Ximage-compiler-option");
+
+    // The runtime will compile a boot image, when necessary, not using installd. Thus, we need to
+    // pass the instruction-set-features/variant as an image-compiler-option.
+    // TODO: Find a better way for the instruction-set.
+#if defined(__arm__)
+    constexpr const char* instruction_set = "arm";
+#elif defined(__aarch64__)
+    constexpr const char* instruction_set = "arm64";
+#elif defined(__mips__) && !defined(__LP64__)
+    constexpr const char* instruction_set = "mips";
+#elif defined(__mips__) && defined(__LP64__)
+    constexpr const char* instruction_set = "mips64";
+#elif defined(__i386__)
+    constexpr const char* instruction_set = "x86";
+#elif defined(__x86_64__)
+    constexpr const char* instruction_set = "x86_64";
+#else
+    constexpr const char* instruction_set = "unknown";
+#endif
+    // Note: it is OK to reuse the buffer, as the values are exactly the same between
+    //       * compiler-option, used for runtime compilation (DexClassLoader)
+    //       * image-compiler-option, used for boot-image compilation on device
+
+    // Copy the variant.
+    sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
+    parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,
+                        "--instruction-set-variant=", "-Ximage-compiler-option");
+    parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,
+                        "--instruction-set-variant=", "-Xcompiler-option");
+    // Copy the features.
+    sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
+    parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,
+                        "--instruction-set-features=", "-Ximage-compiler-option");
+    parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,
+                        "--instruction-set-features=", "-Xcompiler-option");
+
+
     property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
     parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");
 
@@ -824,6 +871,10 @@
     snprintf(cpuAbiListBuf, sizeof(cpuAbiListBuf), "--cpu-abilist=%s", propBuf);
     addOption(cpuAbiListBuf);
 
+    // Dalvik-cache pruning counter.
+    parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf,
+                       "-Xzygote-max-boot-retry=");
+
     initArgs.version = JNI_VERSION_1_4;
     initArgs.options = mOptions.editArray();
     initArgs.nOptions = mOptions.size();
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp
index 8139c24..8bdbff4 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/core/jni/android/graphics/MinikinUtils.cpp
@@ -26,10 +26,10 @@
 
 namespace android {
 
-void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags, TypefaceImpl* typeface,
-        const uint16_t* buf, size_t start, size_t count, size_t bufSize) {
-    TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
-    layout->setFontCollection(resolvedFace->fFontCollection);
+FontStyle MinikinUtils::prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont,
+        const Paint* paint, TypefaceImpl* typeface) {
+    const TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
+    *pFont = resolvedFace->fFontCollection;
     FontStyle resolved = resolvedFace->fStyle;
 
     /* Prepare minikin FontStyle */
@@ -40,15 +40,26 @@
     FontStyle minikinStyle(minikinLang, minikinVariant, resolved.getWeight(), resolved.getItalic());
 
     /* Prepare minikin Paint */
-    MinikinPaint minikinPaint;
-    minikinPaint.size = (int)/*WHY?!*/paint->getTextSize();
-    minikinPaint.scaleX = paint->getTextScaleX();
-    minikinPaint.skewX = paint->getTextSkewX();
-    minikinPaint.letterSpacing = paint->getLetterSpacing();
-    minikinPaint.paintFlags = MinikinFontSkia::packPaintFlags(paint);
-    minikinPaint.fontFeatureSettings = paint->getFontFeatureSettings();
-    minikinPaint.hyphenEdit = HyphenEdit(paint->getHyphenEdit());
+    // Note: it would be nice to handle fractional size values (it would improve smooth zoom
+    // behavior), but historically size has been treated as an int.
+    // TODO: explore whether to enable fractional sizes, possibly when linear text flag is set.
+    minikinPaint->size = (int)paint->getTextSize();
+    minikinPaint->scaleX = paint->getTextScaleX();
+    minikinPaint->skewX = paint->getTextSkewX();
+    minikinPaint->letterSpacing = paint->getLetterSpacing();
+    minikinPaint->paintFlags = MinikinFontSkia::packPaintFlags(paint);
+    minikinPaint->fontFeatureSettings = paint->getFontFeatureSettings();
+    minikinPaint->hyphenEdit = HyphenEdit(paint->getHyphenEdit());
+    return minikinStyle;
+}
 
+void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags,
+        TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count,
+        size_t bufSize) {
+    FontCollection *font;
+    MinikinPaint minikinPaint;
+    FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
+    layout->setFontCollection(font);
     layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
 }
 
diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h
index 236f1fd..1ee6245 100644
--- a/core/jni/android/graphics/MinikinUtils.h
+++ b/core/jni/android/graphics/MinikinUtils.h
@@ -31,22 +31,14 @@
 
 namespace android {
 
-// TODO: these should be defined in Minikin's Layout.h
-enum {
-    kBidi_LTR = 0,
-    kBidi_RTL = 1,
-    kBidi_Default_LTR = 2,
-    kBidi_Default_RTL = 3,
-    kBidi_Force_LTR = 4,
-    kBidi_Force_RTL = 5,
-
-    kBidi_Mask = 0x7
-};
-
 class MinikinUtils {
 public:
-    static void doLayout(Layout* layout, const Paint* paint, int bidiFlags, TypefaceImpl* typeface,
-            const uint16_t* buf, size_t start, size_t count, size_t bufSize);
+    static FontStyle prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont,
+            const Paint* paint, TypefaceImpl* typeface);
+
+    static void doLayout(Layout* layout, const Paint* paint, int bidiFlags,
+            TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count,
+            size_t bufSize);
 
     static float xOffsetForTextAlign(Paint* paint, const Layout& layout);
 
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index f0131b4..4906f59 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -23,6 +23,7 @@
 #include "GraphicsJNI.h"
 #include "core_jni_helpers.h"
 #include <ScopedUtfChars.h>
+#include <ScopedStringChars.h>
 
 #include "SkBlurDrawLooper.h"
 #include "SkColorFilter.h"
@@ -41,6 +42,8 @@
 #include "Paint.h"
 #include "TypefaceImpl.h"
 
+#include <vector>
+
 // temporary for debugging
 #include <Caches.h>
 #include <utils/Log.h>
@@ -101,6 +104,16 @@
     }
 
     static jlong init(JNIEnv* env, jobject clazz) {
+        SK_COMPILE_ASSERT(1 <<  0 == SkPaint::kAntiAlias_Flag,          paint_flags_mismatch);
+        SK_COMPILE_ASSERT(1 <<  2 == SkPaint::kDither_Flag,             paint_flags_mismatch);
+        SK_COMPILE_ASSERT(1 <<  3 == SkPaint::kUnderlineText_Flag,      paint_flags_mismatch);
+        SK_COMPILE_ASSERT(1 <<  4 == SkPaint::kStrikeThruText_Flag,     paint_flags_mismatch);
+        SK_COMPILE_ASSERT(1 <<  5 == SkPaint::kFakeBoldText_Flag,       paint_flags_mismatch);
+        SK_COMPILE_ASSERT(1 <<  6 == SkPaint::kLinearText_Flag,         paint_flags_mismatch);
+        SK_COMPILE_ASSERT(1 <<  7 == SkPaint::kSubpixelText_Flag,       paint_flags_mismatch);
+        SK_COMPILE_ASSERT(1 <<  8 == SkPaint::kDevKernText_Flag,        paint_flags_mismatch);
+        SK_COMPILE_ASSERT(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, paint_flags_mismatch);
+
         Paint* obj = new Paint();
         defaultSettingsForAndroid(obj);
         return reinterpret_cast<jlong>(obj);
@@ -564,7 +577,8 @@
 
         Layout layout;
         TypefaceImpl* typeface = getNativeTypeface(env, jpaint);
-        MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray, index, count, textLength);
+        MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray + index, 0, count,
+                count);
         result = layout.getAdvance();
         env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
         return result;
@@ -962,6 +976,68 @@
                                       JNI_ABORT);
     }
 
+    static jboolean layoutContainsNotdef(const Layout& layout) {
+        for (size_t i = 0; i < layout.nGlyphs(); i++) {
+            if (layout.getGlyphId(i) == 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static jboolean hasGlyphVariation(const Paint* paint, TypefaceImpl* typeface, jint bidiFlags,
+            const jchar* chars, size_t size) {
+        // TODO: query font for whether character has variation selector; requires a corresponding
+        // function in Minikin.
+        return false;
+    }
+
+    static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jlong typefaceHandle,
+            jint bidiFlags, jstring string) {
+        const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+        TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+        ScopedStringChars str(env, string);
+
+        /* start by rejecting variation selectors (not supported yet) */
+        size_t nChars = 0;
+        for (size_t i = 0; i < str.size(); i++) {
+            jchar c = str[i];
+            if (0xDC00 <= c && c <= 0xDFFF) {
+                // invalid UTF-16, unpaired trailing surrogate
+                return false;
+            } else if (0xD800 <= c && c <= 0xDBFF) {
+                if (i + 1 == str.size()) {
+                    // invalid UTF-16, unpaired leading surrogate at end of string
+                    return false;
+                }
+                i++;
+                jchar c2 = str[i];
+                if (!(0xDC00 <= c2 && c2 <= 0xDFFF)) {
+                    // invalid UTF-16, unpaired leading surrogate
+                    return false;
+                }
+                // UTF-16 encoding of range U+E0100..U+E01EF is DB40 DD00 .. DB40 DDEF
+                if (c == 0xDB40 && 0xDD00 <= c2 && c2 <= 0xDDEF) {
+                    return hasGlyphVariation(paint, typeface, bidiFlags, str.get(), str.size());
+                }
+            } else if (0xFE00 <= c && c <= 0xFE0F) {
+                return hasGlyphVariation(paint, typeface, bidiFlags, str.get(), str.size());
+            }
+            nChars++;
+        }
+        Layout layout;
+        MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, str.get(), 0, str.size(),
+                str.size());
+        size_t nGlyphs = layout.nGlyphs();
+        if (nGlyphs != 1 && nChars > 1) {
+            // multiple-character input, and was not a ligature
+            // TODO: handle ZWJ/ZWNJ characters specially so we can detect certain ligatures
+            // in joining scripts, such as Arabic and Mongolian.
+            return false;
+        }
+        return nGlyphs > 0 && !layoutContainsNotdef(layout);
+    }
+
 };
 
 static JNINativeMethod methods[] = {
@@ -1047,6 +1123,7 @@
                                         (void*) PaintGlue::getStringBounds },
     {"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V",
                                     (void*) PaintGlue::getCharArrayBounds },
+    {"native_hasGlyph",           "(JJILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph },
 
     {"native_setShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer},
     {"native_hasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer}
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index b092e44..e0cbc9e 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -18,7 +18,7 @@
 #include "core_jni_helpers.h"
 
 #include "GraphicsJNI.h"
-#include <ScopedPrimitiveArray.h>
+#include "ScopedPrimitiveArray.h"
 #include "SkTypeface.h"
 #include "TypefaceImpl.h"
 #include <android_runtime/android_util_AssetManager.h>
diff --git a/core/jni/android/graphics/TypefaceImpl.h b/core/jni/android/graphics/TypefaceImpl.h
index d36f83a..4b14917 100644
--- a/core/jni/android/graphics/TypefaceImpl.h
+++ b/core/jni/android/graphics/TypefaceImpl.h
@@ -62,4 +62,4 @@
 
 }
 
-#endif  // _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_
\ No newline at end of file
+#endif  // _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_
diff --git a/core/jni/android_app_backup_FullBackup.cpp b/core/jni/android_app_backup_FullBackup.cpp
index 2c02b37..63b2e2a 100644
--- a/core/jni/android_app_backup_FullBackup.cpp
+++ b/core/jni/android_app_backup_FullBackup.cpp
@@ -15,6 +15,8 @@
  */
 
 #define LOG_TAG "FullBackup_native"
+#include <sys/stat.h>
+
 #include <utils/Log.h>
 #include <utils/String8.h>
 
@@ -30,6 +32,12 @@
 namespace android
 {
 
+// android.app.backup.FullBackupDataOutput
+static struct {
+    jfieldID mData;         // type android.app.backup.BackupDataOutput
+    jmethodID addSize;
+} sFullBackupDataOutput;
+
 // android.app.backup.BackupDataOutput
 static struct {
     // This is actually a native pointer to the underlying BackupDataWriter instance
@@ -70,7 +78,7 @@
  * linkdomain:  where a symlink points for purposes of rewriting; current unused
  * rootpath:    prefix to be snipped from full path when encoding in tar
  * path:        absolute path to the file to be saved
- * dataOutput:  the BackupDataOutput object that we're saving into
+ * dataOutput:  the FullBackupDataOutput object that we're saving into
  */
 static jint backupToTar(JNIEnv* env, jobject clazz, jstring packageNameObj,
         jstring domainObj, jstring linkdomain,
@@ -91,15 +99,11 @@
     if (rootchars) env->ReleaseStringUTFChars(rootpathObj, rootchars);
     if (packagenamechars) env->ReleaseStringUTFChars(packageNameObj, packagenamechars);
 
-    // Extract the data output fd
-    BackupDataWriter* writer = (BackupDataWriter*) env->GetLongField(dataOutputObj,
-            sBackupDataOutput.mBackupWriter);
-
-    // Validate
-    if (!writer) {
-        ALOGE("No output stream provided [%s]", path.string());
-        return (jint) -1;
-    }
+    // Extract the data output fd.  'writer' ends up NULL in the measure-only case.
+    jobject bdo = env->GetObjectField(dataOutputObj, sFullBackupDataOutput.mData);
+    BackupDataWriter* writer = (bdo != NULL)
+            ? (BackupDataWriter*) env->GetLongField(bdo, sBackupDataOutput.mBackupWriter)
+            : NULL;
 
     if (path.length() < rootpath.length()) {
         ALOGE("file path [%s] shorter than root path [%s]",
@@ -107,20 +111,30 @@
         return (jint) -1;
     }
 
-    return (jint) write_tarfile(packageName, domain, rootpath, path, writer);
+    off_t tarSize = 0;
+    jint err = write_tarfile(packageName, domain, rootpath, path, &tarSize, writer);
+    if (!err) {
+        //ALOGI("measured [%s] at %lld", path.string(), (long long) tarSize);
+        env->CallVoidMethod(dataOutputObj, sFullBackupDataOutput.addSize, (jlong) tarSize);
+    }
+
+    return err;
 }
 
 static const JNINativeMethod g_methods[] = {
     { "backupToTar",
-            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/backup/BackupDataOutput;)I",
+            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/backup/FullBackupDataOutput;)I",
             (void*)backupToTar },
 };
 
 int register_android_app_backup_FullBackup(JNIEnv* env)
 {
-    jclass clazz = FindClassOrDie(env, "android/app/backup/BackupDataOutput");
+    jclass fbdoClazz = FindClassOrDie(env, "android/app/backup/FullBackupDataOutput");
+    sFullBackupDataOutput.mData = GetFieldIDOrDie(env, fbdoClazz, "mData", "Landroid/app/backup/BackupDataOutput;");
+    sFullBackupDataOutput.addSize = GetMethodIDOrDie(env, fbdoClazz, "addSize", "(J)V");
 
-    sBackupDataOutput.mBackupWriter = GetFieldIDOrDie(env, clazz, "mBackupWriter", "J");
+    jclass bdoClazz = FindClassOrDie(env, "android/app/backup/BackupDataOutput");
+    sBackupDataOutput.mBackupWriter = GetFieldIDOrDie(env, bdoClazz, "mBackupWriter", "J");
 
     return RegisterMethodsOrDie(env, "android/app/backup/FullBackup", g_methods, NELEM(g_methods));
 }
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 49ee6c5..a2c1609 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -86,20 +86,26 @@
     return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
 }
 
-static void restore(JNIEnv* env, jobject, jlong canvasHandle) {
+static void restore(JNIEnv* env, jobject, jlong canvasHandle, jboolean throwOnUnderflow) {
     Canvas* canvas = get_canvas(canvasHandle);
     if (canvas->getSaveCount() <= 1) {  // cannot restore anymore
-        // fail silently on underflow, so as not to break existing apps that miscount
-        return;
+        if (throwOnUnderflow) {
+            doThrowISE(env, "Underflow in restore - more restores than saves");
+        }
+        return; // compat behavior - return without throwing
     }
     canvas->restore();
 }
 
-static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount) {
+static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount,
+        jboolean throwOnUnderflow) {
     Canvas* canvas = get_canvas(canvasHandle);
     if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
-        // fail silently on underflow, so as not to break existing apps that miscount
-        return;
+        if (throwOnUnderflow) {
+            doThrowIAE(env, "Underflow in restoreToCount - more restores than saves");
+            return;
+        }
+        restoreCount = 1; // compat behavior - restore as far as possible
     }
     canvas->restoreToCount(restoreCount);
 }
@@ -661,8 +667,8 @@
     {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
     {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
     {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
-    {"native_restore","(J)V", (void*) CanvasJNI::restore},
-    {"native_restoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
+    {"native_restore","(JZ)V", (void*) CanvasJNI::restore},
+    {"native_restoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount},
     {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
     {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
     {"native_concat","(JJ)V", (void*) CanvasJNI::concat},
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 0b737a7..7d12230 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -18,6 +18,8 @@
 
 #include <map>
 
+#include <ScopedUtfChars.h>
+
 #include <utils/Log.h>
 #include <utils/Looper.h>
 
@@ -99,6 +101,9 @@
         if (string1 == NULL) {
             return string2 != NULL;
         }
+        if (string2 == NULL) {
+            return false;
+        }
         return string1->compare(*string2) < 0;
     }
 };
@@ -264,9 +269,12 @@
     }
 };
 
-static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ, jfloatArray scratch) {
+static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ,
+        jfloatArray scratch, jstring packageName) {
     SensorManager& mgr(SensorManager::getInstance());
-    sp<SensorEventQueue> queue(mgr.createEventQueue());
+    ScopedUtfChars packageUtf(env, packageName);
+    String8 clientName(packageUtf.c_str());
+    sp<SensorEventQueue> queue(mgr.createEventQueue(clientName));
 
     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
     if (messageQueue == NULL) {
@@ -280,10 +288,11 @@
 }
 
 static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
-                               jint maxBatchReportLatency, jint reservedFlags) {
+                               jint maxBatchReportLatency) {
     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
+
     return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
-                                                         reservedFlags);
+                                                         0);
 }
 
 static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
@@ -316,11 +325,11 @@
 
 static JNINativeMethod gBaseEventQueueMethods[] = {
     {"nativeInitBaseEventQueue",
-            "(Landroid/hardware/SystemSensorManager$BaseEventQueue;Landroid/os/MessageQueue;[F)J",
-            (void*)nativeInitSensorEventQueue },
+     "(Landroid/hardware/SystemSensorManager$BaseEventQueue;Landroid/os/MessageQueue;[FLjava/lang/String;)J",
+     (void*)nativeInitSensorEventQueue },
 
     {"nativeEnableSensor",
-            "(JIIII)I",
+            "(JIII)I",
             (void*)nativeEnableSensor },
 
     {"nativeDisableSensor",
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index 807dd32..32b5b02 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -25,6 +25,8 @@
 #define ENCODING_PCM_FLOAT  4
 #define ENCODING_AC3        5
 #define ENCODING_E_AC3      6
+#define ENCODING_DTS        7
+#define ENCODING_DTS_HD     8
 #define ENCODING_INVALID    0
 #define ENCODING_DEFAULT    1
 
@@ -46,6 +48,10 @@
         return AUDIO_FORMAT_AC3;
     case ENCODING_E_AC3:
         return AUDIO_FORMAT_E_AC3;
+    case ENCODING_DTS:
+        return AUDIO_FORMAT_DTS;
+    case ENCODING_DTS_HD:
+        return AUDIO_FORMAT_DTS_HD;
     case ENCODING_DEFAULT:
         return AUDIO_FORMAT_DEFAULT;
     default:
@@ -66,6 +72,10 @@
         return ENCODING_AC3;
     case AUDIO_FORMAT_E_AC3:
         return ENCODING_E_AC3;
+    case AUDIO_FORMAT_DTS:
+        return ENCODING_DTS;
+    case AUDIO_FORMAT_DTS_HD:
+        return ENCODING_DTS_HD;
     case AUDIO_FORMAT_DEFAULT:
         return ENCODING_DEFAULT;
     default:
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 4a98f27..fc05a6d 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -142,7 +142,14 @@
 
 static const char* const kEventHandlerClassPathName =
         "android/media/AudioPortEventHandler";
-static jmethodID gPostEventFromNative;
+static struct {
+    jfieldID    mJniCallback;
+} gEventHandlerFields;
+static struct {
+    jmethodID    postEventFromNative;
+} gAudioPortEventHandlerMethods;
+
+static Mutex gLock;
 
 enum AudioError {
     kAudioStatusOk = 0,
@@ -173,14 +180,14 @@
 private:
     void sendEvent(int event);
 
-    jclass      mClass;     // Reference to AudioPortEventHandlerDelegate class
-    jobject     mObject;    // Weak ref to AudioPortEventHandlerDelegate Java object to call on
+    jclass      mClass;     // Reference to AudioPortEventHandler class
+    jobject     mObject;    // Weak ref to AudioPortEventHandler Java object to call on
 };
 
 JNIAudioPortCallback::JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
 {
 
-    // Hold onto the SoundTriggerModule class for use in calling the static method
+    // Hold onto the AudioPortEventHandler class for use in calling the static method
     // that posts events to the application thread.
     jclass clazz = env->GetObjectClass(thiz);
     if (clazz == NULL) {
@@ -189,7 +196,7 @@
     }
     mClass = (jclass)env->NewGlobalRef(clazz);
 
-    // We use a weak reference so the SoundTriggerModule object can be garbage collected.
+    // We use a weak reference so the AudioPortEventHandler object can be garbage collected.
     // The reference is only used as a proxy for callbacks.
     mObject  = env->NewGlobalRef(weak_thiz);
 }
@@ -211,7 +218,7 @@
     if (env == NULL) {
         return;
     }
-    env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
+    env->CallStaticVoidMethod(mClass, gAudioPortEventHandlerMethods.postEventFromNative, mObject,
                               event, 0, 0, NULL);
     if (env->ExceptionCheck()) {
         ALOGW("An exception occurred while notifying an event.");
@@ -234,6 +241,23 @@
     sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
 }
 
+static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env,
+                                       jobject thiz,
+                                       const sp<JNIAudioPortCallback>& callback)
+{
+    Mutex::Autolock l(gLock);
+    sp<JNIAudioPortCallback> old =
+            (JNIAudioPortCallback*)env->GetLongField(thiz, gEventHandlerFields.mJniCallback);
+    if (callback.get()) {
+        callback->incStrong((void*)setJniCallback);
+    }
+    if (old != 0) {
+        old->decStrong((void*)setJniCallback);
+    }
+    env->SetLongField(thiz, gEventHandlerFields.mJniCallback, (jlong)callback.get());
+    return old;
+}
+
 static int check_AudioSystem_Command(status_t status)
 {
     switch (status) {
@@ -1355,7 +1379,9 @@
 
     sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
 
-    AudioSystem::setAudioPortCallback(callback);
+    if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {
+        setJniCallback(env, thiz, callback);
+    }
 }
 
 static void
@@ -1363,9 +1389,11 @@
 {
     ALOGV("eventHandlerFinalize");
 
-    sp<JNIAudioPortCallback> callback;
+    sp<JNIAudioPortCallback> callback = setJniCallback(env, thiz, 0);
 
-    AudioSystem::setAudioPortCallback(callback);
+    if (callback != 0) {
+        AudioSystem::removeAudioPortCallback(callback);
+    }
 }
 
 static jint
@@ -1636,9 +1664,11 @@
                                                 "Landroid/media/AudioHandle;");
 
     jclass eventHandlerClass = FindClassOrDie(env, kEventHandlerClassPathName);
-    gPostEventFromNative = GetStaticMethodIDOrDie(env, eventHandlerClass, "postEventFromNative",
-                                                  "(Ljava/lang/Object;IIILjava/lang/Object;)V");
-
+    gAudioPortEventHandlerMethods.postEventFromNative = GetStaticMethodIDOrDie(
+                                                    env, eventHandlerClass, "postEventFromNative",
+                                                    "(Ljava/lang/Object;IIILjava/lang/Object;)V");
+    gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env,
+                                                    eventHandlerClass, "mJniCallback", "J");
 
     jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
     gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index a7a925f..5552245 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -17,6 +17,8 @@
 
 #define LOG_TAG "AudioTrack-JNI"
 
+#include "android_media_AudioTrack.h"
+
 #include <JNIHelp.h>
 #include <JniConstants.h>
 #include "core_jni_helpers.h"
@@ -181,6 +183,12 @@
     env->SetLongField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, (jlong)at.get());
     return old;
 }
+
+// ----------------------------------------------------------------------------
+sp<AudioTrack> android_media_AudioTrack_getAudioTrack(JNIEnv* env, jobject audioTrackObj) {
+    return getAudioTrack(env, audioTrackObj);
+}
+
 // ----------------------------------------------------------------------------
 static jint
 android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
diff --git a/core/jni/android_media_AudioTrack.h b/core/jni/android_media_AudioTrack.h
new file mode 100644
index 0000000..ef2aa66
--- /dev/null
+++ b/core/jni/android_media_AudioTrack.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_MEDIA_AUDIOTRACK_H
+#define ANDROID_MEDIA_AUDIOTRACK_H
+
+#include "jni.h"
+
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+class AudioTrack;
+
+}; // namespace android
+
+/* Gets the underlying AudioTrack from an AudioTrack Java object. */
+extern android::sp<android::AudioTrack> android_media_AudioTrack_getAudioTrack(
+        JNIEnv* env, jobject audioTrackObj);
+
+#endif // ANDROID_MEDIA_AUDIOTRACK_H
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index 8800f0b..87c58d6 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -21,6 +21,7 @@
 #include "unicode/brkiter.h"
 #include "utils/misc.h"
 #include "utils/Log.h"
+#include "ScopedStringChars.h"
 #include "ScopedPrimitiveArray.h"
 #include "JNIHelp.h"
 #include "core_jni_helpers.h"
@@ -34,6 +35,7 @@
 #include "MinikinSkia.h"
 #include "MinikinUtils.h"
 #include "Paint.h"
+#include "minikin/LineBreaker.h"
 
 namespace android {
 
@@ -46,636 +48,119 @@
 static jclass gLineBreaks_class;
 static JLineBreaksID gLineBreaks_fieldID;
 
-class Builder {
-    public:
-        ~Builder() {
-            utext_close(&mUText);
-            delete mBreakIterator;
-        }
+// set text and set a number of parameters for creating a layout (width, tabstops, strategy)
+static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length,
+        jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth,
+        jintArray variableTabStops, jint defaultTabStop, jint strategy) {
+    LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr);
+    b->resize(length);
+    env->GetCharArrayRegion(text, 0, length, b->buffer());
+    b->setText();
+    b->setLineWidths(firstWidth, firstWidthLineLimit, restWidth);
+    if (variableTabStops == nullptr) {
+        b->setTabStops(nullptr, 0, defaultTabStop);
+    } else {
+        ScopedIntArrayRO stops(env, variableTabStops);
+        b->setTabStops(stops.get(), stops.size(), defaultTabStop);
+    }
+    b->setStrategy(static_cast<BreakStrategy>(strategy));
+}
 
-        void setLocale(const icu::Locale& locale) {
-            delete mBreakIterator;
-            UErrorCode status = U_ZERO_ERROR;
-            mBreakIterator = icu::BreakIterator::createLineInstance(locale, status);
-            // TODO: check status
-        }
-
-        void resize(size_t size) {
-            mTextBuf.resize(size);
-            mWidthBuf.resize(size);
-        }
-
-        size_t size() const {
-            return mTextBuf.size();
-        }
-
-        uint16_t* buffer() {
-            return mTextBuf.data();
-        }
-
-        float* widths() {
-            return mWidthBuf.data();
-        }
-
-        // set text to current contents of buffer
-        void setText() {
-            UErrorCode status = U_ZERO_ERROR;
-            utext_openUChars(&mUText, mTextBuf.data(), mTextBuf.size(), &status);
-            mBreakIterator->setText(&mUText, status);
-        }
-
-        void finish() {
-            if (mTextBuf.size() > MAX_TEXT_BUF_RETAIN) {
-                mTextBuf.clear();
-                mTextBuf.shrink_to_fit();
-                mWidthBuf.clear();
-                mWidthBuf.shrink_to_fit();
-            }
-        }
-
-        icu::BreakIterator* breakIterator() const {
-            return mBreakIterator;
-        }
-
-        float measureStyleRun(Paint* paint, TypefaceImpl* typeface, size_t start, size_t end,
-                bool isRtl);
-
-        void addReplacement(size_t start, size_t end, float width);
-
-    private:
-        const size_t MAX_TEXT_BUF_RETAIN = 32678;
-        icu::BreakIterator* mBreakIterator = nullptr;
-        UText mUText = UTEXT_INITIALIZER;
-        std::vector<uint16_t>mTextBuf;
-        std::vector<float>mWidthBuf;
-};
-
-static const int CHAR_SPACE = 0x20;
-static const int CHAR_TAB = 0x09;
-static const int CHAR_NEWLINE = 0x0a;
-static const int CHAR_ZWSP = 0x200b;
-
-class TabStops {
-    public:
-        // specified stops must be a sorted array (allowed to be null)
-        TabStops(JNIEnv* env, jintArray stops, jint defaultTabWidth) :
-            mStops(env), mTabWidth(defaultTabWidth) {
-                if (stops != nullptr) {
-                    mStops.reset(stops);
-                    mNumStops = mStops.size();
-                } else {
-                    mNumStops = 0;
-                }
-            }
-        float width(float widthSoFar) const {
-            const jint* mStopsArray = mStops.get();
-            for (int i = 0; i < mNumStops; i++) {
-                if (mStopsArray[i] > widthSoFar) {
-                    return mStopsArray[i];
-                }
-            }
-            // find the next tabstop after widthSoFar
-            return static_cast<int>((widthSoFar + mTabWidth) / mTabWidth) * mTabWidth;
-        }
-    private:
-        ScopedIntArrayRO mStops;
-        const int mTabWidth;
-        int mNumStops;
-
-        // disable copying and assignment
-        TabStops(const TabStops&);
-        void operator=(const TabStops&);
-};
-
-enum PrimitiveType {
-    kPrimitiveType_Box,
-    kPrimitiveType_Glue,
-    kPrimitiveType_Penalty,
-    kPrimitiveType_Variable,
-    kPrimitiveType_Wordbreak
-};
-
-static const float PENALTY_INFINITY = 1e7; // forced non-break, negative infinity is forced break
-
-struct Primitive {
-    PrimitiveType type;
-    int location;
-    // 'Box' has width
-    // 'Glue' has width
-    // 'Penalty' has width and penalty
-    // 'Variable' has tabStop
-    // 'Wordbreak' has penalty
-    union {
-        struct {
-            float width;
-            float penalty;
-        };
-        const TabStops* tabStop;
-    };
-};
-
-class LineWidth {
-    public:
-        LineWidth(float firstWidth, int firstWidthLineCount, float restWidth) :
-                mFirstWidth(firstWidth), mFirstWidthLineCount(firstWidthLineCount),
-                mRestWidth(restWidth) {}
-        float getLineWidth(int line) const {
-            return (line < mFirstWidthLineCount) ? mFirstWidth : mRestWidth;
-        }
-    private:
-        const float mFirstWidth;
-        const int mFirstWidthLineCount;
-        const float mRestWidth;
-};
-
-class LineBreaker {
-    public:
-        LineBreaker(const std::vector<Primitive>& primitives,
-                    const LineWidth& lineWidth) :
-                mPrimitives(primitives), mLineWidth(lineWidth) {}
-        virtual ~LineBreaker() {}
-        virtual void computeBreaks(std::vector<int>* breaks, std::vector<float>* widths,
-                                   std::vector<unsigned char>* flags) const = 0;
-    protected:
-        const std::vector<Primitive>& mPrimitives;
-        const LineWidth& mLineWidth;
-};
-
-class OptimizingLineBreaker : public LineBreaker {
-    public:
-        OptimizingLineBreaker(const std::vector<Primitive>& primitives, const LineWidth& lineWidth) :
-                LineBreaker(primitives, lineWidth) {}
-        void computeBreaks(std::vector<int>* breaks, std::vector<float>* widths,
-                           std::vector<unsigned char>* flags) const {
-            int numBreaks = mPrimitives.size();
-            Node* opt = new Node[numBreaks];
-            opt[0].prev = -1;
-            opt[0].prevCount = 0;
-            opt[0].width = 0;
-            opt[0].demerits = 0;
-            opt[0].flags = false;
-            opt[numBreaks - 1].prev = -1;
-            opt[numBreaks - 1].prevCount = 0;
-
-            std::list<int> active;
-            active.push_back(0);
-            int lastBreak = 0;
-            for (int i = 0; i < numBreaks; i++) {
-                const Primitive& p = mPrimitives[i];
-                if (p.type == kPrimitiveType_Penalty) {
-                    const bool finalBreak = (i + 1 == numBreaks);
-                    bool breakFound = false;
-                    Node bestBreak;
-                    for (std::list<int>::iterator it = active.begin(); it != active.end(); /* incrementing done in loop */) {
-                        const int pos = *it;
-                        bool flags;
-                        float width, printedWidth;
-                        const int lines = opt[pos].prevCount;
-                        const float maxWidth = mLineWidth.getLineWidth(lines);
-                        // we have to compute metrics every time --
-                        // we can't really precompute this stuff and just deal with breaks
-                        // because of the way tab characters work, this makes it computationally
-                        // harder, but this way, we can still optimize while treating tab characters
-                        // correctly
-                        computeMetrics(pos, i, &width, &printedWidth, &flags);
-                        if (printedWidth <= maxWidth) {
-                            float demerits = computeDemerits(maxWidth, printedWidth,
-                                    finalBreak, p.penalty) + opt[pos].demerits;
-                            if (!breakFound || demerits < bestBreak.demerits) {
-                                bestBreak.prev = pos;
-                                bestBreak.prevCount = opt[pos].prevCount + 1;
-                                bestBreak.demerits = demerits;
-                                bestBreak.width = printedWidth;
-                                bestBreak.flags = flags;
-                                breakFound = true;
-                            }
-                            ++it;
-                        } else {
-                            active.erase(it++); // safe to delete like this
-                        }
-                    }
-                    if (p.penalty == -PENALTY_INFINITY) {
-                        active.clear();
-                    }
-                    if (breakFound) {
-                        opt[i] = bestBreak;
-                        active.push_back(i);
-                        lastBreak = i;
-                    }
-                    if (active.empty()) {
-                        // we can't give up!
-                        float width, printedWidth;
-                        bool flags;
-                        const int lines = opt[lastBreak].prevCount;
-                        const float maxWidth = mLineWidth.getLineWidth(lines);
-                        const int breakIndex = desperateBreak(lastBreak, numBreaks, maxWidth, &width, &printedWidth, &flags);
-
-                        opt[breakIndex].prev = lastBreak;
-                        opt[breakIndex].prevCount = lines + 1;
-                        opt[breakIndex].demerits = 0; // doesn't matter, it's the only one
-                        opt[breakIndex].width = width;
-                        opt[breakIndex].flags = flags;
-
-                        active.push_back(breakIndex);
-                        lastBreak = breakIndex;
-                        i = breakIndex; // incremented by i++
-                    }
-                }
-            }
-
-            int idx = numBreaks - 1;
-            int count = opt[idx].prevCount;
-            breaks->resize(count);
-            widths->resize(count);
-            flags->resize(count);
-            while (opt[idx].prev != -1) {
-                --count;
-
-                (*breaks)[count] = mPrimitives[idx].location;
-                (*widths)[count] = opt[idx].width;
-                (*flags)[count] = opt[idx].flags;
-
-                idx = opt[idx].prev;
-            }
-            delete[] opt;
-        }
-    private:
-        inline void computeMetrics(int start, int end, float* width, float* printedWidth, bool* flags) const {
-            bool f = false;
-            float w = 0, pw = 0;
-            for (int i = start; i < end; i++) {
-                const Primitive& p = mPrimitives[i];
-                if (p.type == kPrimitiveType_Box || p.type == kPrimitiveType_Glue) {
-                    w += p.width;
-                    if (p.type == kPrimitiveType_Box) {
-                        pw = w;
-                    }
-                } else if (p.type == kPrimitiveType_Variable) {
-                    w = p.tabStop->width(w);
-                    f = true;
-                }
-            }
-            *width = w;
-            *printedWidth = pw;
-            *flags = f;
-        }
-
-        inline float computeDemerits(float maxWidth, float width, bool finalBreak, float penalty) const {
-            float deviation = finalBreak ? 0 : maxWidth - width;
-            return (deviation * deviation) + penalty;
-        }
-
-        // returns end pos (chosen break), -1 if fail
-        inline int desperateBreak(int start, int limit, float maxWidth, float* width, float* printedWidth, bool* flags) const {
-            float w = 0, pw = 0;
-            bool breakFound = false;
-            int breakIndex = 0, firstTabIndex = INT_MAX;
-            for (int i = start; i < limit; i++) {
-                const Primitive& p = mPrimitives[i];
-
-                if (p.type == kPrimitiveType_Box || p.type == kPrimitiveType_Glue) {
-                    w += p.width;
-                    if (p.type == kPrimitiveType_Box) {
-                        pw = w;
-                    }
-                } else if (p.type == kPrimitiveType_Variable) {
-                    w = p.tabStop->width(w);
-                    firstTabIndex = std::min(firstTabIndex, i);
-                }
-
-                if (pw > maxWidth) {
-                    if (breakFound) {
-                        break;
-                    } else {
-                        // no choice, keep going
-                    }
-                }
-
-                // must make progress
-                if (i > start && (p.type == kPrimitiveType_Penalty || p.type == kPrimitiveType_Wordbreak)) {
-                    breakFound = true;
-                    breakIndex = i;
-                }
-            }
-
-            if (breakFound) {
-                *width = w;
-                *printedWidth = pw;
-                *flags = (start <= firstTabIndex && firstTabIndex < breakIndex);
-                return breakIndex;
-            } else {
-                return -1;
-            }
-        }
-
-        struct Node {
-            int prev; // set to sentinel value (-1) for initial node
-            int prevCount; // number of breaks so far
-            float demerits;
-            float width;
-            bool flags;
-        };
-};
-
-class GreedyLineBreaker : public LineBreaker {
-    public:
-        GreedyLineBreaker(const std::vector<Primitive>& primitives, const LineWidth& lineWidth) :
-            LineBreaker(primitives, lineWidth) {}
-        void computeBreaks(std::vector<int>* breaks, std::vector<float>* widths,
-                           std::vector<unsigned char>* flags) const {
-            int lineNum = 0;
-            float width = 0, printedWidth = 0;
-            bool breakFound = false, goodBreakFound = false;
-            int breakIndex = 0, goodBreakIndex = 0;
-            float breakWidth = 0, goodBreakWidth = 0;
-            int firstTabIndex = INT_MAX;
-
-            float maxWidth = mLineWidth.getLineWidth(lineNum);
-
-            const int numPrimitives = mPrimitives.size();
-            // greedily fit as many characters as possible on each line
-            // loop over all primitives, and choose the best break point
-            // (if possible, a break point without splitting a word)
-            // after going over the maximum length
-            for (int i = 0; i < numPrimitives; i++) {
-                const Primitive& p = mPrimitives[i];
-
-                // update the current line width
-                if (p.type == kPrimitiveType_Box || p.type == kPrimitiveType_Glue) {
-                    width += p.width;
-                    if (p.type == kPrimitiveType_Box) {
-                        printedWidth = width;
-                    }
-                } else if (p.type == kPrimitiveType_Variable) {
-                    width = p.tabStop->width(width);
-                    // keep track of first tab character in the region we are examining
-                    // so we can determine whether or not a line contains a tab
-                    firstTabIndex = std::min(firstTabIndex, i);
-                }
-
-                // find the best break point for the characters examined so far
-                if (printedWidth > maxWidth) {
-                    if (breakFound || goodBreakFound) {
-                        if (goodBreakFound) {
-                            // a true line break opportunity existed in the characters examined so far,
-                            // so there is no need to split a word
-                            i = goodBreakIndex; // no +1 because of i++
-                            lineNum++;
-                            maxWidth = mLineWidth.getLineWidth(lineNum);
-                            breaks->push_back(mPrimitives[goodBreakIndex].location);
-                            widths->push_back(goodBreakWidth);
-                            flags->push_back(firstTabIndex < goodBreakIndex);
-                            firstTabIndex = INT_MAX;
-                        } else {
-                            // must split a word because there is no other option
-                            i = breakIndex; // no +1 because of i++
-                            lineNum++;
-                            maxWidth = mLineWidth.getLineWidth(lineNum);
-                            breaks->push_back(mPrimitives[breakIndex].location);
-                            widths->push_back(breakWidth);
-                            flags->push_back(firstTabIndex < breakIndex);
-                            firstTabIndex = INT_MAX;
-                        }
-                        printedWidth = width = 0;
-                        goodBreakFound = breakFound = false;
-                        goodBreakWidth = breakWidth = 0;
-                        continue;
-                    } else {
-                        // no choice, keep going... must make progress by putting at least one
-                        // character on a line, even if part of that character is cut off --
-                        // there is no other option
-                    }
-                }
-
-                // update possible break points
-                if (p.type == kPrimitiveType_Penalty && p.penalty < PENALTY_INFINITY) {
-                    // this does not handle penalties with width
-
-                    // handle forced line break
-                    if (p.penalty == -PENALTY_INFINITY) {
-                        lineNum++;
-                        maxWidth = mLineWidth.getLineWidth(lineNum);
-                        breaks->push_back(p.location);
-                        widths->push_back(printedWidth);
-                        flags->push_back(firstTabIndex < i);
-                        firstTabIndex = INT_MAX;
-                        printedWidth = width = 0;
-                        goodBreakFound = breakFound = false;
-                        goodBreakWidth = breakWidth = 0;
-                        continue;
-                    }
-                    if (i > breakIndex && (printedWidth <= maxWidth || breakFound == false)) {
-                        breakFound = true;
-                        breakIndex = i;
-                        breakWidth = printedWidth;
-                    }
-                    if (i > goodBreakIndex && printedWidth <= maxWidth) {
-                        goodBreakFound = true;
-                        goodBreakIndex = i;
-                        goodBreakWidth = printedWidth;
-                    }
-                } else if (p.type == kPrimitiveType_Wordbreak) {
-                    // only do this if necessary -- we don't want to break words
-                    // when possible, but sometimes it is unavoidable
-                    if (i > breakIndex && (printedWidth <= maxWidth || breakFound == false)) {
-                        breakFound = true;
-                        breakIndex = i;
-                        breakWidth = printedWidth;
-                    }
-                }
-            }
-
-            if (breakFound || goodBreakFound) {
-                // output last break if there are more characters to output
-                if (goodBreakFound) {
-                    breaks->push_back(mPrimitives[goodBreakIndex].location);
-                    widths->push_back(goodBreakWidth);
-                    flags->push_back(firstTabIndex < goodBreakIndex);
-                } else {
-                    breaks->push_back(mPrimitives[breakIndex].location);
-                    widths->push_back(breakWidth);
-                    flags->push_back(firstTabIndex < breakIndex);
-                }
-            }
-        }
-};
-
-static jint recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks,
-                        jfloatArray recycleWidths, jbooleanArray recycleFlags,
-                        jint recycleLength, const std::vector<jint>& breaks,
-                        const std::vector<jfloat>& widths, const std::vector<jboolean>& flags) {
-    int bufferLength = breaks.size();
-    if (recycleLength < bufferLength) {
+static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks,
+                        jfloatArray recycleWidths, jintArray recycleFlags,
+                        jint recycleLength, size_t nBreaks, const jint* breaks,
+                        const jfloat* widths, const jint* flags) {
+    if ((size_t)recycleLength < nBreaks) {
         // have to reallocate buffers
-        recycleBreaks = env->NewIntArray(bufferLength);
-        recycleWidths = env->NewFloatArray(bufferLength);
-        recycleFlags = env->NewBooleanArray(bufferLength);
+        recycleBreaks = env->NewIntArray(nBreaks);
+        recycleWidths = env->NewFloatArray(nBreaks);
+        recycleFlags = env->NewIntArray(nBreaks);
 
         env->SetObjectField(recycle, gLineBreaks_fieldID.breaks, recycleBreaks);
         env->SetObjectField(recycle, gLineBreaks_fieldID.widths, recycleWidths);
         env->SetObjectField(recycle, gLineBreaks_fieldID.flags, recycleFlags);
     }
     // copy data
-    env->SetIntArrayRegion(recycleBreaks, 0, breaks.size(), &breaks.front());
-    env->SetFloatArrayRegion(recycleWidths, 0, widths.size(), &widths.front());
-    env->SetBooleanArrayRegion(recycleFlags, 0, flags.size(), &flags.front());
-
-    return bufferLength;
-}
-
-void computePrimitives(const jchar* textArr, const jfloat* widthsArr, jint length, const std::vector<int>& breaks,
-                       const TabStops& tabStopCalculator, std::vector<Primitive>* primitives) {
-    int breaksSize = breaks.size();
-    int breakIndex = 0;
-    Primitive p;
-    for (int i = 0; i < length; i++) {
-        p.location = i;
-        jchar c = textArr[i];
-        if (c == CHAR_SPACE || c == CHAR_ZWSP) {
-            p.type = kPrimitiveType_Glue;
-            p.width = widthsArr[i];
-            primitives->push_back(p);
-        } else if (c == CHAR_TAB) {
-            p.type = kPrimitiveType_Variable;
-            p.tabStop = &tabStopCalculator; // shared between all variable primitives
-            primitives->push_back(p);
-        } else if (c != CHAR_NEWLINE) {
-            while (breakIndex < breaksSize && breaks[breakIndex] < i) breakIndex++;
-            p.width = 0;
-            if (breakIndex < breaksSize && breaks[breakIndex] == i) {
-                p.type = kPrimitiveType_Penalty;
-                p.penalty = 0;
-            } else {
-                p.type = kPrimitiveType_Wordbreak;
-            }
-            if (widthsArr[i] != 0) {
-                primitives->push_back(p);
-            }
-
-            p.type = kPrimitiveType_Box;
-            p.width = widthsArr[i];
-            primitives->push_back(p);
-        }
-    }
-    // final break at end of everything
-    p.location = length;
-    p.type = kPrimitiveType_Penalty;
-    p.width = 0;
-    p.penalty = -PENALTY_INFINITY;
-    primitives->push_back(p);
-}
-
-// sets the text on the builder
-static void nSetText(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, int length) {
-    Builder* b = reinterpret_cast<Builder*>(nativePtr);
-    b->resize(length);
-    env->GetCharArrayRegion(text, 0, length, b->buffer());
-    b->setText();
+    env->SetIntArrayRegion(recycleBreaks, 0, nBreaks, breaks);
+    env->SetFloatArrayRegion(recycleWidths, 0, nBreaks, widths);
+    env->SetIntArrayRegion(recycleFlags, 0, nBreaks, flags);
 }
 
 static jint nComputeLineBreaks(JNIEnv* env, jclass, jlong nativePtr,
-                               jint length,
-                               jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth,
-                               jintArray variableTabStops, jint defaultTabStop, jboolean optimize,
                                jobject recycle, jintArray recycleBreaks,
-                               jfloatArray recycleWidths, jbooleanArray recycleFlags,
+                               jfloatArray recycleWidths, jintArray recycleFlags,
                                jint recycleLength) {
-    Builder* b = reinterpret_cast<Builder*>(nativePtr);
+    LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr);
 
-    std::vector<int> breaks;
+    size_t nBreaks = b->computeBreaks();
 
-    icu::BreakIterator* breakIterator = b->breakIterator();
-    int loc = breakIterator->first();
-    while ((loc = breakIterator->next()) != icu::BreakIterator::DONE) {
-        breaks.push_back(loc);
-    }
+    recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleFlags, recycleLength,
+            nBreaks, b->getBreaks(), b->getWidths(), b->getFlags());
 
-    // TODO: all these allocations can be moved into the builder
-    std::vector<Primitive> primitives;
-    TabStops tabStops(env, variableTabStops, defaultTabStop);
-    computePrimitives(b->buffer(), b->widths(), length, breaks, tabStops, &primitives);
-
-    LineWidth lineWidth(firstWidth, firstWidthLineLimit, restWidth);
-    std::vector<int> computedBreaks;
-    std::vector<float> computedWidths;
-    std::vector<unsigned char> computedFlags;
-
-    if (optimize) {
-        OptimizingLineBreaker breaker(primitives, lineWidth);
-        breaker.computeBreaks(&computedBreaks, &computedWidths, &computedFlags);
-    } else {
-        GreedyLineBreaker breaker(primitives, lineWidth);
-        breaker.computeBreaks(&computedBreaks, &computedWidths, &computedFlags);
-    }
     b->finish();
 
-    return recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleFlags, recycleLength,
-            computedBreaks, computedWidths, computedFlags);
+    return static_cast<jint>(nBreaks);
 }
 
 static jlong nNewBuilder(JNIEnv*, jclass) {
-    return reinterpret_cast<jlong>(new Builder);
+    return reinterpret_cast<jlong>(new LineBreaker);
 }
 
 static void nFreeBuilder(JNIEnv*, jclass, jlong nativePtr) {
-    delete reinterpret_cast<Builder*>(nativePtr);
+    delete reinterpret_cast<LineBreaker*>(nativePtr);
 }
 
 static void nFinishBuilder(JNIEnv*, jclass, jlong nativePtr) {
-    Builder* b = reinterpret_cast<Builder*>(nativePtr);
+    LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr);
     b->finish();
 }
 
-static void nSetLocale(JNIEnv* env, jclass, jlong nativePtr, jstring javaLocaleName) {
+static jlong nLoadHyphenator(JNIEnv* env, jclass, jstring patternData) {
+    ScopedStringChars str(env, patternData);
+    Hyphenator* hyphenator = Hyphenator::load(str.get(), str.size());
+    return reinterpret_cast<jlong>(hyphenator);
+}
+
+static void nSetLocale(JNIEnv* env, jclass, jlong nativePtr, jstring javaLocaleName,
+        jlong nativeHyphenator) {
     ScopedIcuLocale icuLocale(env, javaLocaleName);
-    Builder* b = reinterpret_cast<Builder*>(nativePtr);
+    LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr);
+    Hyphenator* hyphenator = reinterpret_cast<Hyphenator*>(nativeHyphenator);
 
     if (icuLocale.valid()) {
-        b->setLocale(icuLocale.locale());
+        b->setLocale(icuLocale.locale(), hyphenator);
     }
 }
 
-float Builder::measureStyleRun(Paint* paint, TypefaceImpl* typeface, size_t start, size_t end,
-        bool isRtl) {
-    Layout layout;
-    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
-    // TODO: should we provide more context?
-    MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, mTextBuf.data() + start, 0,
-            end - start, end - start);
-    layout.getAdvances(mWidthBuf.data() + start);
-    return layout.getAdvance();
-}
-
-void Builder::addReplacement(size_t start, size_t end, float width) {
-    mWidthBuf[start] = width;
-    std::fill(&mWidthBuf[start + 1], &mWidthBuf[end], 0.0f);
-}
-
 // Basically similar to Paint.getTextRunAdvances but with C++ interface
 static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr,
         jlong nativePaint, jlong nativeTypeface, jint start, jint end, jboolean isRtl) {
-    Builder* b = reinterpret_cast<Builder*>(nativePtr);
+    LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr);
     Paint* paint = reinterpret_cast<Paint*>(nativePaint);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(nativeTypeface);
-    return b->measureStyleRun(paint, typeface, start, end, isRtl);
+    FontCollection *font;
+    MinikinPaint minikinPaint;
+    FontStyle style = MinikinUtils::prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
+    return b->addStyleRun(&minikinPaint, font, style, start, end, isRtl);
 }
 
 // Accept width measurements for the run, passed in from Java
 static void nAddMeasuredRun(JNIEnv* env, jclass, jlong nativePtr,
         jint start, jint end, jfloatArray widths) {
-    Builder* b = reinterpret_cast<Builder*>(nativePtr);
-    env->GetFloatArrayRegion(widths, start, end - start, b->widths() + start);
+    LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr);
+    env->GetFloatArrayRegion(widths, start, end - start, b->charWidths() + start);
+    b->addStyleRun(nullptr, nullptr, FontStyle{}, start, end, false);
 }
 
 static void nAddReplacementRun(JNIEnv* env, jclass, jlong nativePtr,
         jint start, jint end, jfloat width) {
-    Builder* b = reinterpret_cast<Builder*>(nativePtr);
+    LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr);
     b->addReplacement(start, end, width);
 }
 
 static void nGetWidths(JNIEnv* env, jclass, jlong nativePtr, jfloatArray widths) {
-    Builder* b = reinterpret_cast<Builder*>(nativePtr);
-    env->SetFloatArrayRegion(widths, 0, b->size(), b->widths());
+    LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr);
+    env->SetFloatArrayRegion(widths, 0, b->size(), b->charWidths());
 }
 
 static JNINativeMethod gMethods[] = {
@@ -683,13 +168,14 @@
     {"nNewBuilder", "()J", (void*) nNewBuilder},
     {"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
     {"nFinishBuilder", "(J)V", (void*) nFinishBuilder},
-    {"nSetLocale", "(JLjava/lang/String;)V", (void*) nSetLocale},
-    {"nSetText", "(J[CI)V", (void*) nSetText},
+    {"nLoadHyphenator", "(Ljava/lang/String;)J", (void*) nLoadHyphenator},
+    {"nSetLocale", "(JLjava/lang/String;J)V", (void*) nSetLocale},
+    {"nSetupParagraph", "(J[CIFIF[III)V", (void*) nSetupParagraph},
     {"nAddStyleRun", "(JJJIIZ)F", (void*) nAddStyleRun},
     {"nAddMeasuredRun", "(JII[F)V", (void*) nAddMeasuredRun},
     {"nAddReplacementRun", "(JIIF)V", (void*) nAddReplacementRun},
     {"nGetWidths", "(J[F)V", (void*) nGetWidths},
-    {"nComputeLineBreaks", "(JIFIF[IIZLandroid/text/StaticLayout$LineBreaks;[I[F[ZI)I",
+    {"nComputeLineBreaks", "(JLandroid/text/StaticLayout$LineBreaks;[I[F[II)I",
         (void*) nComputeLineBreaks}
 };
 
@@ -700,7 +186,7 @@
 
     gLineBreaks_fieldID.breaks = GetFieldIDOrDie(env, gLineBreaks_class, "breaks", "[I");
     gLineBreaks_fieldID.widths = GetFieldIDOrDie(env, gLineBreaks_class, "widths", "[F");
-    gLineBreaks_fieldID.flags = GetFieldIDOrDie(env, gLineBreaks_class, "flags", "[Z");
+    gLineBreaks_fieldID.flags = GetFieldIDOrDie(env, gLineBreaks_class, "flags", "[I");
 
     return RegisterMethodsOrDie(env, "android/text/StaticLayout", gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index fff8604..f1c90ea 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -192,6 +192,9 @@
         case HAL_PIXEL_FORMAT_YCbCr_422_I:
             // Name differs, though the value is the same
             return PublicFormat::YUY2;
+        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+            // Name differs, though the value is the same
+            return PublicFormat::PRIVATE;
         case HAL_PIXEL_FORMAT_Y16:
             // Dataspace-dependent
             switch (dataSpace) {
@@ -216,7 +219,6 @@
             break;
         case HAL_PIXEL_FORMAT_BGRA_8888:
         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
-        case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
             // Not defined in public API
             return PublicFormat::UNKNOWN;
 
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 3d9a9ed..11b3805 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -21,6 +21,7 @@
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 #include "core_jni_helpers.h"
+#include <ScopedPrimitiveArray.h>
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
@@ -35,6 +36,7 @@
 #include <Animator.h>
 #include <AnimationContext.h>
 #include <IContextFactory.h>
+#include <JankTracker.h>
 #include <RenderNode.h>
 #include <renderthread/CanvasContext.h>
 #include <renderthread/RenderProxy.h>
@@ -219,6 +221,12 @@
     proxy->setTextureAtlas(buffer, map, len);
 }
 
+static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jint fd) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    proxy->setProcessStatsBuffer(fd);
+}
+
 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
     RootRenderNode* node = new RootRenderNode(env);
     node->incStrong(0);
@@ -403,6 +411,16 @@
     proxy->dumpProfileInfo(fd, dumpFlags);
 }
 
+static void android_view_ThreadedRenderer_dumpProfileData(JNIEnv* env, jobject clazz,
+        jbyteArray jdata, jobject javaFileDescriptor) {
+    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
+    ScopedByteArrayRO buffer(env, jdata);
+    if (buffer.get()) {
+        JankTracker::dumpBuffer(buffer.get(), buffer.size(), fd);
+    }
+}
+
+
 // ----------------------------------------------------------------------------
 // Shaders
 // ----------------------------------------------------------------------------
@@ -423,6 +441,7 @@
 
 static JNINativeMethod gMethods[] = {
     { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
+    { "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
     { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
     { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
     { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
@@ -449,6 +468,7 @@
     { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
     { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
     { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
+    { "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
     { "setupShadersDiskCache", "(Ljava/lang/String;)V",
                 (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
 };
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 2bfeadb..76db5d3 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -65,9 +65,7 @@
 // Must match values in com.android.internal.os.Zygote.
 enum MountExternalKind {
   MOUNT_EXTERNAL_NONE = 0,
-  MOUNT_EXTERNAL_SINGLEUSER = 1,
-  MOUNT_EXTERNAL_MULTIUSER = 2,
-  MOUNT_EXTERNAL_MULTIUSER_ALL = 3,
+  MOUNT_EXTERNAL_DEFAULT = 1,
 };
 
 static void RuntimeAbort(JNIEnv* env) {
@@ -269,57 +267,16 @@
   // See storage config details at http://source.android.com/tech/storage/
   userid_t user_id = multiuser_get_user_id(uid);
 
-  // Create bind mounts to expose external storage
-  if (mount_mode == MOUNT_EXTERNAL_MULTIUSER || mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
-    // These paths must already be created by init.rc
-    const char* source = getenv("EMULATED_STORAGE_SOURCE");
-    const char* target = getenv("EMULATED_STORAGE_TARGET");
-    const char* legacy = getenv("EXTERNAL_STORAGE");
-    if (source == NULL || target == NULL || legacy == NULL) {
-      ALOGW("Storage environment undefined; unable to provide external storage");
-      return false;
-    }
+  // Bind mount user-specific storage into place
+  const String8 source(String8::format("/mnt/user/%d", user_id));
+  const String8 target(String8::format("/storage/self"));
 
-    // Prepare source paths
+  if (fs_prepare_dir(source.string(), 0755, 0, 0) == -1) {
+    return false;
+  }
 
-    // /mnt/shell/emulated/0
-    const String8 source_user(String8::format("%s/%d", source, user_id));
-    // /storage/emulated/0
-    const String8 target_user(String8::format("%s/%d", target, user_id));
-
-    if (fs_prepare_dir(source_user.string(), 0000, 0, 0) == -1
-        || fs_prepare_dir(target_user.string(), 0000, 0, 0) == -1) {
-      return false;
-    }
-
-    if (mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
-      // Mount entire external storage tree for all users
-      if (TEMP_FAILURE_RETRY(mount(source, target, NULL, MS_BIND, NULL)) == -1) {
-        ALOGW("Failed to mount %s to %s: %s", source, target, strerror(errno));
-        return false;
-      }
-    } else {
-      // Only mount user-specific external storage
-      if (TEMP_FAILURE_RETRY(mount(source_user.string(), target_user.string(), NULL,
-                                   MS_BIND, NULL)) == -1) {
-        ALOGW("Failed to mount %s to %s: %s", source_user.string(), target_user.string(),
-              strerror(errno));
-        return false;
-      }
-    }
-
-    if (fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
-        return false;
-    }
-
-    // Finally, mount user-specific path into place for legacy users
-    if (TEMP_FAILURE_RETRY(
-            mount(target_user.string(), legacy, NULL, MS_BIND | MS_REC, NULL)) == -1) {
-      ALOGW("Failed to mount %s to %s: %s", target_user.string(), legacy, strerror(errno));
-      return false;
-    }
-  } else {
-    ALOGW("Mount mode %d unsupported", mount_mode);
+  if (TEMP_FAILURE_RETRY(mount(source.string(), target.string(), NULL, MS_BIND, NULL)) == -1) {
+    ALOGW("Failed to mount %s to %s: %s", source.string(), target.string(), strerror(errno));
     return false;
   }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4d6b5f6..f427f2b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -73,10 +73,13 @@
     <protected-broadcast android:name="android.intent.action.USER_BACKGROUND" />
     <protected-broadcast android:name="android.intent.action.USER_FOREGROUND" />
     <protected-broadcast android:name="android.intent.action.USER_SWITCHED" />
+    <protected-broadcast android:name="android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION" />
 
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
 
+    <protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" />
+
     <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE" />
     <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE" />
     <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" />
@@ -1218,6 +1221,14 @@
         android:label="@string/permlab_cameraDisableTransmitLed"
         android:description="@string/permdesc_cameraDisableTransmitLed" />
 
+    <!-- Allows sending the camera service notifications about system-wide events.
+        @hide -->
+    <permission android:name="android.permission.CAMERA_SEND_SYSTEM_EVENTS"
+        android:permissionGroup="android.permission-group.CAMERA"
+        android:protectionLevel="signature|system"
+        android:label="@string/permdesc_cameraSendSystemEvent"
+        android:description="@string/permdesc_cameraSendSystemEvent" />
+
     <!-- =========================================== -->
     <!-- Permissions associated with telephony state -->
     <!-- =========================================== -->
@@ -2590,6 +2601,12 @@
         android:description="@string/permdesc_performCdmaProvisioning"
         android:protectionLevel="signature|system" />
 
+    <!-- @SystemApi Allows an application to perform SIM Activation @hide -->
+    <permission android:name="android.permission.PERFORM_SIM_ACTIVATION"
+        android:label="@string/permlab_performSimActivation"
+        android:description="@string/permdesc_performSimActivation"
+        android:protectionLevel="signature|system" />
+
     <!-- @SystemApi Allows enabling/disabling location update notifications from
          the radio.
          <p>Not for use by third-party applications. -->
@@ -2607,7 +2624,8 @@
         android:protectionLevel="signature|system" />
 
     <!-- @SystemApi Allows an application to collect component usage
-         statistics @hide -->
+         statistics
+         <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.PACKAGE_USAGE_STATS"
         android:label="@string/permlab_pkgUsageStats"
         android:description="@string/permdesc_pkgUsageStats"
@@ -2796,6 +2814,23 @@
         android:description="@string/permdesc_bindPackageVerifier"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi @hide Intent filter verifier needs to have this permission before the
+         PackageManager will trust it to verify intent filters.
+    -->
+    <permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"
+        android:label="@string/permlab_intentFilterVerificationAgent"
+        android:description="@string/permdesc_intentFilterVerificationAgent"
+        android:protectionLevel="signature|system" />
+
+    <!-- Must be required by intent filter verifier receiver, to ensure that only the
+         system can interact with it.
+         @hide
+    -->
+    <permission android:name="android.permission.BIND_INTENT_FILTER_VERIFIER"
+        android:label="@string/permlab_bindIntentFilterVerifier"
+        android:description="@string/permdesc_bindIntentFilterVerifier"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows applications to access serial ports via the SerialManager.
          @hide -->
     <permission android:name="android.permission.SERIAL_PORT"
@@ -2974,6 +3009,14 @@
         android:description="@string/permdesc_bindCarrierMessagingService"
         android:protectionLevel="signature|system" />
 
+    <!-- Allows an application to interact with the currently active
+         {@link android.service.voice.VoiceInteractionService}.
+         @hide -->
+    <permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE"
+        android:protectionLevel="signature"
+        android:description="@string/permdesc_accessVoiceInteractionService"
+        android:label="@string/permlab_accessVoiceInteractionService" />
+
     <!-- The system process is explicitly the only one allowed to launch the
          confirmation UI for full backup/restore -->
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
@@ -3158,9 +3201,9 @@
             </intent-filter>
         </receiver>
 
-        <receiver android:name="com.android.server.updates.TZInfoInstallReceiver" >
+        <receiver android:name="com.android.server.updates.TzDataInstallReceiver" >
             <intent-filter>
-                <action android:name="android.intent.action.UPDATE_TZINFO" />
+                <action android:name="android.intent.action.UPDATE_TZDATA" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
diff --git a/core/res/res/anim/ic_checkbox_checked_box_inner_merged_animation.xml b/core/res/res/anim/ic_checkbox_checked_box_inner_merged_animation.xml
new file mode 100644
index 0000000..7be32af
--- /dev/null
+++ b/core/res/res/anim/ic_checkbox_checked_box_inner_merged_animation.xml
@@ -0,0 +1,52 @@
+<?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.
+-->
+
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="166"
+            android:propertyName="pathData"
+            android:valueFrom="M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+            android:valueTo="M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+            android:valueType="pathType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="pathData"
+            android:valueFrom="M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+            android:valueTo="M -7.0,-7.0 l 14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+            android:valueType="pathType"
+            android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="133"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="33"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_0" />
+    </set>
+</set>
diff --git a/core/res/res/anim/ic_checkbox_checked_check_path_merged_animation.xml b/core/res/res/anim/ic_checkbox_checked_check_path_merged_animation.xml
new file mode 100644
index 0000000..fcba2c8
--- /dev/null
+++ b/core/res/res/anim/ic_checkbox_checked_check_path_merged_animation.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="166"
+        android:propertyName="pathData"
+        android:valueFrom="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -5.0,-5.00001525879 -5.0,-5.00001525879 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 3.58590698242,3.58601379395 3.58590698242,3.58601379395 c 0.0,0.0 7.58590698242,-7.58601379395 7.58590698242,-7.58601379395 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -9.0,9.00001525879 -9.0,9.00001525879 Z"
+        android:valueTo="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M 0.0,1.42500305176 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" />
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="133"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1.0"
+            android:valueTo="1.0"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="33"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1.0"
+            android:valueTo="0.0"
+            android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_0" />
+    </set>
+</set>
diff --git a/core/res/res/anim/ic_checkbox_checked_icon_null_animation.xml b/core/res/res/anim/ic_checkbox_checked_icon_null_animation.xml
new file mode 100644
index 0000000..312003f
--- /dev/null
+++ b/core/res/res/anim/ic_checkbox_checked_icon_null_animation.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="166"
+            android:propertyName="scaleX"
+            android:valueFrom="0.2"
+            android:valueTo="0.18"
+            android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleX"
+            android:valueFrom="0.18"
+            android:valueTo="0.2"
+            android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="166"
+            android:propertyName="scaleY"
+            android:valueFrom="0.2"
+            android:valueTo="0.18"
+            android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleY"
+            android:valueFrom="0.18"
+            android:valueTo="0.2"
+            android:interpolator="@interpolator/ic_checkbox_checked_animation_interpolator_1" />
+    </set>
+</set>
diff --git a/core/res/res/anim/ic_checkbox_unchecked_box_inner_merged_animation.xml b/core/res/res/anim/ic_checkbox_unchecked_box_inner_merged_animation.xml
new file mode 100644
index 0000000..b5ad5e9d
--- /dev/null
+++ b/core/res/res/anim/ic_checkbox_unchecked_box_inner_merged_animation.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="166"
+        android:propertyName="pathData"
+        android:valueFrom="M -7.0,-7.0 l 14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueTo="M 0.0,-0.05 l 0.0,0.0 c 0.02761423749,0.0 0.05,0.02238576251 0.05,0.05 l 0.0,0.0 c 0.0,0.02761423749 -0.02238576251,0.05 -0.05,0.05 l 0.0,0.0 c -0.02761423749,0.0 -0.05,-0.02238576251 -0.05,-0.05 l 0.0,0.0 c 0.0,-0.02761423749 0.02238576251,-0.05 0.05,-0.05 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+        android:valueType="pathType"
+        android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" />
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="166"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1.0"
+            android:valueTo="1.0"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="33"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1.0"
+            android:valueTo="0.0"
+            android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_0" />
+    </set>
+</set>
diff --git a/core/res/res/anim/ic_checkbox_unchecked_box_outer_merged_animation.xml b/core/res/res/anim/ic_checkbox_unchecked_box_outer_merged_animation.xml
new file mode 100644
index 0000000..066971a
--- /dev/null
+++ b/core/res/res/anim/ic_checkbox_unchecked_box_outer_merged_animation.xml
@@ -0,0 +1,52 @@
+<?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.
+-->
+
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="pathData"
+            android:valueFrom="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z"
+            android:valueTo="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z"
+            android:valueType="pathType"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="300"
+            android:propertyName="pathData"
+            android:valueFrom="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z"
+            android:valueTo="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -5.0,-5.00001525879 -5.0,-5.00001525879 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 3.58590698242,3.58601379395 3.58590698242,3.58601379395 c 0.0,0.0 7.58590698242,-7.58601379395 7.58590698242,-7.58601379395 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -9.0,9.00001525879 -9.0,9.00001525879 Z"
+            android:valueType="pathType"
+            android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="166"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0.0"
+            android:valueTo="0.0"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="33"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0.0"
+            android:valueTo="1.0"
+            android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_0" />
+    </set>
+</set>
diff --git a/core/res/res/anim/ic_checkbox_unchecked_icon_null_animation.xml b/core/res/res/anim/ic_checkbox_unchecked_icon_null_animation.xml
new file mode 100644
index 0000000..fc40d47
--- /dev/null
+++ b/core/res/res/anim/ic_checkbox_unchecked_icon_null_animation.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="scaleX"
+            android:valueFrom="0.2"
+            android:valueTo="0.18"
+            android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" />
+        <objectAnimator
+            android:duration="300"
+            android:propertyName="scaleX"
+            android:valueFrom="0.18"
+            android:valueTo="0.2"
+            android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="scaleY"
+            android:valueFrom="0.2"
+            android:valueTo="0.18"
+            android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" />
+        <objectAnimator
+            android:duration="300"
+            android:propertyName="scaleY"
+            android:valueFrom="0.18"
+            android:valueTo="0.2"
+            android:interpolator="@interpolator/ic_checkbox_unchecked_animation_interpolator_1" />
+    </set>
+</set>
diff --git a/core/res/res/color/primary_text_secondary_when_activated_material.xml b/core/res/res/color/primary_text_secondary_when_activated_material.xml
new file mode 100644
index 0000000..7ab4a2e
--- /dev/null
+++ b/core/res/res/color/primary_text_secondary_when_activated_material.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_activated="true"
+        android:color="?attr/textColorPrimary" />
+    <item
+        android:color="?attr/textColorSecondary" />
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color/date_picker_header_text_material.xml b/core/res/res/color/primary_text_secondary_when_activated_material_inverse.xml
similarity index 100%
rename from core/res/res/color/date_picker_header_text_material.xml
rename to core/res/res/color/primary_text_secondary_when_activated_material_inverse.xml
diff --git a/core/res/res/color/time_picker_header_text_material.xml b/core/res/res/color/time_picker_header_text_material.xml
deleted file mode 100644
index cda894b..0000000
--- a/core/res/res/color/time_picker_header_text_material.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item
-        android:state_selected="true"
-        android:color="?attr/textColorPrimaryInverse" />
-    <item
-        android:color="?attr/textColorSecondaryInverse" />
-</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_000.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_000.png
deleted file mode 100644
index 3cb4073..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_001.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_001.png
deleted file mode 100644
index 8fd1480..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_002.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_002.png
deleted file mode 100644
index d35b579..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_003.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_003.png
deleted file mode 100644
index 543c6bc..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_004.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_004.png
deleted file mode 100644
index 4fc3c40..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_005.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_005.png
deleted file mode 100644
index c184535..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_006.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_006.png
deleted file mode 100644
index 9f9dd43..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_007.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_007.png
deleted file mode 100644
index 8c629ce..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_008.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_008.png
deleted file mode 100644
index 81134b5..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_009.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_009.png
deleted file mode 100644
index baa5860..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_010.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_010.png
deleted file mode 100644
index d7e28366..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_011.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_011.png
deleted file mode 100644
index 6f24795..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_012.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_012.png
deleted file mode 100644
index 22f997d..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_013.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_013.png
deleted file mode 100644
index 85f4471..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_014.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_014.png
deleted file mode 100644
index ad483c9..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_015.png b/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_015.png
deleted file mode 100644
index f24c2fb..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_off_mtrl_015.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_000.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_000.png
deleted file mode 100644
index 7a9e9bd..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_001.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_001.png
deleted file mode 100644
index af04902..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_002.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_002.png
deleted file mode 100644
index 32a6e94..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_003.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_003.png
deleted file mode 100644
index c1b4b37..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_004.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_004.png
deleted file mode 100644
index 34d3ade..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_005.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_005.png
deleted file mode 100644
index 3d5db53..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_006.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_006.png
deleted file mode 100644
index ea35437..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_007.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_007.png
deleted file mode 100644
index 48744f8..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_008.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_008.png
deleted file mode 100644
index f654517..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_009.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_009.png
deleted file mode 100644
index 16f959a..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_010.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_010.png
deleted file mode 100644
index 98c754b..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_011.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_011.png
deleted file mode 100644
index 5827dc2..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_012.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_012.png
deleted file mode 100644
index 9850d74..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_013.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_013.png
deleted file mode 100644
index 03ab06b..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_014.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_014.png
deleted file mode 100644
index 11cdd88..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_015.png b/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_015.png
deleted file mode 100644
index 874edbf..0000000
--- a/core/res/res/drawable-hdpi/btn_check_to_on_mtrl_015.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_divider_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/list_divider_mtrl_alpha.9.png
deleted file mode 100644
index 2fa6d7e..0000000
--- a/core/res/res/drawable-hdpi/list_divider_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_000.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_000.png
deleted file mode 100644
index 9759818..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_001.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_001.png
deleted file mode 100644
index 4eb2c4f..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_002.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_002.png
deleted file mode 100644
index e6d6b42..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_003.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_003.png
deleted file mode 100644
index 03cb23a..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_004.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_004.png
deleted file mode 100644
index bfe3c3d..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_005.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_005.png
deleted file mode 100644
index 65bdf42..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_006.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_006.png
deleted file mode 100644
index 44f9614b..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_007.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_007.png
deleted file mode 100644
index cf8ec38..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_008.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_008.png
deleted file mode 100644
index 4d624b3..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_009.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_009.png
deleted file mode 100644
index 7c4eb7f..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_010.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_010.png
deleted file mode 100644
index e90dd31..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_011.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_011.png
deleted file mode 100644
index 831c0e8..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_012.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_012.png
deleted file mode 100644
index 7355dfd..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_013.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_013.png
deleted file mode 100644
index be71a69..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_014.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_014.png
deleted file mode 100644
index a4a185b..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_015.png b/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_015.png
deleted file mode 100644
index 8d0386f..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_off_mtrl_015.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_000.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_000.png
deleted file mode 100644
index 70793c4..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_001.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_001.png
deleted file mode 100644
index 632082b..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_002.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_002.png
deleted file mode 100644
index e7fc5fb..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_003.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_003.png
deleted file mode 100644
index 91a0a33..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_004.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_004.png
deleted file mode 100644
index 3bd90d6..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_005.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_005.png
deleted file mode 100644
index 5ac39ec..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_006.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_006.png
deleted file mode 100644
index 4181983..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_007.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_007.png
deleted file mode 100644
index c8b04df..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_008.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_008.png
deleted file mode 100644
index b7b3a9f..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_009.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_009.png
deleted file mode 100644
index 62bc4ed..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_010.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_010.png
deleted file mode 100644
index ac463ad..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_011.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_011.png
deleted file mode 100644
index 12b605d..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_012.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_012.png
deleted file mode 100644
index 63a3c6a..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_013.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_013.png
deleted file mode 100644
index 17660c4..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_014.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_014.png
deleted file mode 100644
index 7d9de3d..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_015.png b/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_015.png
deleted file mode 100644
index 8aa1be2..0000000
--- a/core/res/res/drawable-mdpi/btn_check_to_on_mtrl_015.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_divider_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/list_divider_mtrl_alpha.9.png
deleted file mode 100644
index 070bdbf..0000000
--- a/core/res/res/drawable-mdpi/list_divider_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_000.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_000.png
deleted file mode 100644
index 2347643..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_001.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_001.png
deleted file mode 100644
index 70aaa01..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_002.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_002.png
deleted file mode 100644
index 01e498a..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_003.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_003.png
deleted file mode 100644
index 71d1cf7..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_004.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_004.png
deleted file mode 100644
index d1e7b1d..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_005.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_005.png
deleted file mode 100644
index 7db7d06..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_006.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_006.png
deleted file mode 100644
index dadb62e..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_007.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_007.png
deleted file mode 100644
index f87f744..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_008.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_008.png
deleted file mode 100644
index be99d87..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_009.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_009.png
deleted file mode 100644
index f83bc05..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_010.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_010.png
deleted file mode 100644
index 870071d..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_011.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_011.png
deleted file mode 100644
index 3a18414..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_012.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_012.png
deleted file mode 100644
index f3d1187..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_013.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_013.png
deleted file mode 100644
index 4078cca..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_014.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_014.png
deleted file mode 100644
index d4849b5..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_015.png b/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_015.png
deleted file mode 100644
index 6e2af72..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_off_mtrl_015.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_000.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_000.png
deleted file mode 100644
index 9244174..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_001.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_001.png
deleted file mode 100644
index 8c7fe95..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_002.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_002.png
deleted file mode 100644
index 71eb1d0..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_003.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_003.png
deleted file mode 100644
index 613f38a..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_004.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_004.png
deleted file mode 100644
index 2d20ccc..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_005.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_005.png
deleted file mode 100644
index 407f78d..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_006.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_006.png
deleted file mode 100644
index 1bf24b0..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_007.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_007.png
deleted file mode 100644
index a450bd0..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_008.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_008.png
deleted file mode 100644
index 63ba593..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_009.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_009.png
deleted file mode 100644
index 6d05e5a..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_010.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_010.png
deleted file mode 100644
index 1c8cd8f..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_011.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_011.png
deleted file mode 100644
index b8bc564..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_012.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_012.png
deleted file mode 100644
index 3d80128..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_013.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_013.png
deleted file mode 100644
index c21dfba..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_014.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_014.png
deleted file mode 100644
index 2dfe90d..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_015.png b/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_015.png
deleted file mode 100644
index 5f40d73..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_to_on_mtrl_015.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_divider_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/list_divider_mtrl_alpha.9.png
deleted file mode 100644
index 0d2836d..0000000
--- a/core/res/res/drawable-xhdpi/list_divider_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_000.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_000.png
deleted file mode 100644
index b754381..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_001.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_001.png
deleted file mode 100644
index 517d7a7..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_002.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_002.png
deleted file mode 100644
index 2c1d5b6..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_003.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_003.png
deleted file mode 100644
index 0c6ff7e..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_004.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_004.png
deleted file mode 100644
index 0796601..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_005.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_005.png
deleted file mode 100644
index 9b4e0f8..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_006.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_006.png
deleted file mode 100644
index 25767eb..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_007.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_007.png
deleted file mode 100644
index cd0951f..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_008.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_008.png
deleted file mode 100644
index 9ae8165..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_009.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_009.png
deleted file mode 100644
index efd9bc6..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_010.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_010.png
deleted file mode 100644
index fccbc9d..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_011.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_011.png
deleted file mode 100644
index dddafca..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_012.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_012.png
deleted file mode 100644
index 7e37433..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_013.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_013.png
deleted file mode 100644
index 9bc22de..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_014.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_014.png
deleted file mode 100644
index 507ed10..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_015.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_015.png
deleted file mode 100644
index 6a21c7f..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_off_mtrl_015.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_000.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_000.png
deleted file mode 100644
index 0d544d9..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_001.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_001.png
deleted file mode 100644
index 39da0ac..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_002.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_002.png
deleted file mode 100644
index d5ada12..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_003.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_003.png
deleted file mode 100644
index d4e096c..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_004.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_004.png
deleted file mode 100644
index 468a9b4..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_005.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_005.png
deleted file mode 100644
index ea3cd2e..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_006.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_006.png
deleted file mode 100644
index 0652cb0..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_007.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_007.png
deleted file mode 100644
index 768d2b0..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_008.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_008.png
deleted file mode 100644
index 1d06a90..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_009.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_009.png
deleted file mode 100644
index 8a70a80..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_010.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_010.png
deleted file mode 100644
index bf9ec7f..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_011.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_011.png
deleted file mode 100644
index cff07b9..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_012.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_012.png
deleted file mode 100644
index 40f997e..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_013.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_013.png
deleted file mode 100644
index 6ba84ec..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_014.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_014.png
deleted file mode 100644
index 766610e..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_015.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_015.png
deleted file mode 100644
index 810a029..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_to_on_mtrl_015.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_divider_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/list_divider_mtrl_alpha.9.png
deleted file mode 100644
index b8ac46d..0000000
--- a/core/res/res/drawable-xxhdpi/list_divider_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_000.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_000.png
deleted file mode 100644
index f0ff1a7..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_001.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_001.png
deleted file mode 100644
index b382df3..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_002.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_002.png
deleted file mode 100644
index 8cb4ce2..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_003.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_003.png
deleted file mode 100644
index 4db2b01..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_004.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_004.png
deleted file mode 100644
index 8c4709b..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_005.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_005.png
deleted file mode 100644
index 1ad960a..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_006.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_006.png
deleted file mode 100644
index e47cc20..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_007.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_007.png
deleted file mode 100644
index c4d0d51..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_008.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_008.png
deleted file mode 100644
index 915d56a..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_009.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_009.png
deleted file mode 100644
index 85795cb..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_010.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_010.png
deleted file mode 100644
index 157fd91..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_011.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_011.png
deleted file mode 100644
index 9d446de..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_012.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_012.png
deleted file mode 100644
index dfac1f0..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_013.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_013.png
deleted file mode 100644
index aed6c08..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_014.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_014.png
deleted file mode 100644
index 1b8bd6b..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_015.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_015.png
deleted file mode 100644
index 5dd0e5b..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_off_mtrl_015.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_000.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_000.png
deleted file mode 100644
index 5dd0e5b..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_000.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_001.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_001.png
deleted file mode 100644
index 1a31ad9..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_001.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_002.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_002.png
deleted file mode 100644
index 63c7f12..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_002.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_003.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_003.png
deleted file mode 100644
index 847dd08..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_003.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_004.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_004.png
deleted file mode 100644
index b93f3cc..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_004.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_005.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_005.png
deleted file mode 100644
index 1e3dea7..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_005.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_006.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_006.png
deleted file mode 100644
index 5a85238..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_006.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_007.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_007.png
deleted file mode 100644
index 35960ca..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_007.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_008.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_008.png
deleted file mode 100644
index 6db5555..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_008.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_009.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_009.png
deleted file mode 100644
index a9c5851..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_009.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_010.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_010.png
deleted file mode 100644
index 38465bd..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_010.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_011.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_011.png
deleted file mode 100644
index 15942dc..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_011.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_012.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_012.png
deleted file mode 100644
index 67d0d64..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_012.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_013.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_013.png
deleted file mode 100644
index 69b5c1b..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_013.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_014.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_014.png
deleted file mode 100644
index 0e5d331..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_014.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_015.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_015.png
deleted file mode 100644
index f0ff1a7..0000000
--- a/core/res/res/drawable-xxxhdpi/btn_check_to_on_mtrl_015.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/btn_check_material_anim.xml b/core/res/res/drawable/btn_check_material_anim.xml
index 24df879..41caa4e 100644
--- a/core/res/res/drawable/btn_check_material_anim.xml
+++ b/core/res/res/drawable/btn_check_material_anim.xml
@@ -15,159 +15,15 @@
 -->
 
 <animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:state_checked="true">
-        <bitmap android:src="@drawable/btn_check_to_on_mtrl_015"
-                android:tint="?attr/colorControlNormal"
-                android:alpha="?attr/disabledAlpha" />
-    </item>
-    <item android:state_enabled="false">
-        <bitmap android:src="@drawable/btn_check_to_on_mtrl_000"
-                android:tint="?attr/colorControlNormal"
-                android:alpha="?attr/disabledAlpha" />
-    </item>
-    <item android:state_checked="true" android:id="@+id/on">
-        <bitmap android:src="@drawable/btn_check_to_on_mtrl_015"
-                android:tint="?attr/colorControlActivated" />
-    </item>
-    <item android:id="@+id/off">
-        <bitmap android:src="@drawable/btn_check_to_on_mtrl_000"
-                android:tint="?attr/colorControlNormal" />
-    </item>
-    <transition android:fromId="@+id/off" android:toId="@+id/on">
-        <animation-list>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_000"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_001"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_002"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_003"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_004"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_005"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_006"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_007"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_008"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_009"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_010"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_011"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_012"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_013"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_014"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_on_mtrl_015"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-        </animation-list>
-    </transition>
-    <transition android:fromId="@+id/on" android:toId="@+id/off">
-        <animation-list>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_000"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_001"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_002"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_003"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_004"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_005"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_006"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_007"
-                        android:tint="?attr/colorControlActivated" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_008"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_009"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_010"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_011"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_012"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_013"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_014"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-            <item android:duration="15">
-                <bitmap android:src="@drawable/btn_check_to_off_mtrl_015"
-                        android:tint="?attr/colorControlNormal" />
-            </item>
-        </animation-list>
-    </transition>
+    <item android:state_checked="true" android:id="@+id/on"
+        android:drawable="@drawable/ic_checkbox_checked" />
+    <item android:id="@+id/off"
+        android:drawable="@drawable/ic_checkbox_unchecked" />
+
+    <transition android:fromId="@+id/off" android:toId="@+id/on"
+        android:drawable="@drawable/ic_checkbox_unchecked_animation" />
+
+    <transition android:fromId="@+id/on" android:toId="@+id/off"
+        android:drawable="@drawable/ic_checkbox_checked_animation" />
 </animated-selector>
 
diff --git a/core/res/res/drawable/ic_check_circle_24px.xml b/core/res/res/drawable/ic_check_circle_24px.xml
new file mode 100644
index 0000000..066a8a7
--- /dev/null
+++ b/core/res/res/drawable/ic_check_circle_24px.xml
@@ -0,0 +1,27 @@
+<!--
+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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M0 0h24v24H0z"
+        android:fillColor="#00000000"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12.0,2.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zm-2.0,15.0l-5.0,-5.0 1.41,-1.41L10.0,14.17l7.59,-7.59L19.0,8.0l-9.0,9.0z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_checkbox_checked.xml b/core/res/res/drawable/ic_checkbox_checked.xml
new file mode 100644
index 0000000..4764115
--- /dev/null
+++ b/core/res/res/drawable/ic_checkbox_checked.xml
@@ -0,0 +1,52 @@
+<?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:name="ic_checkbox_checked"
+    android:width="32dp"
+    android:viewportWidth="48"
+    android:height="32dp"
+    android:viewportHeight="48"
+    android:tint="?attr/colorControlNormal" >
+    <group
+        android:name="icon_null"
+        android:translateX="24"
+        android:translateY="24"
+        android:scaleX="0.2"
+        android:scaleY="0.2" >
+        <group
+            android:name="check"
+            android:scaleX="7.5"
+            android:scaleY="7.5" >
+            <path
+                android:name="check_path_merged"
+                android:pathData="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -5.0,-5.00001525879 -5.0,-5.00001525879 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 3.58590698242,3.58601379395 3.58590698242,3.58601379395 c 0.0,0.0 7.58590698242,-7.58601379395 7.58590698242,-7.58601379395 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -9.0,9.00001525879 -9.0,9.00001525879 Z"
+                android:fillColor="#FF000000" />
+        </group>
+        <group
+            android:name="box_dilate"
+            android:scaleX="7.5"
+            android:scaleY="7.5" >
+            <path
+                android:name="box_inner_merged"
+                android:pathData="M 0.0,-1.0 l 0.0,0.0 c 0.5522847498,0.0 1.0,0.4477152502 1.0,1.0 l 0.0,0.0 c 0.0,0.5522847498 -0.4477152502,1.0 -1.0,1.0 l 0.0,0.0 c -0.5522847498,0.0 -1.0,-0.4477152502 -1.0,-1.0 l 0.0,0.0 c 0.0,-0.5522847498 0.4477152502,-1.0 1.0,-1.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+                android:fillColor="#FF000000"
+                android:fillAlpha="0" />
+        </group>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/ic_checkbox_checked_animation.xml b/core/res/res/drawable/ic_checkbox_checked_animation.xml
new file mode 100644
index 0000000..af5eeee
--- /dev/null
+++ b/core/res/res/drawable/ic_checkbox_checked_animation.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+
+<animated-vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/ic_checkbox_checked" >
+    <target
+        android:name="icon_null"
+        android:animation="@anim/ic_checkbox_checked_icon_null_animation" />
+    <target
+        android:name="check_path_merged"
+        android:animation="@anim/ic_checkbox_checked_check_path_merged_animation" />
+    <target
+        android:name="box_inner_merged"
+        android:animation="@anim/ic_checkbox_checked_box_inner_merged_animation" />
+</animated-vector>
diff --git a/core/res/res/drawable/ic_checkbox_unchecked.xml b/core/res/res/drawable/ic_checkbox_unchecked.xml
new file mode 100644
index 0000000..410f0bc
--- /dev/null
+++ b/core/res/res/drawable/ic_checkbox_unchecked.xml
@@ -0,0 +1,52 @@
+<?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:name="ic_checkbox_unchecked"
+    android:width="32dp"
+    android:viewportWidth="48"
+    android:height="32dp"
+    android:viewportHeight="48"
+    android:tint="?attr/colorControlNormal" >
+    <group
+        android:name="icon_null"
+        android:translateX="24"
+        android:translateY="24"
+        android:scaleX="0.2"
+        android:scaleY="0.2" >
+        <group
+            android:name="check"
+            android:scaleX="7.5"
+            android:scaleY="7.5" >
+            <path
+                android:name="box_outer_merged"
+                android:pathData="M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M -2.0,5.00001525879 c 0.0,0.0 -1.4234161377,-1.40159606934 -1.4234161377,-1.40159606934 c 0.0,0.0 1.41409301758,-1.41409301758 1.41409301758,-1.41409301758 c 0.0,0.0 0.00932312011719,-0.0124053955078 0.00932312011719,-0.0124053955078 c 0.0,0.0 0.0234069824219,-0.0235137939453 0.0234069824219,-0.0235137939453 c 0.0,0.0 1.41409301758,1.41409301758 1.41409301758,1.41409301758 c 0.0,0.0 -1.4375,1.43751525879 -1.4375,1.43751525879 Z"
+                android:fillColor="#FF000000"
+                android:fillAlpha="0" />
+        </group>
+        <group
+            android:name="box_dilate"
+            android:scaleX="7.5"
+            android:scaleY="7.5" >
+            <path
+                android:name="box_inner_merged"
+                android:pathData="M -7.0,-7.0 l 14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -14.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-14.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z M 7.0,-9.0 c 0.0,0.0 -14.0,0.0 -14.0,0.0 c -1.1044921875,0.0 -2.0,0.8955078125 -2.0,2.0 c 0.0,0.0 0.0,14.0 0.0,14.0 c 0.0,1.1044921875 0.8955078125,2.0 2.0,2.0 c 0.0,0.0 14.0,0.0 14.0,0.0 c 1.1044921875,0.0 2.0,-0.8955078125 2.0,-2.0 c 0.0,0.0 0.0,-14.0 0.0,-14.0 c 0.0,-1.1044921875 -0.8955078125,-2.0 -2.0,-2.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z"
+                android:fillColor="#FF000000" />
+        </group>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/ic_checkbox_unchecked_animation.xml b/core/res/res/drawable/ic_checkbox_unchecked_animation.xml
new file mode 100644
index 0000000..605fce1
--- /dev/null
+++ b/core/res/res/drawable/ic_checkbox_unchecked_animation.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+
+<animated-vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/ic_checkbox_unchecked" >
+    <target
+        android:name="icon_null"
+        android:animation="@anim/ic_checkbox_unchecked_icon_null_animation" />
+    <target
+        android:name="box_outer_merged"
+        android:animation="@anim/ic_checkbox_unchecked_box_outer_merged_animation" />
+    <target
+        android:name="box_inner_merged"
+        android:animation="@anim/ic_checkbox_unchecked_box_inner_merged_animation" />
+</animated-vector>
diff --git a/core/res/res/drawable/ic_chevron_left.xml b/core/res/res/drawable/ic_chevron_left.xml
new file mode 100644
index 0000000..dc24706
--- /dev/null
+++ b/core/res/res/drawable/ic_chevron_left.xml
@@ -0,0 +1,25 @@
+<!--
+    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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M15.41 7.41L14 6l-6 6 6 6 1.41,-1.41L10.83 12z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_chevron_right.xml b/core/res/res/drawable/ic_chevron_right.xml
new file mode 100644
index 0000000..4e6d8e3
--- /dev/null
+++ b/core/res/res/drawable/ic_chevron_right.xml
@@ -0,0 +1,25 @@
+<!--
+    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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6,-6z"/>
+</vector>
diff --git a/core/res/res/drawable/list_divider_material.xml b/core/res/res/drawable/list_divider_material.xml
index babb646..658a59d 100644
--- a/core/res/res/drawable/list_divider_material.xml
+++ b/core/res/res/drawable/list_divider_material.xml
@@ -14,7 +14,10 @@
      limitations under the License.
 -->
 
-<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/list_divider_mtrl_alpha"
-    android:tint="?attr/colorForeground"
-    android:alpha="0.12" />
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:tint="?attr/colorForeground">
+    <solid android:color="#1f000000" />
+    <size
+        android:height="1dp"
+        android:width="1dp" />
+</shape>
diff --git a/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_0.xml b/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_0.xml
new file mode 100644
index 0000000..ceac663
--- /dev/null
+++ b/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_0.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 l 1.0,0.0 l 0.0,1.0" />
diff --git a/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_1.xml b/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_1.xml
new file mode 100644
index 0000000..26bc8ad
--- /dev/null
+++ b/core/res/res/interpolator/ic_checkbox_checked_animation_interpolator_1.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.33333333,0.0 0.0,1.0 1.0,1.0" />
diff --git a/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_0.xml b/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_0.xml
new file mode 100644
index 0000000..ceac663
--- /dev/null
+++ b/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_0.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 l 1.0,0.0 l 0.0,1.0" />
diff --git a/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_1.xml b/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_1.xml
new file mode 100644
index 0000000..26bc8ad
--- /dev/null
+++ b/core/res/res/interpolator/ic_checkbox_unchecked_animation_interpolator_1.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.33333333,0.0 0.0,1.0 1.0,1.0" />
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index 1b85e8f..89c3749 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -53,6 +53,7 @@
                 android:id="@+id/hours"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
                 android:singleLine="true"
                 android:ellipsize="none"
                 android:gravity="right"
@@ -64,6 +65,7 @@
                 android:id="@+id/separator"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
                 android:importantForAccessibility="no"
                 tools:text=":"
                 tools:textSize="@dimen/timepicker_time_label_size"
@@ -75,6 +77,7 @@
                 android:id="@+id/minutes"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
                 android:singleLine="true"
                 android:ellipsize="none"
                 android:gravity="left"
@@ -97,6 +100,7 @@
                 android:id="@+id/am_label"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.Material.TimePicker.AmPmLabel"
                 android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
                 android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
                 android:paddingTop="@dimen/timepicker_am_top_padding"
@@ -111,6 +115,7 @@
                 android:id="@+id/pm_label"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.Material.TimePicker.AmPmLabel"
                 android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
                 android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
                 android:paddingTop="@dimen/timepicker_pm_top_padding"
diff --git a/core/res/res/layout-watch/progress_dialog_material.xml b/core/res/res/layout-watch/progress_dialog_material.xml
new file mode 100644
index 0000000..228f724
--- /dev/null
+++ b/core/res/res/layout-watch/progress_dialog_material.xml
@@ -0,0 +1,47 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <LinearLayout
+        android:id="@+id/body"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:baselineAligned="false"
+        android:paddingStart="?attr/dialogPreferredPadding"
+        android:paddingTop="@dimen/dialog_padding_top_material"
+        android:paddingEnd="?attr/dialogPreferredPadding"
+        android:paddingBottom="@dimen/dialog_padding_top_material">
+
+        <ProgressBar
+            android:id="@id/progress"
+            style="?android:attr/progressBarStyleSmall"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:max="10000"
+            android:layout_marginEnd="?attr/dialogPreferredPadding" />
+
+        <TextView
+            android:id="@+id/message"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical" />
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/date_picker_month_item_material.xml b/core/res/res/layout/date_picker_month_item_material.xml
new file mode 100644
index 0000000..cb79cee
--- /dev/null
+++ b/core/res/res/layout/date_picker_month_item_material.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+
+<android.widget.SimpleMonthView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/month_view"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingStart="@dimen/day_picker_padding_horizontal"
+    android:paddingEnd="@dimen/day_picker_padding_horizontal"
+    android:paddingTop="@dimen/day_picker_padding_top" />
diff --git a/core/res/res/layout/date_picker_view_animator_material.xml b/core/res/res/layout/date_picker_view_animator_material.xml
index 98ef1dd..620ddfa 100644
--- a/core/res/res/layout/date_picker_view_animator_material.xml
+++ b/core/res/res/layout/date_picker_view_animator_material.xml
@@ -26,9 +26,8 @@
         android:id="@+id/date_picker_day_picker"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:paddingStart="@dimen/day_picker_padding_horizontal"
-        android:paddingEnd="@dimen/day_picker_padding_horizontal"
-        android:paddingTop="@dimen/day_picker_padding_top" />
+        android:inAnimation="@anim/fade_in"
+        android:outAnimation="@anim/fade_out" />
 
     <android.widget.YearPickerView
         android:id="@+id/date_picker_year_picker"
diff --git a/core/res/res/layout/floating_popup_container.xml b/core/res/res/layout/floating_popup_container.xml
new file mode 100644
index 0000000..f247919
--- /dev/null
+++ b/core/res/res/layout/floating_popup_container.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 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.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="wrap_content"
+    android:layout_height="@dimen/floating_toolbar_height"
+    android:elevation="2dp"
+    android:focusable="true"
+    android:focusableInTouchMode="true"
+    android:background="@android:color/background_light" />
diff --git a/core/res/res/layout/floating_popup_menu_button.xml b/core/res/res/layout/floating_popup_menu_button.xml
new file mode 100644
index 0000000..9fa13bd
--- /dev/null
+++ b/core/res/res/layout/floating_popup_menu_button.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 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.
+*/
+-->
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:minWidth="@dimen/floating_toolbar_menu_button_side_padding"
+    android:paddingLeft="@dimen/floating_toolbar_menu_button_side_padding"
+    android:paddingRight="@dimen/floating_toolbar_menu_button_side_padding"
+    android:paddingTop="0dp"
+    android:paddingBottom="0dp"
+    android:singleLine="true"
+    android:ellipsize="end"
+    android:fontFamily="sans-serif"
+    android:textSize="@dimen/floating_toolbar_text_size"
+    android:textAllCaps="true"
+    android:background="?attr/selectableItemBackground" />
\ No newline at end of file
diff --git a/core/res/res/layout/floating_popup_open_overflow_button.xml b/core/res/res/layout/floating_popup_open_overflow_button.xml
new file mode 100644
index 0000000..4c1176c
--- /dev/null
+++ b/core/res/res/layout/floating_popup_open_overflow_button.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 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.
+*/
+-->
+<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="@dimen/floating_toolbar_menu_button_minimum_width"
+    android:layout_height="match_parent"
+    android:minWidth="@dimen/floating_toolbar_menu_button_minimum_width"
+    android:minHeight="@dimen/floating_toolbar_height"
+    android:src="@drawable/ic_menu_moreoverflow_material"
+    android:contentDescription="@string/action_menu_overflow_description"
+    android:background="?attr/selectableItemBackgroundBorderless" />
diff --git a/core/res/res/layout/time_picker_header_material.xml b/core/res/res/layout/time_picker_header_material.xml
index 0ef404d..be9e443 100644
--- a/core/res/res/layout/time_picker_header_material.xml
+++ b/core/res/res/layout/time_picker_header_material.xml
@@ -15,6 +15,8 @@
   ~ limitations under the License
   -->
 
+<!-- This layout is duplicated in land/time_picker_material.xml, so any
+     changes made here need to be manually copied over. -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 xmlns:tools="http://schemas.android.com/tools"
                 android:id="@+id/time_header"
@@ -32,6 +34,7 @@
         android:layout_height="wrap_content"
         android:layout_toLeftOf="@+id/separator"
         android:layout_alignBaseline="@+id/separator"
+        android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
         android:singleLine="true"
         android:ellipsize="none"
         android:gravity="right"
@@ -46,6 +49,7 @@
         android:layout_marginLeft="@dimen/timepicker_separator_padding"
         android:layout_marginRight="@dimen/timepicker_separator_padding"
         android:layout_centerInParent="true"
+        android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
         android:importantForAccessibility="no"
         tools:text=":"
         tools:textSize="@dimen/timepicker_time_label_size"
@@ -59,6 +63,7 @@
         android:layout_height="wrap_content"
         android:layout_toRightOf="@+id/separator"
         android:layout_alignBaseline="@+id/separator"
+        android:textAppearance="@style/TextAppearance.Material.TimePicker.TimeLabel"
         android:singleLine="true"
         android:ellipsize="none"
         android:gravity="left"
@@ -83,6 +88,7 @@
             android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
             android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
             android:paddingTop="@dimen/timepicker_am_top_padding"
+            android:textAppearance="@style/TextAppearance.Material.TimePicker.AmPmLabel"
             android:lines="1"
             android:ellipsize="none"
             tools:text="AM"
@@ -95,6 +101,7 @@
             android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
             android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
             android:paddingTop="@dimen/timepicker_pm_top_padding"
+            android:textAppearance="@style/TextAppearance.Material.TimePicker.AmPmLabel"
             android:lines="1"
             android:ellipsize="none"
             tools:text="PM"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 0c61591..52cb598 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Swerfbanier af"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Soek vir diens"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-oproepe"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nie aangestuur nie"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> na <xliff:g id="TIME_DELAY">{2}</xliff:g> sekondes"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Laat die program toe om foto\'s en video\'s met die kamera te neem. Hierdie toestemming laat die program toe om die kamera te eniger tyd sonder jou bevestiging te gebruik."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"deaktiveer LED wat oordrag aandui wanneer kamera gebruik word"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Laat \'n pre-geïnstalleerde stelselprogram toe om die LED wat kamera-gebruik aandui, te deaktiveer."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Laat \'n voorafgeïnstalleerde stelselprogram toe om stelselgebeure aan die kameradiens te stuur."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"deaktiveer tablet permanent"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"deaktiveer TV permanent"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"deaktiveer foon permanent"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"begin CDMA-TV-opstelling regstreeks"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"begin dadelik met CDMA-foonopstelling"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Laat die program toe om CDMA-voorsiening te begin. Kwaadwillige programme kan dalk onnodig CDMA-voorsiening begin."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"bestuur kennisgewings vir liggingopdatering"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Laat die jeug program toe om liggingopdatering-berigte van die radio te aktiveer/deaktiveer. Nie vir gebruik deur normale programme nie."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"kry toegang tot insleutel-eienskappe"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Laat die program toe om metodes te benut om vingerafdruksjablone vir gebruik by te voeg en uit te vee."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"gebruik vingerafdrukhardeware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Laat die program toe om vingerafdrukhardeware vir stawing te gebruik"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Gedeeltelike vingerafdruk is bespeur. Probeer asseblief weer."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Kon nie vingerafdruk verwerk nie. Probeer asseblief weer."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Vingerafdruksensor is vuil. Maak dit skoon en probeer weer."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Vinger is te vinnig beweeg. Probeer asseblief weer."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Vinger is te stadig beweeg. Probeer asseblief weer."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Handelaarspesifieke aankoopfoutboodskap 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Kon nie verwerk nie. Probeer weer."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardeware is nie beskikbaar nie."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Vingerafdruk kan nie gestoor word nie. Verwyder asseblief \'n bestaande vingerafdruk."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vingerafdrukuittelling is bereik. Probeer weer."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Vingerafdrukuittelling is bereik. Probeer weer."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Handelaarspesifieke foutboodskap."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lees sinkroniseer-instellings"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Laat die program toe om die sinkroniseringinstellings van \'n rekening te lees. Byvoorbeeld, dit kan bepaal of die People-program met \'n rekening gesinkroniseer is."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"wissel tussen sinkronisasie aan en af"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Laat \'n program toe om DRM-sertifikate te verwyder. Behoort nooit vir gewone programme nodig te wees nie."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"bind aan \'n diensverskaffer-boodskapdiens"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Dit laat die houer toe om aan die top-koppelvlak van \'n diensverskaffer-boodskapdiens te bind. Behoort nooit vir gewone programme nodig te wees nie."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Beheer die lengte en die karakters wat in skermslotwagwoorde en -PIN\'e toegelaat word."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor pogings om skerm te ontsluit"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Laat die program toe om te verifieer dat \'n pakket installeerbaar is."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind aan \'n pakkieverifieerder"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Laat die houer toe om versoeke aan pakketverifieerders te rig. Dit moet nooit vir normale programme nodig wees nie."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verifieer voornemefilter"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Laat die program toe om te kyk of \'n voornemefilter geverifieer is of nie."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"bind aan \'n voornemefilterverifieerder"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Laat die houer toe om versoeke te rig aan voornemefilterverifieerders. Behoort nooit vir normale programme nodig te wees nie."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"kry toegang tot reekspoorte"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Laat die houer toe om toegang te verkry tot reekspoorte wat die SerialManager API gebruik."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"verkry toegang tot inhoud ekstern"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Verminder dag"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Vermeerder jaar"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Verminder jaar"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Vorige maand"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Volgende maand"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Kanselleer"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Vee uit"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Minute se sirkelglyer"</string>
     <string name="select_hours" msgid="6043079511766008245">"Kies ure"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Kies minute"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Maandrooster van dae"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Jaarlys"</string>
     <string name="select_day" msgid="7774759604701773332">"Kies maand en dag"</string>
     <string name="select_year" msgid="7952052866994196170">"Kies jaar"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> gekies"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> uitgevee"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Om hierdie skerm te ontspeld, raak en hou tegelyk Terug en Oorsig."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index b639b4f..b1b6c18 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"የዝውውር ሰንደቅ ጠፍቷል"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"አገልግሎት ፍለጋ"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"የWi-Fi ጥሪ ማድረጊያ"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>፡አልተላለፈም"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>፡<xliff:g id="DIALING_NUMBER">{1}</xliff:g> ከ<xliff:g id="TIME_DELAY">{2}</xliff:g> ሰከንዶች በኋላ"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"መተግበሪያው በካሜራው ፎቶዎችንና ቪዲዮዎችን እንዲያነሳ ይፈቅድለታል። ይህ ፈቃድ መተግበሪያው ካሜራውን በማንኛውም ጊዜ ያላንተ ማረጋገጫ እንዲጠቀም ይፈቅድለታል።"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"ካሜራው ስራ ላይ ሲሆን የማስተላለፍ አመልካች ኤል ኢ ዲን ያሰናክሉ"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"ቀድሞ የተጫነ የስርዓት መተግበሪያ ካሜራውን አመላካች ኤል ኢ ዲ እንዳይጠቀም እንዲያሰናክል ያስችለዋል።"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Allows a pre-installed system application to send the camera service system"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"በቋሚነት ጡባዊ አቦዝን"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"ቴሌቪዥን እስከመጨረሻ አሰናክል"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"በቋሚነት ስልኩን አቦዝን"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"በቀጥታ የሲዲኤምኤ ቴሌቪዥን ማዋቀር ጀምር"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"የCDMA ስልክ ጫን በቀጥታ አስጀምር"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"መተግበሪያው የCDMA ዝግጅት ለመጀመር ይፈቅዳሉ ። ተንኮል አዘል መተግበሪያዎች አላስፈላጊ የCDMA ዝግጅት ይጀምራሉ።"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"የሥፍራ አዘምን ማሳወቂያዎችን ተቆጣጠር"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"ከሬድዮ የአከባቢ አዘምን ማሳወቂያዎችን ለማንቃት/ለማስወገድ ለመተግበሪያው ይፈቅዳል፡፡ ለመደበኛ መተግበሪያዎች ጥቅም አይደለም፡፡"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"የድረስባህሪያት ምልከታ"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"መተግበሪያው ጥቅም ላይ እንዲውሉ የጣት አሻራ ቅንብር ደንቦችን ለማከል እና ለመሰረዝ የሚያስችሉ ስልቶችን እንዲያስጀምር ያስችለዋል።"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"የጣት አሻራ ሃርድዌርን ተጠቀም"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"መተግበሪያው የጣት አሻራ ሃርድዌር ለማረጋገጥ ስራ እንዲጠቀም ያስችለዋል"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ከፊል የጣት አሻራ ተገኝቷል። እባክዎ እንደገና ይሞክሩ።"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ጣት አሻራን መስራት አልተቻለም። እባክዎ እንደገና ይሞክሩ።"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"የጣት አሻራ ዳሳሽ ቆሽሿል። እባክዎ ያጽዱት እና እንደገና ይሞክሩ።"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"ጣት በጣም በፍጥነት ተንቀሳቅሷል። እባክዎ እንደገና ይሞክሩ።"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"ጣት በጣም በዝግታ ተንቀሳቅሷል። እባክዎ እንደገና ይሞክሩ።"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"አቅራቢ-ተኮር ግዢ የስህተት መልዕክት 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"ሂደትን ማከናወን አልተቻለም። እንደገና ይሞክሩ።"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"ሃርድዌር አይገኝም።"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"የጣት አሻራ ሊከማች አይችልም። እባክዎ አሁን ያለውን የጣት አሻራ ያስወግዱ።"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"የጣት አሻራ ማብቂያ ጊዜ ደርሷል። እንደገና ይሞክሩ።"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"የጣት አሻራ ማብቂያ ጊዜ ደርሷል። እንደገና ይሞክሩ።"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"አቅራቢ-ተኮር የስህተት መልዕክት"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"የሥምሪያ ቅንብሮች አንብብ"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"መተግበሪያው የአንድ መለያ የማመሳሰል ቅንብሮችን እንዲያነብ ይፈቅድለታል። ለምሳሌ ይህ የሰዎች መተግበሪያ ከመለያ ጋር መመሳሰሉን አለመመሳሰሉን ሊወስን ይችላል።"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ማመሳሰያ በማብራትና በማጥፋት መካከል ቀያይር"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"አንድ መተግበሪያ የDRM እውቅና ማረጋገጫዎችን እንዲያስወግድ ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"ወደሞባይል አገልግሎት ሰጪ የመልዕክት አገልግሎት አያይዝ"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"ያዢው በሞባይል አገልግሎት ሰጪ የመልዕክት አላላክ አገልግሎት ላይ ከፍተኛውን ደረጃ በይነ ገጽ እንዲይዝ ይፈቅድለታል። ለመደበኛ መተግበሪያ በጭራሽ አያስፈልግም።"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ደንቦች አዘጋጅ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"በማያ ገጽ መቆለፊያ የይለፍ ቃሎች እና ፒኖች ውስጥ የሚፈቀዱ ቁምፊዎችን እና ርዝመታቸውን ተቆጣጠር።"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"የማሳያ-ክፈት ሙከራዎችን አሳይ"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"ፓኬጅ መጫን የሚችል መሆኑን ለማረጋገጥ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"በፓኬጅ አረጋጋጭ የተወሰነ"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"የፓኬጅ አረጋጋጮችን ጥየቃ ለማድረግ ያዡ ይፈቅዳሉ። ለመደበኛ መተግበሪያዎች በፍፁም አያስፈልግም።"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"የፍላጎት ማጣሪያን አረጋግጥ"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"የፍላጎት ማጣሪያው የተረጋገጠ ወይም ያልተረጋገጠ መሆኑን ለመፈተሽ እንዲችል መተግበሪያውን ይፈቅድለታል።"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"በፍላጎት ማጣሪያ አረጋገጭ ተገደብ"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"የፍላጎት ማጣሪያ አረጋጋጮችን ጥየቃ ለማድረግ ያዡ ይፈቅዳሉ። ለመደበኛ መተግበሪያዎች በፍፁም አያስፈልግም።"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"ተከታታይ ወደቦችን ድረስ"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Allows the holder to access serial ports using the SerialManager API. የተከታታይ አደራጅ APIን በመጠቀም ያዡ የተከታታይ ወደቦችን እንዲደርስ ይፈቅዳል።"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"ይዘት አቅራቢዎችን በውጭ በኩል ድረስባቸው"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ቀን ቀንስ"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"ዓመት ጨምር"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ዓመት ቀንስ"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"ያለፈው ወር"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"ቀጣይ ወር"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"ይቅር"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ሰርዝ"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"የደቂቃዎች ክብ ተንሸራታች"</string>
     <string name="select_hours" msgid="6043079511766008245">"ሰዓታትን ይምረጡ"</string>
     <string name="select_minutes" msgid="3974345615920336087">"ደቂቃዎችን ይምረጡ"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"የቀናት የወር ፍርግርግ"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"የዓመት ዝርዝር"</string>
     <string name="select_day" msgid="7774759604701773332">"ወር እና ቀን ይምረጡ"</string>
     <string name="select_year" msgid="7952052866994196170">"ዓመት ይምረጡ"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ተመርጧል"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ተሰርዟል"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"ይህን ማያ ገጽ ለመንቀል ተመለስን እና አጠቃላይ እይታን በተመሳሳይ ይንኳቸውና ይያዟቸው።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 42bf57d..1409d1d 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -128,8 +128,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"إعلان بانر للتجوال متوقف"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"البحث عن خدمة"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"‏الاتصال عبر Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: لم تتم إعادة التوجيه"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> بعد <xliff:g id="TIME_DELAY">{2}</xliff:g> ثانية"</string>
@@ -588,6 +599,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"للسماح للتطبيق بالتقاط صور ومقاطع فيديو من خلال الكاميرا. ويتيح هذا الإذن للتطبيق استخدام الكاميرا في أي وقت وبدون موافقة منك."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"‏تعطيل مؤشر LED للإرسال عندما تكون الكاميرا قيد الاستخدام"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"‏للسماح لتطبيق نظام مثبت مسبقًا لتعطيل مؤشر LED لاستخدام الكاميرا."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"للسماح لتطبيق نظام مثبت مسبقًا بإرسال أحداث نظام خدمة الكاميرا."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"تعطيل الجهاز اللوحي نهائيًا"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"تعطيل التلفزيون نهائيًا"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"تعطيل الهاتف على الدوام"</string>
@@ -636,6 +648,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"‏تشغيل إعداد تلفزيون CDMA مباشرة"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"‏بدء إعداد هاتف CDMA مباشرة"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"‏للسماح للتطبيق ببدء توفير CDMA. قد تبدأ التطبيقات الضارة توفير CDMA بدون الحاجة إلى ذلك."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"التحكم في اشعارات تحديث الموقع"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"للسماح للتطبيق بتمكين/تعطيل إشعارات تحديث الموقع من اللاسلكي. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"الدخول إلى خصائص الإيداع"</string>
@@ -750,6 +766,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"للسماح للتطبيق باستدعاء طرق لإضافة نماذج من بصمات الأصابع وحذفها."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"لاستخدام أجهزة بصمة الإصبع"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"للسماح للتطبيق باستخدام أجهزة بصمة الإصبع للمصادقة"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"تم اكتشاف بصمة الإصبع بشكل جزئي؛ يرجى إعادة المحاولة."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"تعذرت معالجة بصمة الإصبع. يُرجى إعادة المحاولة."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"جهاز استشعار بصمات الأصابع متسخ، يرجى تنظيفه وإعادة المحاولة."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"تحرك الإصبع بسرعة كبيرة جدًا؛ يرجى إعادة المحاولة."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"تحرك الإصبع ببطء شديد جدًا؛ يرجى إعادة المحاولة."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"رسالة الخطأ 0 التي حددها المورّد بشأن الاكتساب"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"تعذرت المعالجة؛ أعد المحاولة."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"الجهاز غير متاح."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"يتعذر تخزين بصمة الإصبع؛ يرجى إزالة إحدى البصمات المخزنة."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"تم بلوغ مهلة إدخال بصمة الإصبع. أعد المحاولة."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"تم بلوغ مهلة إدخال بصمة الإصبع. أعد المحاولة."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"رسالة الخطأ التي حددها المورّد."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"قراءة إعدادات المزامنة"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"للسماح للتطبيق بقراءة الإعدادات المتزامنة لحساب ما. على سبيل المثال، يمكن أن يؤدي هذا إلى تحديد ما إذا تمت مزامنة تطبيق \"الأشخاص\" مع حساب ما."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"التبديل بين تشغيل المزامنة وإيقافها"</string>
@@ -826,6 +858,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"‏للسماح لأحد التطبيقات بإزالة شهادات DRM. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"الالتزام بخدمة المراسلة التابعة لمشغل شبكة الجوّال"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"يسمح لحامله بالالتزام بواجهة المستوى العالي لخدمة المراسلة التابعة لمشغل شبكة الجوَّال. ومن المفترض عدم الحاجة إليه مع التطبيقات العادية."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"التفاعل مع خدمة التفاعل الصوتي"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"للسماح للمالك بالتفاعل مع خدمة التفاعل الصوتي النشطة حاليًا. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"للتحكم في الطول والأحرف المسموح بها في كلمات المرور وأرقام التعريف الشخصي في قفل الشاشة."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"مراقبة محاولات إلغاء قفل الشاشة"</string>
@@ -1123,6 +1157,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"السماح للتطبيق بالتحقق من إمكانية تثبيت حزمة."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"الالتزام بمحقق حزمة"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"السماح للمالك بإجراء طلبات محققي الحزمة. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"التحقق من فلتر الأهداف"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"للسماح للتطبيق بفحص ما إذا كان فلتر الأهداف قد تم التحقق منه أم لا."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"الالتزام بمحقق فلتر الأهداف"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"للسماح للمالك بإجراء طلبات محققي فلتر الأهداف. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"الدخول إلى المنافذ التسلسلية"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"يسمح لحامله بالدخول إلى المنافذ التسلسلية باستخدام واجهة برمجة التطبيقات."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"الدخول إلى مزودي المحتوى خارجيًا"</string>
@@ -1576,6 +1614,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"تقليل الأيام"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"زيادة الأعوام"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"تقليل الأعوام"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"الشهر السابق"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"الشهر التالي"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"إلغاء"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"حذف"</string>
@@ -1830,11 +1870,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"شريط التمرير الدائري للدقائق"</string>
     <string name="select_hours" msgid="6043079511766008245">"تحديد الساعات"</string>
     <string name="select_minutes" msgid="3974345615920336087">"تحديد الدقائق"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"شبكة الشهر مكونة من الأيام"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"قائمة الأعوام"</string>
     <string name="select_day" msgid="7774759604701773332">"تحديد الشهر واليوم"</string>
     <string name="select_year" msgid="7952052866994196170">"تحديد العام"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"تم تحديد <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"تم حذف <xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> المخصص للعمل"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"لإلغاء تثبيت هذه الشاشة، يمكنك لمس \"رجوع\" و\"نظرة عامة\" في آن واحد مع الاستمرار."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index ecfa7bd..ecdeb13 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Банерът за роуминг е изключен"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Търси се покритие"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Обаждания през Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Не е пренасочено"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> след <xliff:g id="TIME_DELAY">{2}</xliff:g> секунди"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Разрешава на приложението да прави снимки и видеоклипове с камерата. Това разрешение му позволява да я използва по всяко време без потвърждение от ваша страна."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"деактивиране на светодиодния индикатор за предаване, когато камерата се използва"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Разрешава на предварително инсталирано системно приложение да деактивира светодиодния индикатор за използване на камерата."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Разрешава на предварително инсталирано системно приложение да изпраща известия за системни събития до услугата за камера."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"деактивиране на таблета за постоянно"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"деактивиране на телевизора за постоянно"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"деактивиране на телефона за постоянно"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"директно стартиране на настройването на телевизора със CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"директно стартиране на настройката на телефона през CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Разрешава на приложението да стартира обезпечаване за CDMA. Злонамерените приложения могат ненужно да стартират този процес."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"контролиране на известията за актуализиране на местоположението"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Разрешава на приложението да активира или деактивира известията за актуализиране на местоположението от радиомодула. Не е предназначено за нормални приложения."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"достъп до свойствата на услугата за проверка"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Разрешава на приложението да извиква начини за добавяне и изтриване на шаблони за отпечатъци, които да се използват."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"използване на хардуера за отпечатъци"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Разрешава на приложението да използва хардуера за отпечатъци с цел удостоверяване"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Открит е частичен отпечатък. Моля, опитайте отново."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Отпечатъкът не можа да се обработи. Моля, опитайте отново."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Сензорът за отпечатъци е мръсен. Моля, почистете го и опитайте отново."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Преместихте пръста си твърде бързо. Моля, опитайте отново."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Преместихте пръста си твърде бавно. Моля, опитайте отново."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Съобщение за грешка 0 при придобиване от конкретен доставчик"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Не може да се обработи. Опитайте отново."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Няма достъп до хардуера."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Отпечатъкът не може да бъде съхранен. Моля, премахнете съществуващ."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Времето за изчакване за отпечатък изтече. Опитайте отново."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Времето за изчакване за отпечатък изтече. Опитайте отново."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Съобщение за грешка от конкретен доставчик."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"четене на настройките за синхронизиране"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Разрешава на приложението да чете настройките за синхронизиране на профил. Например това може да определи дали приложението Хора е синхронизирано с даден профил."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"включване и изключване на синхронизирането"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Разрешава на приложението да премахва сертификатите за управление на цифровите права (DRM). Нормалните приложения би трябвало никога да се нуждаят от това."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"свързване с услуга за съобщения от оператор"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Разрешава на притежателя да се свърже към интерфейса от най-високото ниво на услуга за съобщения от оператор. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролира дължината и разрешените знаци за паролите и ПИН кодовете за заключване на екрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Наблюдаване на опитите за отключване на екрана"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Разрешава на приложението да провери дали пакетът може да се инсталира."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"обвързване с верификатор на пакета"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Разрешава на притежателя да прави заявки за верификатори на пакета. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"проверка на филтъра за намерения"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Разрешава на приложението да проверява дали даден филтър за намерения е потвърден или не."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"свързв. с вериф. на филтри за намерения"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Разрешава на притежателя да отправя заявки за верификатори на филтрите за намерения. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"достъп до серийни портове"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Разрешава на притежателя достъп до серийни портове посредством приложния програмен интерфейс (API) SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"външен достъп до доставчиците на съдърж."</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Намаляване на дните"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Увеличаване на годините"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Намаляване на годините"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Предишен месец"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Следващ месец"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Отказ"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Изтриване"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Кръгов плъзгач за минутите"</string>
     <string name="select_hours" msgid="6043079511766008245">"Избиране на часове"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Избиране на минути"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Месечна таблица на дните"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Списък с години"</string>
     <string name="select_day" msgid="7774759604701773332">"Избиране на месец и ден"</string>
     <string name="select_year" msgid="7952052866994196170">"Избиране на година"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Избрахте <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Изтрихте <xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> за работа"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"За да освободите екрана, докоснете и задръжте едновременно бутона за връщане назад и този за общ преглед."</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index f20e21f..cf45bf7a 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"রোমিং ব্যানার বন্ধ আছে"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"পরিষেবা অনুসন্ধান করা হচ্ছে"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi কলিং"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফরওয়ার্ড করা হয়নি"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> সেকেন্ড পরে"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"ক্যামেরার সাহায্যে ছবি তুলতে ও ভিডিও তৈরি করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এই অনুমতিটি অ্যাপ্লিকেশানটিকে আপনার নিশ্চয়তা ছাড়াই যেকোনো সময় ক্যামেরা ব্যবহার করতে মঞ্জুর করে৷"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"যখন ক্যামেরা ব্যবহারে থাকে তখন ট্রান্সমিট সূচক LED অক্ষম করে"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"আগে থেকে ইনস্টল থাকা একটি সিস্টেম অ্যাপ্লিকেশানকে ক্যামেরা ব্যবহারের সূচক LEDটিকে অক্ষম করার অনুমতি দেয়৷"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"ক্যামেরা পরিষেবার সিস্টেম ইভেন্টগুলি পাঠাতে আগে থেকে ইনস্টল থাকা একটি সিস্টেম অ্যাপ্লিকেশানকে অনুমতি দেয়৷"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"ট্যাবলেটকে স্থায়ীভাবে অক্ষম করে"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"টিভি স্থায়ীভাবে অক্ষম করে"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ফোনকে স্থায়ীভাবে অক্ষম করে"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"সরাসরি CDMA TV সেটআপ শুরু করে"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA ফোন সেটআপ সরাসরি শুরু করে"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"অ্যাপ্লিকেশানকে CDMA প্রস্তুতি শুরু করার অনুমতি দেয়৷ ক্ষতিকারক অ্যাপ্লিকেশান অকারণে CDMA প্রস্তুতি শুরু করতে পারে৷"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"অবস্থান আপডেট বিজ্ঞপ্তিগুলিকে নিয়ন্ত্রণ করে"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"অ্যাপ্লিকেশানকে রেডিও থেকে অবস্থানের আপডেটের বিজ্ঞপ্তি সক্ষম/অক্ষম করতে দেয়৷ সাধারণ অ্যাপ্লিকেশানগুলির ব্যবহারের জন্য নয়৷"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"চেক ইন বৈশিষ্ট্যাবলী অ্যাক্সেস করে"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ব্যবহার করার জন্য আঙ্গুলের ছাপের টেম্প্লেটগুলি যোগ করা এবং মোছার পদ্ধতিগুলি গ্রহন করতে অ্যাপ্লিকেশানটিতে অমুমতি দেয়৷"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার ব্যবহার করুন"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"অনুমোদনের জন্য আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার ব্যবহার করতে অ্যাপ্লিকেশানটিতে অনুমতি দেয়"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"আঙ্গুলের ছাপ আংশিক সনাক্ত করা হয়েছে৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"আঙ্গুলের ছাপ প্রক্রিয়া করা যায়নি৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"আঙ্গুলের ছাপ নেওয়ার সেন্সরটি অপরিস্কার৷ অনুগ্রহ করে পরিষ্কার করে আবার চেষ্টা করুন৷"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"আঙ্গুল অতি দ্রুত সরানো হয়েছে৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"আঙ্গুল ধীরে সরানো হয়েছে৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"বিক্রেতা-নির্দিষ্ট অর্জনে ত্রুটি বার্তা ০"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"প্রক্রিয়া করতে অক্ষম হয়েছে৷ আবার চেষ্টা করুন৷"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"হার্ডওয়্যার অনুপলব্ধ৷"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"আঙ্গুলের ছাপ সংরক্ষণ করা যাবে না৷ অনুগ্রহ করে একটি বিদ্যমান আঙ্গুলের ছাপ সরান৷"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"আঙ্গুলের ছাপ নেওয়ার সময়সীমা শেষ হযেছে৷ আবার চেষ্টা করুন৷"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"আঙ্গুলের ছাপ নেওয়ার সময়সীমা শেষ হযেছে৷ আবার চেষ্টা করুন৷"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"বিক্রেতা-নির্দিষ্ট ত্রুটি বার্তা৷"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"সিঙ্ক সেটিংস পড়ে"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"অ্যাপ্লিকেশানটিকে একটি অ্যাকাউন্টের জন্য সিঙ্ক সেটিংস পড়ার অনুমতি দেয়৷ উদাহরণস্বরূপ, \'পিপল\' অ্যাপ্লিকেশানটি কোনো অ্যাকাউন্টের সাথে সিঙ্ক করা আছে কিনা তা নির্ধারণ করতে পারে৷"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"সমন্বয় চালু এবং বন্ধ করা টগল করুন"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"কোনো অ্যাপ্লিকেশানকে DRM শংসাপত্রগুলি সরানোর অনুমতি দেয়। সাধারণ অ্যাপ্লিকেশানগুলির জন্য কখনো প্রয়োজন হয় না।"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"একটি ক্যারিয়ার বার্তাপ্রেরণ পরিষেবা আবদ্ধ করতে"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"ধারককে, একটি ক্যারিয়ার বার্তাপ্রেরণ পরিষেবার উচ্চ স্তরের ইন্টারফেসে জুড়তে অনুমতি দেয়৷ সধারণ অ্যাপ্লিকেশানগুলির জন্য কখনই প্রয়োজন হয় না৷"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"পাসওয়ার্ড নিয়মগুলি সেট করে"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"স্ক্রীন লক করার পাসওয়ার্ডগুলিতে অনুমতিপ্রাপ্ত অক্ষর এবং দৈর্ঘ্য নিয়ন্ত্রণ করে৷"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"স্ক্রীণ আনলক করার প্রচেষ্টাগুলি নিরীক্ষণ করে"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"অ্যাপ্লিকেশানকে ইনস্টলযোগ্য প্যাকেজ যাচাই করার অনুমতি দেয়৷"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"একটি প্যাকেজ যাচাইকারীতে সংলগ্ন করে"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"ধারককে, প্যাকেজ যাচাইকারীতে অনুরোধগুলি পাঠাতে দেয়৷ সাধারণ অ্যাপ্লিকেশানগুলির জন্য কখনোই প্রয়োজনীয় নয়৷"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"অভিপ্রায় ফিল্টার যাচাই করুন"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"কোনো অভিপ্রায় ফিল্টার যাচাই করা হয়েছে কি না অ্যাপ্লিকেশানটিকে তা পরীক্ষা করার মঞ্জুরি দেয়৷"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"একটি অভিপ্রায় ফিল্টার যাচাইকারী আবদ্ধ করুন"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"ধারককে,অভিপ্রায় ফিল্টার যাচাইকারীতে অনুরোধগুলি পাঠাতে দেয়৷ সাধারণ অ্যাপ্লিকেশানগুলির জন্য কখনোই প্রয়োজনীয় নয়৷"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"সিরিয়াল পোর্টগুলি অ্যাক্সেস করে"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"সিরিয়াল ম্যানেজার API ব্যবহার করে ধারককে সিরিয়াল পোর্টগুলি অ্যাক্সেস করতে অনুমতি দেয়৷"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"বাহ্যিকভাবে সামগ্রীর পরিষেবা প্রদানকারীদের অ্যাক্সেস করুন"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"দিন কম করুন"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"বছর বাড়ান"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"বছর কম করুন"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"পূর্ববর্তী মাস"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"পরের মাস"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"বাতিল করুন"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"মুছুন"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"বৃত্তাকার মিনিট নির্বাচকের স্লাইডার"</string>
     <string name="select_hours" msgid="6043079511766008245">"ঘন্টা নির্বাচন করুন"</string>
     <string name="select_minutes" msgid="3974345615920336087">"মিনিট নির্বাচন করুন"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"দিন দিয়ে সংগঠিত মাসের গ্রিড"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"বছরের তালিকা"</string>
     <string name="select_day" msgid="7774759604701773332">"মাস এবং দিন নির্বাচন করুন"</string>
     <string name="select_year" msgid="7952052866994196170">"বছর নির্বাচন করুন"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> নির্বাচন করা হয়েছে"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> মুছে ফেলা হয়েছে"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"কর্মক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"এই স্ক্রীনটিকে আনপিন করতে, \'ফিরুন\' এবং \'এক নজরে\' একসাথে স্পর্শ করুন এবং ধরে রাখুন৷"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index aebebf2..2f07733 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Bàner d\'itinerància desactivat"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"S\'està cercant el servei"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Trucades per Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no s\'ha desviat"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> després de <xliff:g id="TIME_DELAY">{2}</xliff:g> segons"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Permet que l\'aplicació faci fotos i vídeos amb la càmera. Aquest permís permet que l\'aplicació utilitzi la càmera en qualsevol moment sense la teva confirmació."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"desactiva la transmissió del LED indicador en fer servir la càmera"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Permet que una aplicació dels sistema preinstal·lada desactivi el LED indicador d\'ús de la càmera."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Permet que una aplicació dels sistema preinstal·lada enviï esdeveniments del sistema al servei de la càmera."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"desactiva la tauleta de manera permanent"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"desactivar el televisor de manera permanent"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"desactivar definitivament el telèfon"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"iniciar directament la configuració del televisor CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directament la configuració del telèfon CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Permet que l\'aplicació iniciï l\'aprovisionament CDMA. Les aplicacions malicioses poden iniciar l\'aprovisionament CDMA innecessàriament."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar les notificacions d\'actualització de la ubicació"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permet que l\'aplicació activi i desactivi les notificacions d\'actualització de la ubicació del senyal mòbil. No la poden fer servir les aplicacions normals."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"accedir a les propietats d\'accés"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permet que l\'aplicació invoqui mètodes per afegir i suprimir plantilles d\'empremtes digitals que es puguin fer servir."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utilitzar el maquinari d\'empremtes digitals"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permet que l\'aplicació faci servir maquinari d\'empremtes digitals per a l\'autenticació"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"S\'ha detectat una empremta digital parcial. Torna-ho a provar."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No s\'ha pogut processar l\'empremta digital. Torna-ho a provar."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"El sensor d\'empremtes digitals està brut. Neteja\'l i torna-ho a provar."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"El dit s\'ha mogut massa ràpid. Torna-ho a provar."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"El dit s\'ha mogut massa lentament. Torna-ho a provar."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Missatge d\'error d\'adquisició 0 específic del proveïdor"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"No es pot processar. Torna-ho a provar."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"No hi ha maquinari disponible."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empremta digital no es pot desar. Suprimeix-ne una."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Missatge d\'error específic del proveïdor."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"llegir la configuració de sincronització"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permet que l\'aplicació llegeixi la configuració de sincronització d\'un compte. Per exemple, això pot determinar que l\'aplicació Persones estigui sincronitzada amb un compte."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activar o desactivar la sincronització"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permet que una aplicació suprimeixi els certificats DRM. No ha de ser mai necessari per a aplicacions normals."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"vincular-la al servei de missatgeria d\'un operador"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permet que el propietari la pugui vincular a la interfície principal del servei de missatgeria d\'un operador. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Permet controlar la longitud i el nombre de caràcters permesos a les contrasenyes i als PIN del bloqueig de pantalla."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Controlar els intents de desbloqueig de pantalla"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permet que l\'aplicació verifiqui si un paquet es pot instal·lar."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"vincula a un verificador de paquets"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permet que el titular sol·liciti verificadors de paquets. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verificar el filtre d\'intenció"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Permet que l\'aplicació comprovi si un filtre d\'intenció està verificat."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"enllaçar amb verific. de filtre d\'inten."</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Permet que el titular sol·liciti verificadors de filtres. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"accedeix a ports sèrie"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permet que el titular accedeixi a ports sèrie amb l\'API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"accedeix als proveïdors de contingut externament"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Fes disminuir el dia"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Fes augmentar l\'any"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Fes disminuir l\'any"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Mes anterior"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Mes següent"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Cancel·la"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Suprimeix"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Control circular dels minuts"</string>
     <string name="select_hours" msgid="6043079511766008245">"Selecciona les hores"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Selecciona els minuts"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Graella mensual de dies"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Llista anual"</string>
     <string name="select_day" msgid="7774759604701773332">"Selecciona un mes i un dia"</string>
     <string name="select_year" msgid="7952052866994196170">"Selecciona un any"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionat"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> suprimit"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Per anul·lar la fixació d\'aquesta pantalla, mantén premudes les opcions Enrere i Visió general alhora."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 988818b..8fd8092 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -126,8 +126,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Banner roamingu je vypnutý"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Vyhledávání služby"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Volání přes Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepřesměrováno"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sek."</string>
@@ -586,6 +597,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Umožňuje aplikaci pořizovat fotografie a videa pomocí fotoaparátu. Toto oprávnění umožňuje aplikaci používat fotoaparát kdykoliv i bez vašeho svolení."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"vypnutí indikátoru LED přenosu při použití fotoaparátu"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Umožňuje předinstalované systémové aplikaci vypnout kontrolku LED fotoaparátu."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Umožňuje předinstalované systémové aplikaci odesílat systémové události služby fotoaparátu."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"trvalé vypnutí tabletu"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"trvalé vypnutí televize"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"trvalé vypnutí telefonu"</string>
@@ -634,6 +646,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"přímé spuštění nastavení kódového multiplexu v televizi"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"přímo spustit nastavení telefonu CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Umožňuje aplikaci zahájit poskytování CDMA. Škodlivé aplikace mohou poskytování CDMA zahájit samovolně."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"ovládání oznámení o aktualizaci polohy"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Umožňuje aplikaci zapnout nebo vypnout oznámení o aktualizaci polohy pomocí bezdrátového modulu. Toto oprávnění není určeno pro běžné aplikace."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"přístup k vlastnostem Checkin"</string>
@@ -748,6 +764,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Umožňuje aplikaci volat metody k přidání a smazání šablon otisků prstů, které budou použity."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"použití hardwaru na čtení otisků prstů"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Umožňuje aplikaci použít k ověření hardware na čtení otisků prstů"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Byla zjištěna jen část otisku prstu. Zkuste to znovu."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Zpracování otisku prstu se nezdařilo. Zkuste to znovu."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Senzor otisků prstů je znečištěn. Vyčistěte jej a zkuste to znovu."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Pohyb prstem byl příliš rychlý. Zkuste to znovu."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Pohyb prstem byl příliš pomalý. Zkuste to znovu."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Chybová zpráva 0 dodavatele ohledně načtení otisků"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Otisk prstu nelze zpracovat. Zkuste to znovu."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware není dostupný."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisk prstu nelze uložit. Odstraňte existující otisk prstu."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit sejmutí otisku prstu vypršel. Zkuste to znovu."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Časový limit sejmutí otisku prstu vypršel. Zkuste to znovu."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Chybová zpráva dodavatele"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čtení nastavení synchronizace"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Umožňuje aplikaci číst nastavení synchronizace v účtu. Může například určit, zda je s účtem synchronizována aplikace Lidé."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"vypnutí nebo zapnutí synchronizace"</string>
@@ -824,6 +856,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Povoluje aplikaci odstranit certifikáty DRM. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"navázat se na nejvyšší úroveň rozhraní služby zasílání zpráv prostřednictvím operátora"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní služby zasílání zpráv prostřednictvím operátora. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ovládání délky a znaků povolených v heslech a kódech PIN zámku obrazovky."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemčení obrazovky"</string>
@@ -1121,6 +1157,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Umožňuje aplikaci ověřit, zda balíček lze nainstalovat."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"navázat na ověřovatele balíčků"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Umožňuje držiteli podávat žádosti o ověření balíčků. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"ověření filtru objektů intent"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Umožňuje aplikaci zkontrolovat, zda je filtr objektů intent ověřený."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"vazba na ověření filtru objektů intent"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Umožňuje držiteli podávat žádosti o ověření filtrů objektů intent. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"přístup k sériovým portům"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Umožňuje držiteli přístup k sériovým portům pomocí rozhraní SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"externí přístup k poskytovatelům obsahu"</string>
@@ -1560,6 +1600,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Ubrat den"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Přidat rok"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Ubrat rok"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Předchozí měsíc"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Příští měsíc"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Zrušit"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Smazat"</string>
@@ -1812,11 +1854,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Kruhový posuvník minut"</string>
     <string name="select_hours" msgid="6043079511766008245">"Zvolte hodiny"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Zvolte minuty"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Dny uspořádané po měsících"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Seznam roků"</string>
     <string name="select_day" msgid="7774759604701773332">"Vyberte měsíc a den"</string>
     <string name="select_year" msgid="7952052866994196170">"Vyberte rok"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Vybrána položka <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Číslice <xliff:g id="KEY">%1$s</xliff:g> byla smazána"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Pracovní <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Chcete-li tuto obrazovku uvolnit, klepněte současně na možnosti Zpět a Přehled a podržte je."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 20b7ad2..ca037f5 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Roamingbanner fra"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Søger efter tjeneste"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Opkald via Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderestillet"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> efter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Tillader, at appen kan tage billeder og videoer med kameraet. Med denne tilladelse kan appen til enhver tid bruge kameraet uden din bekræftelse."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"deaktiver sendelysdioden, når kameraet er i brug"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Tillader, at en forudinstalleret systemapplikation deaktiverer lysdioden for brug af kameraet."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Giver en forudinstalleret systemapp tilladelse til at sende systembegivenheder til kameratjenesten."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"deaktiver tabletcomputeren permanent"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"deaktivere tv\'et permanent"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"deaktiver telefonen permanent"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"direkte starte konfiguration af CDMA TV"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"start CDMA-telefonopsætning direkte"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Tillader, at appen kan starte CDMA-levering. Ondsindede apps kan starte unødvendig CDMA-levering."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"kontroller underretninger om placeringsopdatering"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Tillader, at appen kan aktivere/deaktivere underretninger om placeringsopdatering fra senderen. Anvendes ikke i almindelige apps."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"egenskaber for adgangskontrol"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Tillader, at appen kan køre metoder til at tilføje og slette fingeraftryksskabeloner"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"brug fingeraftrykhardware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Tillader, at appen kan bruge fingeraftrykhardware til godkendelse"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Der blev registreret et delvist fingeraftryk. Prøv igen."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Fingeraftrykket kunne ikke behandles. Prøv igen."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sensoren til registrering af fingeraftryk er beskidt. Tør den af, og prøv igen."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Du bevægede fingeren for hurtigt. Prøv igen."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Du bevægede fingeren for langsomt. Prøv igen."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Leverandørspecifik fejlmeddelelse 0 i forbindelse med hentning"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Registreringen kan ikke gennemføres. Prøv igen."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardwaren er ikke tilgængelig."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeraftrykket kan ikke gemmes. Fjern et eksisterende fingeraftryk."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Registrering af fingeraftryk fik timeout. Prøv igen."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Registrering af fingeraftryk fik timeout. Prøv igen."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Leverandørspecifik fejlmeddelelse."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"læse indstillinger for synkronisering"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Tillader, at appen kan læse synkroniseringsindstillingerne for en konto. Denne tilladelse kan f.eks. fastslå, om appen Personer er synkroniseret med en konto."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"slå synkronisering til og fra"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Tillader, at en app fjerner DRM-certifikater. Dette bør aldrig være nødvendigt for almindelige apps."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"knytte til et mobilselskabs beskedtjeneste"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Dette giver indehaveren mulighed for at knytte sig til det øverste grænsefladeniveau for et mobilselskabs beskedtjeneste. Dette bør ikke være nødvendigt i normale apps."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrollér længden samt tilladte tegn i adgangskoder og pinkoder til skærmlåsen."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
@@ -908,7 +944,7 @@
     <string name="phoneTypeCar" msgid="8738360689616716982">"Bil"</string>
     <string name="phoneTypeCompanyMain" msgid="540434356461478916">"Virksomhed (hovednummer)"</string>
     <string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
-    <string name="phoneTypeMain" msgid="6766137010628326916">"Hoved"</string>
+    <string name="phoneTypeMain" msgid="6766137010628326916">"Hovednr."</string>
     <string name="phoneTypeOtherFax" msgid="8587657145072446565">"Andre faxbeskeder"</string>
     <string name="phoneTypeRadio" msgid="4093738079908667513">"Radio"</string>
     <string name="phoneTypeTelex" msgid="3367879952476250512">"Telex"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Tillader, at appen kan bekræfte, at en pakke kan installeres."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind til en bekræftelse af pakker"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Tillader, at indehaveren kan sende anmodninger om bekræftelser af pakker. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"bekræft intent-filter"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Tillader, at appen kan kontrollere, om et intent-filter er bekræftet eller ej."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"knyt til en bekræfter af intent-filtre"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Tillader, at indehaveren kan sende anmodninger om bekræftelser af intent-filtre. Dette bør aldrig være nødvendigt for almindelige apps."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"adgang til serielle porte"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Tillader, at indehaveren kan få adgang til serielle porte ved hjælp af SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"adgang til indholdsleverandører eksternt"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Tidligere dag"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Senere år"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Tidligere år"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Forrige måned"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Næste måned"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Annuller"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Slet"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Cirkulær minutvælger"</string>
     <string name="select_hours" msgid="6043079511766008245">"Vælg timer"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Vælg minutter"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Månedsgitter med dage"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Liste over år"</string>
     <string name="select_day" msgid="7774759604701773332">"Vælg måned og dag"</string>
     <string name="select_year" msgid="7952052866994196170">"Vælg år"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> er valgt"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> er slettet"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> – arbejde"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Hvis du vil frigøre dette skærmbillede, skal du trykke på Tilbage og Oversigt på samme tid og holde fingeren nede."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 07153fe..88aea31 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Roaming-Banner aus"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Suche nach Dienst"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"WLAN-Telefonie"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nicht weitergeleitet"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> nach <xliff:g id="TIME_DELAY">{2}</xliff:g> Sekunden."</string>
@@ -203,7 +214,7 @@
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flugmodus ist AN."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist AUS."</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Einstellungen"</string>
-    <string name="global_action_assist" msgid="3892832961594295030">"Geräteassistent"</string>
+    <string name="global_action_assist" msgid="3892832961594295030">"Assistent"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Sprachassistent"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Jetzt sperren"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Ermöglicht der App, Bilder und Videos mit der Kamera aufzunehmen. Die Berechtigung erlaubt der App, die Kamera jederzeit und ohne Ihre Bestätigung zu nutzen."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"LED-Anzeige für Übertragung bei Kameranutzung deaktivieren"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Vorinstallierte System-Apps können die LED-Anzeige für die Kameranutzung deaktivieren."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Ermöglicht vorinstallierten System-Apps, Systemereignisse an den Kameradienst zu senden"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"Tablet dauerhaft deaktivieren"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"Fernseher dauerhaft deaktivieren"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"Telefon dauerhaft deaktivieren"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA-TV-Einrichtung direkt starten"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA-Telefoneinrichtung direkt starten"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Ermöglicht der App, die CDMA-Bereitstellung zu starten. Schädliche Apps können so die CDMA-Bereitstellung unnötigerweise starten."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"Benachrichtigungen für Standortaktualisierung steuern"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Ermöglicht der App, Mobilfunkbenachrichtigungen über Standort-Updates zu aktivieren bzw. zu deaktivieren. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"Auf Check-in-Eigenschaften zugreifen"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Erlaubt der App, Methoden zum Hinzufügen und Löschen zu verwendender Fingerabdruckvorlagen aufzurufen"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Fingerabdruckhardware verwenden"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Erlaubt der App, Fingerabdruckhardware zur Authentifizierung zu verwenden"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Fingerabdruck teilweise erkannt. Versuchen Sie es erneut."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Fingerabdruck konnte nicht verarbeitet werden. Versuchen Sie es erneut."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingerabdrucksensor ist verschmutzt. Reinigen Sie ihn und versuchen Sie es erneut."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Finger zu schnell bewegt. Versuchen Sie es erneut."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Finger zu langsam bewegt. Versuchen Sie es erneut."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Anbieterspezifische Erfassungsfehlermeldung 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Unbrauchbar. Versuchen Sie es erneut."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware nicht verfügbar"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerabdruck kann nicht gespeichert werden. Entfernen Sie einen vorhandenen Fingerabdruck."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Zeitüberschreitung für Fingerabdruck. Versuchen Sie es erneut."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Zeitüberschreitung für Fingerabdruck. Versuchen Sie es erneut."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Anbieterspezifische Fehlermeldung"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Synchronisierungseinstellungen lesen"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Ermöglicht der App, die Synchronisierungseinstellungen eines Kontos zu lesen. Beispielsweise kann damit festgestellt werden, ob Kontakte mit einem Konto synchronisiert werden."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"Synchronisierung aktivieren oder deaktivieren"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Ermöglicht einer App das Entfernen von DRM-Zertifikaten. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"An einen Mobilfunkanbieter-SMS/MMS-Dienst binden"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Ermöglicht dem Inhaber die Bindung an die Oberfläche eines Mobilfunkanbieter-SMS/MMS-Dienstes auf oberster Ebene. Für normale Apps sollte dies nie erforderlich sein."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Zulässige Länge und Zeichen für Passwörter für die Displaysperre festlegen"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Ermöglicht der App die Überprüfung, ob ein Paket installiert werden kann"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"An Paketprüfung binden"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Ermöglicht dem Halter, Anfragen für die Paketprüfung zu senden. Sollte nie für normale Apps benötigt werden."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"Intent-Filter verifizieren"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Ermöglicht einer App, zu überprüfen, ob ein Intent-Filter verifiziert wurde"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"An Intent-Filter-Verifizierung binden"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Ermöglicht dem Inhaber, Anfragen für die Verifizierung von Intent-Filtern zu senden. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"Zugriff auf serielle Schnittstellen"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Ermöglicht dem Inhaber den Zugriff auf serielle Schnittstellen über das SerialManager-API"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"Extern auf Content-Anbieter zugreifen"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Tag verringern"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Jahr verlängern"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Jahr verringern"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Vormonat"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Nächster Monat"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Abbrechen"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Löschen"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Kreisförmiger Schieberegler für Minuten"</string>
     <string name="select_hours" msgid="6043079511766008245">"Stunden auswählen"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Minuten auswählen"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Monatsraster mit einzelnen Tagen"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Jahresliste"</string>
     <string name="select_day" msgid="7774759604701773332">"Monat und Tag auswählen"</string>
     <string name="select_year" msgid="7952052866994196170">"Jahr auswählen"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ausgewählt"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> gelöscht"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Um die Fixierung dieses Bildschirms aufzuheben, berühren und halten Sie gleichzeitig \"Zurück\" und \"Übersicht\"."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index e0a6f88..4c805e8 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Διαφημιστικό πλαίσιο περιαγωγής απενεργοποιημένο"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Αναζήτηση υπηρεσιών"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Κλήση Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Δεν προωθήθηκε"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> μετά από <xliff:g id="TIME_DELAY">{2}</xliff:g> δευτερόλεπτα"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Επιτρέπει στην εφαρμογή τη λήψη φωτογραφιών και βίντεο με τη φωτογραφική μηχανή. Αυτή η άδεια δίνει τη δυνατότητα στην εφαρμογή να χρησιμοποιεί τη φωτογραφική μηχανή ανά πάσα στιγμή χωρίς την έγκρισή σας."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"απενεργοποίηση ένδειξης LED μετάδοσης όταν χρησιμοποιείται η φωτογραφική μηχανή"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Επιτρέπει σε μια προεγκατεστημένη εφαρμογή συστήματος να απενεργοποιήσει την ένδειξη LED χρήσης της φωτογραφικής μηχανής."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Επιτρέπει σε μια προεγκατεστημένη εφαρμογή συστήματος να αποστέλλει στην υπηρεσία κάμερας συμβάντα συστήματος."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"μόνιμη απενεργοποίηση του tablet"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"μόνιμη απενεργοποίηση της τηλεόρασης"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"μόνιμη απενεργοποίηση τηλεφώνου"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"άμεση έναρξη της ρύθμισης CDMA της τηλεόρασης"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"άμεση έναρξη της εγκατάστασης τηλεφώνου CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Επιτρέπει στην εφαρμογή να ξεκινήσει την παροχή CDMA. Κακόβουλες εφαρμογές ενδέχεται να ξεκινήσουν την παροχή CDMA χωρίς λόγο"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"έλεγχος ειδοποιήσεων ενημέρωσης τοποθεσίας"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Επιτρέπει στην εφαρμογή την ενεργοποίηση/απενεργοποίηση των ειδοποιήσεων ενημέρωσης τοποθεσίας από το ραδιόφωνο. Δεν προορίζεται για χρήση από συνήθεις εφαρμογές."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"πρόσβαση σε ιδιότητες ελέγχου εισόδου"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Επιτρέπει στην εφαρμογή να επικαλείται μεθόδους για την προσθήκη και τη διαγραφή προτύπων μοναδικού χαρακτηριστικού για χρήση."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"χρήση εξοπλισμού μοναδικού χαρακτηριστικού"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί εξοπλισμό μοναδικού χαρακτηριστικού για έλεγχο ταυτότητας"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Εντοπίστηκε μερικό μοναδικό χαρακτηριστικό. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Δεν ήταν δυνατή η επεξεργασία του μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Ο αισθητήρας μοναδικού χαρακτηριστικού δεν είναι καθαρός. Καθαρίστε τον και δοκιμάστε ξανά."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Πολύ γρήγορη κίνηση δαχτύλου. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Πολύ αργή κίνηση δαχτύλου. Δοκιμάστε ξανά."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Μήνυμα σφάλματος εξαγοράς για συγκεκριμένο προμηθευτή 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Δεν είναι δυνατή η επεξεργασία. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Ο εξοπλισμός δεν είναι διαθέσιμος."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Δεν είναι δυνατή η αποθήκευση μοναδικού χαρακτηριστικού. Καταργήστε το υπάρχον μοναδικό χαρακτηριστικό."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Λήξη χρονικού ορίου μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Λήξη χρονικού ορίου μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Μήνυμα σφάλματος για συγκεκριμένο προμηθευτή."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ανάγνωση ρυθμίσεων συγχρονισμού"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Επιτρέπει στην εφαρμογή την ανάγνωση των ρυθμίσεων συγχρονισμού για έναν λογαριασμό. Για παράδειγμα, αυτό μπορεί να καθορίσει εάν η εφαρμογή \"Άτομα\" είναι συγχρονισμένη με έναν λογαριασμό."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"εναλλαγή ενεργοποίησης και απενεργοποίησης συγχρονισμού"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Επιτρέπει σε μια εφαρμογή την κατάργηση πιστοποιητικών DRM. Δεν χρειάζεται ποτέ για κανονικές εφαρμογές."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"δέσμευση σε υπηρεσία ανταλλαγής μηνυμάτων εταιρείας κινητής τηλεφωνίας"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας ανταλλαγής μηνυμάτων εταιρείας κινητής τηλεφωνίας. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ελέγξτε την έκταση και τους επιτρεπόμενους χαρακτήρες σε κωδικούς πρόσβασης κλειδώματος οθόνης και PIN."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Επιτρέπει στην εφαρμογή να επαληθεύσει τη δυνατότητα εγκατάστασης ενός πακέτου."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"δέσμευση με επαλήθευση πακέτου"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Επιτρέπει στον κάτοχο να υποβάλλει ερωτήματα σε προγράμματα επαλήθευσης πακέτου. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"επαλήθευση φίλτρου πρόθεσης"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Επιτρέπει στην εφαρμογή να ελέγχει εάν ένα φίλτρο πρόθεσης είναι επαληθευμένο ή όχι."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"σύνδεση σε προγρ.επαλήθ.φίλτρου πρόθεσης"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Επιτρέπει στον κάτοχο να υποβάλλει ερωτήματα σε προγράμματα επαλήθευσης φίλτρων πρόθεσης. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"πρόσβαση στις σειριακές θύρες"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Επιτρέπει στον κάτοχο την πρόσβαση στις σειριακές θύρες με τη χρήση του SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"εξωτερική πρόσβαση σε παρόχους περιεχ."</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Μείωση ημέρας"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Αύξηση έτους"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Μείωση έτους"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Προηγούμενος μήνας"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Επόμενος μήνας"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Ακύρωση"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Διαγραφή"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Κυκλικό ρυθμιστικό λεπτών"</string>
     <string name="select_hours" msgid="6043079511766008245">"Επιλογή ωρών"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Επιλογή λεπτών"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Πλέγμα ημερών του μήνα"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Λίστα ετών"</string>
     <string name="select_day" msgid="7774759604701773332">"Επιλογή μήνα και ημέρας"</string>
     <string name="select_year" msgid="7952052866994196170">"Επιλογή έτους"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Επιλέχτηκε το στοιχείο <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> διαγράφηκε"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Εργασία <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Για να ξεκαρφιτσώσετε αυτήν την οθόνη, πατήστε παρατεταμένα \"Επιστροφή\" και \"Επισκόπηση\" ταυτόχρονα."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index f52daf6..082c024 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -124,8 +124,15 @@
     <string name="roamingText12" msgid="1189071119992726320">"Roaming Banner Off"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Searching for Service"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi Calling"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Off"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi preferred"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="5920549484600758786">"Mobile preferred"</string>
+    <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Wi-Fi only"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
@@ -584,6 +591,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Allows the app to take pictures and videos with the camera. This permission allows the app to use the camera at any time without your confirmation."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"disable transmit indicator LED when camera is in use"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Allows a pre-installed system application to disable the camera use indicator LED."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Allows a pre-installed system application to send the camera service system events."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"permanently disable tablet"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"permanently disable TV"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"permanently disable phone"</string>
@@ -632,6 +640,8 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"directly start CDMA TV setup"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"directly start CDMA phone setup"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Allows the app to start CDMA provisioning. Malicious apps may unnecessarily start CDMA provisioning."</string>
+    <string name="permlab_performSimActivation" msgid="1651116521896665009">"start SIM card setup"</string>
+    <string name="permdesc_performSimActivation" msgid="1778214876348917401">"Allows the app to handle SIM activation requests. The app may directly perform activation or may delegate to another app."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"control location update notifications"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Allows the app to enable/disable location update notifications from the radio. Not for use by normal apps."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"access check-in properties"</string>
@@ -746,6 +756,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Allows the app to invoke methods to add and delete fingerprint templates for use."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"use fingerprint hardware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Allows the app to use fingerprint hardware for authentication"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingerprint sensor is dirty. Please clean and try again."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Finger moved to fast. Please try again."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Finger moved to slow. Please try again."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Vendor-specific acquisition error message 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Unable to process. Try again."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware not available."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Fingerprint timeout reached. Try again."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Vendor-specific error message."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"read sync settings"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"toggle sync on and off"</string>
@@ -822,6 +848,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"bind to a carrier messaging service"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"interact with voice interaction service"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"Allows the holder to interact with the currently active voice interaction service. Should never be needed for normal apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
@@ -1119,6 +1147,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Allows the app to verify a package is installable."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind to a package verifier"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Allows the holder to make requests of package verifiers. Should never be needed for normal apps."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verify intent filter"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Allows the app to check if an intent filter is verified or not."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"bind to an intent filter verifier"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Allows the holder to make requests of intent filter verifiers. Should never be needed for normal apps."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"access serial ports"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Allows the holder to access serial ports using the SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"access content providers externally"</string>
@@ -1544,6 +1576,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Decrease day"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Increase year"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Decrease year"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Previous month"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Next month"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Cancel"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1794,11 +1828,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Minutes circular slider"</string>
     <string name="select_hours" msgid="6043079511766008245">"Select hours"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Select minutes"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Month grid of days"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Year list"</string>
     <string name="select_day" msgid="7774759604701773332">"Select month and day"</string>
     <string name="select_year" msgid="7952052866994196170">"Select year"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selected"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"To unpin this screen, touch and hold Back and Overview at the same time."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index f52daf6..082c024 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -124,8 +124,15 @@
     <string name="roamingText12" msgid="1189071119992726320">"Roaming Banner Off"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Searching for Service"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi Calling"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Off"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi preferred"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="5920549484600758786">"Mobile preferred"</string>
+    <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Wi-Fi only"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
@@ -584,6 +591,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Allows the app to take pictures and videos with the camera. This permission allows the app to use the camera at any time without your confirmation."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"disable transmit indicator LED when camera is in use"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Allows a pre-installed system application to disable the camera use indicator LED."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Allows a pre-installed system application to send the camera service system events."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"permanently disable tablet"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"permanently disable TV"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"permanently disable phone"</string>
@@ -632,6 +640,8 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"directly start CDMA TV setup"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"directly start CDMA phone setup"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Allows the app to start CDMA provisioning. Malicious apps may unnecessarily start CDMA provisioning."</string>
+    <string name="permlab_performSimActivation" msgid="1651116521896665009">"start SIM card setup"</string>
+    <string name="permdesc_performSimActivation" msgid="1778214876348917401">"Allows the app to handle SIM activation requests. The app may directly perform activation or may delegate to another app."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"control location update notifications"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Allows the app to enable/disable location update notifications from the radio. Not for use by normal apps."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"access check-in properties"</string>
@@ -746,6 +756,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Allows the app to invoke methods to add and delete fingerprint templates for use."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"use fingerprint hardware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Allows the app to use fingerprint hardware for authentication"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingerprint sensor is dirty. Please clean and try again."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Finger moved to fast. Please try again."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Finger moved to slow. Please try again."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Vendor-specific acquisition error message 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Unable to process. Try again."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware not available."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Fingerprint timeout reached. Try again."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Vendor-specific error message."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"read sync settings"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"toggle sync on and off"</string>
@@ -822,6 +848,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"bind to a carrier messaging service"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"interact with voice interaction service"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"Allows the holder to interact with the currently active voice interaction service. Should never be needed for normal apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
@@ -1119,6 +1147,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Allows the app to verify a package is installable."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind to a package verifier"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Allows the holder to make requests of package verifiers. Should never be needed for normal apps."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verify intent filter"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Allows the app to check if an intent filter is verified or not."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"bind to an intent filter verifier"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Allows the holder to make requests of intent filter verifiers. Should never be needed for normal apps."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"access serial ports"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Allows the holder to access serial ports using the SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"access content providers externally"</string>
@@ -1544,6 +1576,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Decrease day"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Increase year"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Decrease year"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Previous month"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Next month"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Cancel"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1794,11 +1828,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Minutes circular slider"</string>
     <string name="select_hours" msgid="6043079511766008245">"Select hours"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Select minutes"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Month grid of days"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Year list"</string>
     <string name="select_day" msgid="7774759604701773332">"Select month and day"</string>
     <string name="select_year" msgid="7952052866994196170">"Select year"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selected"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"To unpin this screen, touch and hold Back and Overview at the same time."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index f52daf6..082c024 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -124,8 +124,15 @@
     <string name="roamingText12" msgid="1189071119992726320">"Roaming Banner Off"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Searching for Service"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi Calling"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Off"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi preferred"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="5920549484600758786">"Mobile preferred"</string>
+    <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Wi-Fi only"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
@@ -584,6 +591,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Allows the app to take pictures and videos with the camera. This permission allows the app to use the camera at any time without your confirmation."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"disable transmit indicator LED when camera is in use"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Allows a pre-installed system application to disable the camera use indicator LED."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Allows a pre-installed system application to send the camera service system events."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"permanently disable tablet"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"permanently disable TV"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"permanently disable phone"</string>
@@ -632,6 +640,8 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"directly start CDMA TV setup"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"directly start CDMA phone setup"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Allows the app to start CDMA provisioning. Malicious apps may unnecessarily start CDMA provisioning."</string>
+    <string name="permlab_performSimActivation" msgid="1651116521896665009">"start SIM card setup"</string>
+    <string name="permdesc_performSimActivation" msgid="1778214876348917401">"Allows the app to handle SIM activation requests. The app may directly perform activation or may delegate to another app."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"control location update notifications"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Allows the app to enable/disable location update notifications from the radio. Not for use by normal apps."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"access check-in properties"</string>
@@ -746,6 +756,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Allows the app to invoke methods to add and delete fingerprint templates for use."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"use fingerprint hardware"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Allows the app to use fingerprint hardware for authentication"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingerprint sensor is dirty. Please clean and try again."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Finger moved to fast. Please try again."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Finger moved to slow. Please try again."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Vendor-specific acquisition error message 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Unable to process. Try again."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware not available."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerprint can\'t be stored. Please remove an existing fingerprint."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Fingerprint timeout reached. Try again."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Vendor-specific error message."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"read sync settings"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Allows the app to read the sync settings for an account. For example, this can determine whether the People app is synced with an account."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"toggle sync on and off"</string>
@@ -822,6 +848,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Allows an application to remove DRM certficates. Should never be needed for normal apps."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"bind to a carrier messaging service"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"interact with voice interaction service"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"Allows the holder to interact with the currently active voice interaction service. Should never be needed for normal apps."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
@@ -1119,6 +1147,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Allows the app to verify a package is installable."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind to a package verifier"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Allows the holder to make requests of package verifiers. Should never be needed for normal apps."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verify intent filter"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Allows the app to check if an intent filter is verified or not."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"bind to an intent filter verifier"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Allows the holder to make requests of intent filter verifiers. Should never be needed for normal apps."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"access serial ports"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Allows the holder to access serial ports using the SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"access content providers externally"</string>
@@ -1544,6 +1576,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Decrease day"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Increase year"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Decrease year"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Previous month"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Next month"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Cancel"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1794,11 +1828,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Minutes circular slider"</string>
     <string name="select_hours" msgid="6043079511766008245">"Select hours"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Select minutes"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Month grid of days"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Year list"</string>
     <string name="select_day" msgid="7774759604701773332">"Select month and day"</string>
     <string name="select_year" msgid="7952052866994196170">"Select year"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selected"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"To unpin this screen, touch and hold Back and Overview at the same time."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index ce419dc..837fbac 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Banner de roaming desactivado"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Buscando servicio"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Llamada por Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha remitido"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> después de <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Permite que la aplicación saque fotos o grabe videos con la cámara. Este permiso autoriza a la aplicación a utilizar la cámara en cualquier momento sin tu confirmación."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"Inhabilitar el indicador LED de transmisión mientras se utiliza la cámara"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Permite que una aplicación del sistema instalada previamente inhabilite el indicador LED de uso de la cámara."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Permite que una aplicación del sistema preinstalada envíe eventos del sistema al servicio de cámara."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"desactivar tablet de forma permanente"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"inhabilitar la TV permanentemente"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"desactivar dispositivo de manera permanente"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"iniciar directamente la configuración de la TV CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directamente la configuración CDMA del dispositivo"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Permite que la aplicación inicie el método de acceso CDMA. Las aplicaciones maliciosas pueden iniciar el método CDMA de forma innecesaria."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar las notificaciones de actualización de ubicación"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permite que la aplicación habilite/deshabilite notificaciones de actualización de ubicación de la radio. Las aplicaciones normales no deben utilizar este permiso."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"acceder a las propiedades de protección"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que la aplicación emplee métodos para agregar y eliminar plantillas de huellas digitales para su uso."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utilizar hardware de huellas digitales"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que la aplicación utilice el hardware de huellas digitales para realizar la autenticación."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"La huella digital se detectó parcialmente. Vuelve a intentarlo."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No se pudo procesar la huella digital. Vuelve a intentarlo."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"El sensor de huellas digitales está sucio. Limpia el sensor y vuelve a intentarlo."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Moviste el dedo muy rápido. Vuelve a intentarlo."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Moviste el dedo muy despacio. Vuelve a intentarlo."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Mensaje de error de adquisición específico del proveedor 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"No se puede procesar. Vuelve a intentarlo."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"El hardware no está disponible."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"No se puede almacenar la huella digital. Elimina una de las existentes."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Finalizó el tiempo de espera para la huella digital. Vuelve a intentarlo."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Finalizó el tiempo de espera para la huella digital. Vuelve a intentarlo."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Mensaje de error específico del proveedor"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Este permiso permite que la aplicación consulte la configuración de sincronización de una cuenta. Esto permite, por ejemplo, determinar si la aplicación Personas está sincronizada con una cuenta."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activar y desactivar la sincronización"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permite que una aplicación elimine certificados DRM. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"vincular al servicio de mensajería del proveedor"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permite al propietario vincularse a la interfaz de nivel superior del servicio de mensajería del proveedor. Las aplicaciones regulares no lo necesitan."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Permite controlar la longitud y los caracteres permitidos en las contraseñas y los PIN para el bloqueo de pantalla."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite que la aplicación verifique si se puede instalar un paquete."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"Vincular a un verificador de paquetes"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite que el titular solicite verificadores de paquetes. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verificar filtro de intento"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Permite que la aplicación compruebe si se verificó un filtro de intento."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"vincular a verificador filtro de intento"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Permite que el titular solicite verificadores de filtros de intentos. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"Acceder a los puertos serie"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite acceder a puertos serie a través de la API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"acceder a proveedores externamente"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reducir día"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumentar año"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reducir año"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Mes anterior"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Mes siguiente"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Cancelar"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Eliminar"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Control deslizante circular de minutos"</string>
     <string name="select_hours" msgid="6043079511766008245">"Seleccionar horas"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Seleccionar minutos"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Cuadrícula mensual de días"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Lista de años"</string>
     <string name="select_day" msgid="7774759604701773332">"Seleccionar mes y día"</string>
     <string name="select_year" msgid="7952052866994196170">"Seleccionar año"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionado"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> borrado"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Para dejar de fijar esta pantalla, mantén presionados los botones para volver y Recientes al mismo tiempo."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index e22ea21..c54976a 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Banner de itinerancia desactivado"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Buscando servicio"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Llamadas Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: No desviada"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> transcurridos <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Permite que la aplicación haga fotos o grabe vídeos con la cámara. Este permiso autoriza a la aplicación a utilizar la cámara en cualquier momento sin tu confirmación."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"inhabilitar el indicador LED de transmisión mientras se utiliza la cámara"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Permite que una aplicación de sistema instalada previamente inhabilite el indicador LED que advierte del uso de la cámara."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Permite que una aplicación del sistema preinstalada envíe eventos del sistema al servicio de cámara."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"inhabilitar tablet de forma permanente"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"inhabilitar permanentemente la TV"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"inhabilitar el teléfono de forma permanente"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"iniciar directamente la configuración CDMA de la TV"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directamente el método de acceso CDMA del teléfono"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Permite que la aplicación inicie el método de acceso CDMA. Las aplicaciones malintencionadas pueden iniciar el método CDMA inútilmente."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar las notificaciones de actualización de la ubicación"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permite que la aplicación habilite o inhabilite las notificaciones de actualización de la señal móvil. Las aplicaciones normales no deben usar este permiso."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"acceder a propiedades de registro"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que la aplicación invoque métodos para añadir y eliminar plantillas de huellas digitales y utilizarlas."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"utilizar hardware de huellas digitales"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que la aplicación utilice el hardware de huellas digitales para realizar la autenticación"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Se ha detectado una huella digital parcial. Vuelve a intentarlo."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No se ha podido procesar la huella digital. Vuelve a intentarlo."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"El sensor de huellas digitales está sucio. Límpialo y vuelve a intentarlo."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Has movido el dedo muy rápido. Vuelve a intentarlo."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Has movido el dedo muy despacio. Vuelve a intentarlo."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Mensaje de error de adquisición específico del proveedor: 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"No se puede procesar la huella digital. Vuelve a intentarlo."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware no disponible."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"No se puede almacenar la huella digital. Elimina una ya creada."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Se ha alcanzado el tiempo de espera de la huella digital. Vuelve a intentarlo."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Se ha alcanzado el tiempo de espera de la huella digital. Vuelve a intentarlo."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Mensaje de error específico del proveedor."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permite que la aplicación consulte la configuración de sincronización de una cuenta. La aplicación puede utilizar este permiso, por ejemplo, para determinar si la aplicación Contactos está sincronizada con una cuenta."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activar y desactivar la sincronización"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permite a una aplicación eliminar los certificados DRM. Las aplicaciones normales no deberí­an necesitar este permiso."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"enlazar con el servicio de mensajería de un operador"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permite enlazar con la interfaz de nivel superior del servicio de mensajería de un operador. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla la longitud y los caracteres permitidos en los PIN y en las contraseñas de bloqueo de pantalla."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite que la aplicación verifique si se puede instalar un paquete."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"enlazar con un detector de paquetes"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite que se envíen solicitudes de detectores de paquetes. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verificar filtro de intento"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Permite que la aplicación compruebe si un filtro de intento se ha verificado."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"enlazar con detector filtro de intento"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Permite que se envíen solicitudes de detectores de filtros de intentos. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"acceder a puertos serie"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite acceder a puertos serie a través de SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"acceder a proveedores de contenido externamente"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reducir días"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumentar año"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reducir año"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Mes anterior"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Próximo mes"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Cancelar"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Eliminar"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Control deslizante circular de minutos"</string>
     <string name="select_hours" msgid="6043079511766008245">"Seleccionar horas"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Seleccionar minutos"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Cuadrícula mensual de días"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Lista de años"</string>
     <string name="select_day" msgid="7774759604701773332">"Seleccionar mes y día"</string>
     <string name="select_year" msgid="7952052866994196170">"Seleccionar año"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionado"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Para desactivar esta pantalla, mantén pulsados los botones de retroceso y Visión general al mismo tiempo."</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 85b5c3c..0e1ecec6 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Rändlusbänner väljas"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Teenuse otsimine"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"WiFi-kõned"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: pole suunatud"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundi pärast"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Võimaldab rakendusel teha kaameraga pilte ja videoid. See luba võimaldab rakendusel kasutada kaamerat mis tahes ajal teie kinnituseta."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"keela kaamera kasutamisel näidikutule kasutamine"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Lubab eelinstallitud süsteemirakendusel keelata kaamera näidikutule kasutamise."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Lubab eelinstallitud süsteemirakendusel saata kaamerateenuse süsteemi sündmusi."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"blokeeri tahvelarvuti jäädavalt"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"teleri alaline keelamine"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"blokeeri telefon jäädavalt"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA TV seadistamise otsekäivitus"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA-telefoniseadistuse otse käivitamine"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Võimaldab rakendusel käivitada CDMA ettevalmistamise. Pahatahtlikud rakendused võivad CDMA ettevalmistamise asjatult käivitada."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"kontrolli asukoha värskendamise teatisi"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Võimaldab rakendusel lubada/keelata asukoha värskendamise teatised raadiost. Mitte kasutada tavarakenduste puhul."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"juurdepääs registreerimisatribuutidele"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Võimaldab rakendusel tühistada meetodid kasutatavate sõrmejäljemallide lisamiseks ja kustutamiseks."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"sõrmejälje riistvara kasutamine"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Võimaldab rakendusel autentimiseks kasutada sõrmejälje riistvara"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Tuvastati osaline sõrmejälg. Proovige uuesti."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Sõrmejälge ei õnnestunud töödelda. Proovige uuesti."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sõrmejäljeandur on must. Puhastage see ja proovige uuesti."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Sõrm liikus liiga kiiresti. Proovige uuesti."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Sõrm liikus liiga aeglaselt. Proovige uuesti."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Teenusepakkujapõhise värbamise veateade 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Töötlemine ei õnnestu. Proovige uuesti."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Riistvara pole saadaval."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sõrmejälge ei saa salvestada. Eemaldage olemasolev sõrmejälg."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sõrmejälje riistvara taimeri ajalõpp. Proovige uuesti."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Sõrmejälje riistvara taimeri ajalõpp. Proovige uuesti."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Teenusepakkujapõhine veateade."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"loe sünkroonimisseadeid"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Võimaldab rakendusel lugeda konto sünkroonimisseadeid. Näiteks võib see määrata, kas rakendus Inimesed on kontoga sünkroonitud."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"lülitage sünkroonimine sisse ja välja"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Lubab rakendusel eemaldada DRM-sertifikaate. Pole kunagi vajalik tavaliste rakenduste puhul."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"seose loomine operaatori sõnumisideteenusega"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Lubab omanikul luua seose operaatori sõnumisideteenuse ülataseme liidesega. Pole kunagi vajalik tavalise rakenduse puhul."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parooli reeglite määramine"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Juhitakse ekraaniluku paroolide ja PIN-koodide pikkusi ning lubatud tähemärkide seadeid."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekraani avamiskatsed"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Võimaldab rakendusel kinnitada, et paketti saab installida."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"sidumine paketi kinnitajaga"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Lubab omanikul teha taotlusi paketi kinnitajate kohta. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"kavatsuste filtri kinnitamine"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Võimaldab rakendusel kontrollida, kas kavatsuste filter on kinnitatud või mitte."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"sidumine kavatsuste filtri kinnitajaga"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Võimaldab omanikul teha taotlusi kavatsuste filtri kinnitajate kohta. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"juurdepääs jadaportidele"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Võimaldab omanikul SerialManageri API-liidese abil jadaportidele juurde pääseda."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"väline juurdepääs sisupakkujatele"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Päeva vähendamine"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aasta suurendamine"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Aasta vähendamine"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Eelmine kuu"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Järgmine kuu"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Tühista"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Kustuta"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Ringikujuline minutiliugur"</string>
     <string name="select_hours" msgid="6043079511766008245">"Tundide valimine"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Minutite valimine"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Päevad kuu ruudustikus"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Aastate loend"</string>
     <string name="select_day" msgid="7774759604701773332">"Kuu ja päeva valimine"</string>
     <string name="select_year" msgid="7952052866994196170">"Aasta valimine"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> on valitud"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> on kustutatud"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Ekraanikuva vabastamiseks puudutage pikalt samal ajal nuppe Tagasi ja Ülevaade."</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 02d8dd3..a6cb111 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Ibiltaritzari buruzko jakinarazpena desaktibatuta"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Zerbitzu bila"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi bidezko deiak"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ez da desbideratu"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> zenbakira <xliff:g id="TIME_DELAY">{2}</xliff:g> segundotan"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Kamerarekin argazkiak ateratzeko eta bideoak grabatzeko baimena ematen die aplikazioei. Baimen horrekin, aplikazioak kamera edonoiz erabil dezake zure baimenik gabe."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"Desgaitu LED argi adierazlea kamera abian denean"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Kamera erabiltzen ari dela adierazten duen LED argia desgaitzeko aukera ematen dio sisteman aurrez instalatutako aplikazio bati."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Kamerara sistemako gertaerak bidaltzeko aukera ematen dio sisteman aurrez instalatutako aplikazio bati."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"desgaitu telefonoa behin betiko"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"Desgaitu telebista betiko"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"desgaitu telefonoa behin betiko"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"Hasi zuzenean telebista CDMA bidez konfiguratzen"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"hasi zuzenean CDMA bidezko telefono-konfigurazioa"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"CDMA horniketa hastea baimentzen die aplikazioei. Aplikazio gaiztoek CDMA horniketa has dezakete behar ez denean ere."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"Kontrolatu kokapen-eguneratzeen jakinarazpenak"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Kokapenari buruz irratiak bidalitako informazio eguneratuaren jakinarazpenak gaitzea edo desgaitzea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"atzitu erregistratze-propietateak"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Hatz-marka digitalen txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Erabili hatz-marka digitalen hardwarea"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autentifikatzeko hatz-marka digitalen hardwarea erabiltzea baimentzen die aplikazioei."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Hatz-marka digitala ez da osorik hauteman. Saiatu berriro."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Ezin izan da hatza-marka prozesatu. Saiatu berriro."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Hatz-marka digitalen sentsorea zikina dago. Garbi ezazu, eta saiatu berriro."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Hatza bizkorregi mugitu duzu. Saiatu berriro."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Hatza mantsoegi mugitu duzu. Saiatu berriro."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Saltzailearen berariazko errore-mezua, erosketarekin erlazionatuta"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Ezin da prozesatu. Saiatu berriro."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardwarea ez dago erabilgarri."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ezin da gorde hatz-marka digitala. Kendu lehendik gordeta duzunetako bat."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Hatz-marka digitalak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Hatz-marka digitalak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Saltzailearen berariazko errore-mezua."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Irakurri sinkronizazio-ezarpenak"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Kontu baten sinkronizazio-ezarpenak irakurtzeko baimena ematen die aplikazioei. Adibidez, Jendea aplikazioa konturen batekin sinkronizatuta dagoen zehatz dezake."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"sinkronizazioa aktibatzea eta desaktibatzea"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM ziurtagiriak kentzea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"lotu operadorearen mezularitza-zerbitzuari"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Operadore baten mezularitza-zerbitzuaren goi-mailako interfazeari lotzea baimentzen die erabiltzaileei. Aplikazio normalek ez lukete inoiz beharko."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ezarri pasahitzen arauak"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolatu pantaila blokeoaren pasahitzen eta PINen luzera eta onartutako karaktereak."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Kontrolatu pantaila desblokeatzeko saiakerak"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Paketeak instala daitezkeen egiaztatzea baimentzen die aplikazioei."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"lotu pakete-egiaztatzaile batekin"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Pakete-egiaztatzaileei eskaerak egitea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"Egiaztatu saiakera-iragazkia"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Saiakera-iragazki bat egiaztatuta dagoen ala ez egiaztatzea baimentzen die aplikazioei."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"Lotu saiakera-iragazkien egiaztatzaile bati"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Saiakera-iragazkien egiaztatzaileei eskaerak egitea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"atzitu serie-atakak"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Jabeari serieko atakak atzitzeko aukera ematen dio SerialManager APIa erabilita."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"eduki-hornitzaileak kanpotik atzitzea"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Atzeratu egun bat"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aurreratu urtebete"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Atzeratu urtebete"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Aurreko hilabetea"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Hurrengo hilabetea"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Utzi"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Ezabatu"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Minutuak aukeratzeko ikuspegi zirkularra"</string>
     <string name="select_hours" msgid="6043079511766008245">"Hautatu orduak"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Hautatu minutuak"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Hilabete-ikuspegiko eguna aukeratzeko sareta"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Urteen zerrenda"</string>
     <string name="select_day" msgid="7774759604701773332">"Hautatu hilabetea eta eguna"</string>
     <string name="select_year" msgid="7952052866994196170">"Hautatu urtea"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> hautatu da"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ezabatu da"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Laneko <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Aingura kentzeko, eduki ukituta Atzera eta Ikuspegi orokorra botoiak aldi berean."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 2073b5e..8a915af 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"اعلان رومینگ خاموش"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"جستجوی سرویس"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"‏تماس از طریق Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: هدایت نشده"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> پس از <xliff:g id="TIME_DELAY">{2}</xliff:g> ثانیه"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"به برنامه اجازه می‌دهد با دوربین به عکسبرداری و فیلمبرداری بپردازد. این مجوز به برنامه اجازه می‌‌دهد از دوربین در هر زمانی بدون تأیید شما استفاده کند."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"‏LED نشانگر انتقال داده، هنگام استفاده از دوربین غیرفعال شود"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"‏به یک برنامه سیستم از قبل نصب شده اجازه می‌دهد LED نشانگر استفاده از دوربین را غیرفعال کند."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"به یک برنامه کاربردی سیستم از قبل نصب شده اجازه می‌دهد رویدادهای سیستم را به سرویس دوربین ارسال کند."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"غیر فعال کردن دائم رایانهٔ لوحی"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"غیرفعالسازی دائم تلویزیون"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"تلفن بطور دائمی غیرفعال شود"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"‏شروع مستقیم راه‌اندازی تلویزیون CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"‏شروع مستقیم راه‌اندازی تلفن CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"‏به برنامه اجازه می‎دهد تا شرایط مقررات CDMA را شروع کند. برنامه‎های مخرب می‎توانند شرایط مقررات CDMA را در مواقع غیرضروری شروع کند."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"کنترل اعلان‌های به‌روزرسانی مکان"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"‏به برنامه اجازه می‎دهد اعلانهای به‎روزرسانی موقعیت مکانی را از رادیو فعال/غیرفعال کند. برای استفاده برنامه‎های عادی نیست."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"دسترسی به مشخصات اعلام ورود"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"به برنامه امکان می‌دهد روش‌هایی را برای افزودن و حذف الگوهای اثر انگشت جهت استفاده، فعال کند."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"استفاده از سخت‌افزار اثر انگشت"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"به برنامه امکان می‌دهد از سخت‌افزار اثر انگشت برای احراز هویت استفاده کند"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"بخشی از اثر انگشت شناسایی شد. لطفاً دوباره امتحان کنید."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"اثرانگشت پردازش نشد. لطفاً دوباره امتحان کنید."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"حسگر اثر انگشت کثیف است. لطفاً آن را تمیز کنید و دوباره امتحان نمایید."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"انگشت خیلی سریع حرکت کرد. لطفاً دوباره امتحان کنید."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"انگشت خیلی آهسته حرکت کرد. لطفاً دوباره امتحان کنید."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"پیام خطای خرید خاص فروشنده ۰"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"پردازش ممکن نیست. دوباره امتحان کنید."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"سخت‌افزار در دسترس نیست."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ذخیره اثر انگشت ممکن نیست. لطفاً یک اثر انگشت موجود را حذف کنید."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"مهلت زمانی ثبت اثر انگشت به پایان رسید. دوباره امتحان کنید."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"مهلت زمانی ثبت اثر انگشت به پایان رسید. دوباره امتحان کنید."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"پیام خطای خاص فروشنده."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"خواندن تنظیمات همگام‌سازی"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"به برنامه اجازه می‌دهد تنظیمات را برای یک حساب بخواند. به‌عنوان مثال، این ویژگی می‌تواند تعیین کند آیا حساب «افراد» شما با یک حساب همگام‌سازی شده است."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"تغییر وضعیت همگام‌سازی بین فعال و غیرفعال"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"‏به برنامه امکان می‌دهد گواهی‌های DRM را حذف کند. نباید برای برنامه‌های عادی هیچ‌وقت لازم باشد."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"مقید به سرویس پیام‌رسانی شرکت مخابراتی"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"به کنترل‌کننده اجازه می‌دهد که به سطح بالای رابط کاربر سرویس پیام‌رسانی شرکت مخابراتی مقید شود. هرگز نباید برای برنامه‌های عادی مورد نیاز شود."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"کنترل طول و نوع نویسه‌هایی که در گذرواژه و پین قفل صفحه مجاز است."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش‌های قفل گشایی صفحه"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"به برنامه اجازه می‌دهد قابل نصب بودن بسته را تأیید کند."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"اتصال به یک تأیید کننده بسته"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"‏به دارنده اجازه می‎دهد تا تاییدکنندگان بسته را درخواست کند. برای برنامه‎های عادی نیاز نیست."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"تأیید فیلتر هدف"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"به برنامه اجازه می‌دهد بررسی کند که فیلتر هدف تأیید شده یا خیر."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"ارتباط با یک بررسی‌کننده فیلتر هدف"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"به دارنده اجازه می‌دهد بررسی‌کننده فیلتر هدف را درخواست کند. هرگز نباید برای برنامه‌های عادی مورد نیاز شود."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"دسترسی به درگاه‌های سریال"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"‏به دارنده اجازه می‌دهد با استفاده از SerialManager API به درگاه‌های سریال دسترسی داشته باشد."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"دسترسی خارجی به ارائه‌دهندگان محتوا"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"کاهش روز"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"افزایش سال"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"کاهش سال"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"ماه قبل"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"ماه بعد"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"لغو"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"لغزنده دایره‌ای دقیقه"</string>
     <string name="select_hours" msgid="6043079511766008245">"انتخاب ساعت"</string>
     <string name="select_minutes" msgid="3974345615920336087">"انتخاب دقیقه"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"جدول روزها براساس ماه"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"لیست سال‌ها"</string>
     <string name="select_day" msgid="7774759604701773332">"انتخاب ماه و روز"</string>
     <string name="select_year" msgid="7952052866994196170">"انتخاب سال"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> انتخاب شد"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> حذف شد"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> محل کار"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"برای برداشتن پین این صفحه، هم‌زمان «بازگشت» و «نمای کلی» را لمس کنید و نگه دارید."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index a2f1ccf..8a42eaf 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Roaming-banneri pois käytöstä"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Etsitään signaalia"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-puhelut"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ei siirretty"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunnin päästä"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Antaa sovelluksen ottaa kuvia ja kuvata videoita kameralla. Sovellus voi käyttää kameraa milloin tahansa ilman lupaasi."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"poista lähetyksen merkkivalo käytöstä, kun kameraa käytetään"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Antaa valmiiksi asennetun järjestelmäsovelluksen poistaa käytöstä kameran käytössäolon merkkivalon."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Antaa valmiiksi asennetun järjestelmäsovelluksen lähettää kamerapalvelulle tietoja järjestelmätapahtumista."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"poista tabletti käytöstä lopullisesti"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"Poista televisio pysyvästi käytöstä"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"poista puhelin käytöstä pysyvästi"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"Käynnistä CDMA-television asetusten määrittäminen"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"aloita CDMA-puhelimen asetuksien määrittäminen"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Antaa sovelluksen aloittaa CDMA-määrityksen. Haitalliset sovellukset voivat aloittaa tarpeettoman CDMA-määrityksen."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"hallitse sijaintien päivitysilmoituksia"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Antaa sovelluksen ottaa käyttöön / poistaa käytöstä radion sijainninpäivitysilmoitukset. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"käyttää checkin-asetuksia"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Sallii sovelluksen käyttää menetelmiä, joilla voidaan lisätä tai poistaa sormenjälkimalleja."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"sormenjälkilaitteiston käyttö"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Sallii sovelluksen käyttää sormenjälkilaitteistoa todennukseen."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Sormenjälki havaittiin vain osittain. Yritä uudelleen."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Sormenjäljen käsittely epäonnistui. Yritä uudelleen."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sormenjälkitunnistin on likainen. Puhdista tunnistin ja yritä uudelleen."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Liikutit sormea liian nopeasti. Yritä uudelleen."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Liikutit sormea liian hitaasti. Yritä uudelleen."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Toimittajakohtainen ​​hankintavirheilmoitus 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Käsittely ei onnistu. Yritä uudelleen."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Laitteisto ei ole käytettävissä."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sormenjälkeä ei voida tallentaa. Poista aiemmin lisätty sormenjälki."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sormenjälkitunnistimen toiminta aikakatkaistiin. Yritä uudelleen."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Sormenjälkitunnistimen toiminta aikakatkaistiin. Yritä uudelleen."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Toimittajakohtainen ​​virheilmoitus."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lue synkronointiasetuksia"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Antaa sovelluksen lukea tilien synkronointiasetuksia. Sovellus voi esimerkiksi määrittää, onko Henkilöt-sovellus synkronoitu tilin kanssa."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ota synkronointi käyttöön tai poista se käytöstä"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Antaa sovelluksen poistaa DRM-varmenteita. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"Operaattorin viestipalveluun sitoutuminen"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Antaa sovelluksen sitoutua operaattorin viestipalvelun ylätason liittymään. Ei tavallisten sovellusten käyttöön."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Hallinnoi ruudun ruudun lukituksen salasanoissa ja PIN-koodeissa sallittuja merkkejä ja niiden pituutta."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile ruudun lukituksen poistoyrityksiä"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Antaa sovelluksen vahvistaa, että pakkaus on asennettavissa."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"sitoudu paketin vahvistajaan"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Antaa sovelluksen tehdä pakettien vahvistuspyyntöjä. Ei tavallisten sovellusten käyttöön."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"vahvista aikomussuodatin"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Antaa sovelluksen tarkistaa, onko aikomussuodatin vahvistettu vai ei."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"sitoudu aikomussuodattimen vahvistuspalveluun"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Antaa sovelluksen tehdä aikomussuodattimen vahvistuspyyntöjä. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"käytä sarjaportteja"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Luvan haltija voi käyttää sarjaportteja SerialManager-sovellusliittymän avulla."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"käytä ulkoisia sisällöntarjoajia"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Vähennä päivien määrää."</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Lisää vuosien määrää."</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Vähennä vuosien määrää."</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Edellinen kuukausi"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Seuraava kuukausi"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Peruuta"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Poista"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Minuuttien ympyränmuotoinen liukusäädin"</string>
     <string name="select_hours" msgid="6043079511766008245">"Valitse tunnit"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Valitse minuutit"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Päiväruudukko kuukausittain"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Vuosiluettelo"</string>
     <string name="select_day" msgid="7774759604701773332">"Valitse kuukausi ja päivä"</string>
     <string name="select_year" msgid="7952052866994196170">"Valitse vuosi"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> on valittu"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> poistettiin"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (työ)"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Poista näytön kiinnitys painamalla Edellinen- ja Viimeisimmät-kohtaa samanaikaisesti pitkään."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 837b58a..8a6f10b 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Bannière d\'itinérance désactivée"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Recherche des services disponibles"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Appels Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g> au bout de <xliff:g id="TIME_DELAY">{2}</xliff:g> secondes"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Permet à l\'application de prendre des photos et de filmer des vidéos avec l\'appareil photo. Cette autorisation lui permet d\'utiliser l\'appareil photo à tout moment sans votre consentement."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"désactiver l\'indicateur d\'émission LED lorsque la caméra est en cours d\'utilisation"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Permet à une application système préinstallée de désactiver l\'indicateur LED d\'utilisation de la caméra."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Permet à une application système préinstallée d\'envoyer au service de l\'appareil photo des événements relatifs au système."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"désactiver définitivement la tablette"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"désactiver définitivement le téléviseur"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"désactiver définitivement le téléphone"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"lancer directement la configuration du téléviseur par CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"démarrer directement la configuration du téléphone CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Permet à l\'application de lancer le déploiement CDMA. Des applications malveillantes sont susceptibles de le lancer inutilement."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"contrôler les notifications de mise à jour de la position géographique"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permet à l\'application d\'activer ou de désactiver les notifications de mise à jour de la position à partir du signal radio. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"accéder aux propriétés d\'enregistrement"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permet à l\'application de faire appel à des méthodes d\'ajout et de suppression de modèles d\'empreinte digitale que vous pouvez utiliser."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"utiliser le matériel d\'empreinte digitale"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permet à l\'application d\'utiliser du matériel d\'empreinte digitale pour l\'authentification"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte digitale partielle détectée. Veuillez essayer de nouveau."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossible de traiter les empreintes digitales. Veuillez essayer de nouveau."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Le capteur d\'empreintes digitales est sale. Veuillez le nettoyer et essayer de nouveau."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Le doigt a bougé trop vite. Veuillez essayer de nouveau."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Le doigt a bougé trop lentement. Veuillez essayer de nouveau."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Message d\'erreur d\'acquisition propre au fournisseur 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Traitement impossible. Essayer de nouveau."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Matériel non disponible."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empreinte digitale ne peut pas être enregistrée. Veuillez supprimer une empreinte existante."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Le temps attribué pour lire l\'empreinte est écoulé. Veuillez essayer de nouveau."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Le temps attribué pour lire l\'empreinte est écoulé. Veuillez essayer de nouveau."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Message d\'erreur propre au fournisseur."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lire les paramètres de synchronisation"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permet à l\'application d\'accéder aux paramètres de synchronisation d\'un compte. Par exemple, cette autorisation peut permettre de déterminer si l\'application Contacts est synchronisée avec un compte ou non."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activer ou désactiver la synchronisation"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permet à une application de supprimer les certificats GDN. Cela ne devrait jamais être nécessaire pour des applications normales."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"s\'associer à un service de messagerie d\'un fournisseur"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service de messagerie d\'un fournisseur. Les applications standards ne devraient jamais avoir recours à cette fonctionnalité."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Gérer le nombre et le type de caractères autorisés dans les mots de passe et les NIP de verrouillage de l\'écran."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permet à l\'application de vérifier qu\'un paquet peut être installé."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"s\'associer à un vérificateur de paquet"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permet à l\'application autorisée d\'effectuer des requêtes de vérificateurs de paquet. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"vérifier le filtre d\'intention"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Permet à l\'application de vérifier si un filtre d\'intention est validé ou non."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"s\'associer à un vérificateur de filtre d\'intention"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Permet à l\'application autorisée d\'effectuer des requêtes de vérificateurs de filtres d\'intention. Les applications standards ne devraient jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"accéder aux ports série"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permet à l\'application autorisée d\'accéder aux ports série avec l\'API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"accès externe aux fournisseurs de contenu"</string>
@@ -1224,7 +1264,7 @@
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Ouvrir avec %1$s"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Modifier avec"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Modifier avec %1$s"</string>
-    <string name="whichSendApplication" msgid="6902512414057341668">"Partager avec"</string>
+    <string name="whichSendApplication" msgid="6902512414057341668">"Partager"</string>
     <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Partager avec %1$s"</string>
     <string name="whichHomeApplication" msgid="4307587691506919691">"Sélectionner une application pour l\'écran d\'accueil"</string>
     <string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Utiliser %1$s comme écran d\'accueil"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Jour précédent"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Année suivante"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Année précédente"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Le mois précédent"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Le mois prochain"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Annuler"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Supprimer"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Curseur circulaire des minutes"</string>
     <string name="select_hours" msgid="6043079511766008245">"Sélectionnez les heures"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Sélectionnez les minutes"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Calendrier mensuel sous forme de grille"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Liste des années"</string>
     <string name="select_day" msgid="7774759604701773332">"Sélectionnez un mois et un jour"</string>
     <string name="select_year" msgid="7952052866994196170">"Sélectionnez une année"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"« <xliff:g id="ITEM">%1$s</xliff:g> » a été sélectionné"</string>
     <string name="deleted_key" msgid="7659477886625566590">"« <xliff:g id="KEY">%1$s</xliff:g> » a été supprimé"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Pour annuler l\'épinglage de cet écran, appuyez de manière prolongée sur Retour et Aperçu simultanément."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index c6e1387..57e49ec 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Bannière d\'itinérance désactivée"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Recherche des services disponibles"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Appels Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g> au bout de <xliff:g id="TIME_DELAY">{2}</xliff:g> secondes"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Permet à l\'application de prendre des photos et de filmer des vidéos avec l\'appareil photo. Cette autorisation lui permet d\'utiliser l\'appareil photo à tout moment sans votre consentement."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"désactiver l\'indicateur d\'émission LED lorsque la caméra est en cours d\'utilisation"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Permet à une application système préinstallée de désactiver l\'indicateur LED d\'utilisation de la caméra."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Permet à une application système préinstallée d\'envoyer au service de l\'appareil photo des événements relatifs au système."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"désactiver définitivement la tablette"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"désactiver le téléviseur de manière définitive"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"désactiver définitivement le téléphone"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"lancer directement la configuration CDMA du téléviseur"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"démarrer directement la configuration du téléphone CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Permet à l\'application de lancer le déploiement CDMA. Des applications malveillantes sont susceptibles de le lancer inutilement."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"Contrôle des notifications de mise à jour de position géo."</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permet à l\'application d\'activer ou de désactiver les notifications de mise à jour de la position à partir du signal radio. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"Accès aux propriétés d\'enregistrement"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Autoriser l\'application à invoquer des méthodes pour ajouter et supprimer des modèles d\'empreintes digitales"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utiliser le matériel d\'empreintes digitales"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autoriser l\'application à utiliser le matériel d\'empreintes digitales pour l\'authentification"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte numérique partiellement détectée. Veuillez réessayer."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossible de reconnaître l\'empreinte numérique. Veuillez réessayer."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Le capteur d\'empreintes numériques est sale. Veuillez le nettoyer, puis réessayer."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Vous avez retiré votre doigt trop rapidement. Veuillez réessayer."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Vous avez déplacé votre doigt trop lentement. Veuillez réessayer."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Message d\'erreur d\'acquisition spécifique au fournisseur 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Impossible de reconnaître l\'empreinte numérique. Veuillez réessayer."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Matériel non disponible."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossible d\'enregistrer l\'empreinte numérique. Veuillez supprimer une empreinte."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Délai de détection de l\'empreinte numérique expiré. Veuillez réessayer."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Délai de détection de l\'empreinte numérique expiré. Veuillez réessayer."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Message d\'erreur spécifique au fournisseur."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lire les paramètres de synchronisation"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permet à l\'application d\'accéder aux paramètres de synchronisation d\'un compte. Par exemple, cette autorisation peut permettre de déterminer si l\'application Contacts est synchronisée avec un compte ou non."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activer/désactiver la synchronisation"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permet à une application de supprimer les certificats de GDN. Ne devrait jamais être nécessaire pour les applications standards."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"s\'associer au service SMS/MMS d\'un opérateur"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permettre à l\'application de s\'associer à l\'interface de niveau supérieur du service SMS/MMS d\'un opérateur. Ne devrait jamais être nécessaire pour les applications standards."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Gérer le nombre et le type de caractères autorisés dans les mots de passe et les codes d\'accès de verrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permet à l\'application de vérifier qu\'un package peut être installé."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"associer à un vérificateur de package"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permet à l\'application autorisée d\'effectuer des requêtes de vérificateurs de package. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"valider le filtre d\'intention"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Permet à l\'application de vérifier si un filtre d\'intention est validé ou non."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"s\'associer pour valider filtre d\'intention"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Permet à l\'application autorisée de demander la validation des filtres d\'intention. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"accéder aux ports série"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permet à l\'application autorisée d\'accéder aux ports série avec l\'API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"accès externe fournisseurs de contenu"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Jour précédent"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Année suivante"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Année précédente"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Mois précédent"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Mois suivant"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Annuler"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Supprimer"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Curseur circulaire des minutes"</string>
     <string name="select_hours" msgid="6043079511766008245">"Sélectionner une heure"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Sélectionner des minutes"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Calendrier mensuel sous forme de grille"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Liste des années"</string>
     <string name="select_day" msgid="7774759604701773332">"Sélectionner un mois et un jour"</string>
     <string name="select_year" msgid="7952052866994196170">"Sélectionner une année"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"\"<xliff:g id="ITEM">%1$s</xliff:g>\" sélectionné"</string>
     <string name="deleted_key" msgid="7659477886625566590">"\"<xliff:g id="KEY">%1$s</xliff:g>\" supprimé"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Pour annuler l\'épinglage, appuyez de manière prolongée et simultanée sur \"Retour\" et \"Aperçu\"."</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 5218ed5..e6f763d 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Banner de itinerancia desactivado"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Buscando servizo"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Chamadas por wifi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: non desviada"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> tras <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Permite á aplicación tomar imaxes e vídeos coa cámara. Con este permiso a aplicación pode utilizar a cámara en calquera momento sen a túa confirmación."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"desactivar LED indicador de transmisión cando se está utilizando a cámara"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Permite a unha aplicación do sistema preinstalada desactivar o LED indicador de uso da cámara."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Permite a unha aplicación do sistema preinstalada enviar eventos do sistema do servizo da cámara."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"desactivar o tablet permanentemente"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"desactivar a televisión permanentemente"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"desactivar o teléfono permanentemente"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"iniciar directamente a configuración CDMA da televisión"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directamente a configuración CDMA do teléfono"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Permite á aplicación iniciar o aprovisionamento CDMA. É posible que aplicacións maliciosas inicien o aprovisionamento CDMA de forma innecesaria."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar as notificacións de actualización de localización"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permite á aplicación activar/desactivar as notificacións de actualización de localización desde a radio. As aplicacións normais non deben utilizar este permiso."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"acceder ás propiedades de rexistro"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que a aplicación invoque métodos para engadir e eliminar modelos de uso de identificación dixital."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"usar hardware de identificación dixital"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que a aplicación utilice hardware de identificación dixital para a autenticación"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Detectouse unha identificación dixital parcial. Téntao de novo."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Non se puido procesar a impresión dixital. Téntao de novo."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"O sensor de identificación dixital está sucio. Límpao e téntao de novo."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"O dedo moveuse demasiado rápido. Téntao de novo."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"O dedo moveuse demasiado lento. Téntao de novo."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Mensaxe de erro de adquisición específico do vendedor 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Non se pode procesar. Téntao de novo."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware non dispoñible."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Non se pode almacenar a identificación dixital. Elimina unha identificación dixital existente."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Esgotouse o tempo de espera da identificación dixital. Téntao de novo."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Esgotouse o tempo de espera da identificación dixital. Téntao de novo."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Mensaxe de erro específico do vendedor"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler a configuración de sincronización"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permite á aplicación ler a configuración de sincronización dunha conta. Por exemplo, esta acción pode determinar se a aplicación Contactos se sincroniza cunha conta."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activar e desactivar a sincronización"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permite a unha aplicación eliminar os certificados DRM. As aplicacións normais non o deberían precisar nunca."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"vincular a un servizo de mensaxería"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permite ao propietario vincularse á interface de nivel superior dun servizo de mensaxería. As aplicacións normais non deberían necesitar este permiso."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer as normas de contrasinal"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla a lonxitude e os caracteres permitidos nos contrasinais e nos PIN de bloqueo da pantalla."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisar os intentos de desbloqueo da pantalla"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite á aplicación verificar se un paquete é instalable."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"vincular a un verificador de paquetes"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite ao propietario realizar solicitudes de verificadores de paquetes. As aplicacións normais non deberían necesitar este permiso."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verificar filtro de intento"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Permite á aplicación comprobar se un filtro de intento está verificado ou non."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"ligar a verificador de filtro de intento"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Permite ao propietario realizar solicitudes de verificadores de filtros de intento. As aplicacións normais non deberían necesitar este permiso."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"acceder a portos serie"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite que o propietario poida acceder aos portos serie usando a API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"acceder a provedores de contido externamente"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reducir día"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumentar ano"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reducir ano"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Mes anterior"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Mes seguinte"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Cancelar"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Eliminar"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Control de desprazamento circular dos minutos"</string>
     <string name="select_hours" msgid="6043079511766008245">"Seleccionar horas"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Seleccionar minutos"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Grade mensual de días"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Lista de anos"</string>
     <string name="select_day" msgid="7774759604701773332">"Seleccionar mes e día"</string>
     <string name="select_year" msgid="7952052866994196170">"Seleccionar ano"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionado"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Para soltar a pantalla, mantén premido Atrás e Visión xeral ao mesmo tempo."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 6463cc5..320ecfb 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"रोमिंग बैनर बंद"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"सेवा खोज रहा है"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"वाई-फ़ाई कॉलिंग"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित नहीं किया गया"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकंड के बाद"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"ऐप्स  को कैमरे से चित्र और वीडियो लेने देता है. यह अनुमति ऐप्स  को किसी भी समय आपकी पुष्टि के बिना कैमरे का उपयोग करने देती है."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"कैमरा उपयोग में होने पर संचारण संकेतक LED अक्षम करें"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"पहले से इंस्टॉल किए गए सिस्टम ऐप्स  को कैमरे को संकेतक LED का उपयोग करने से अक्षम करती है."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"पहले से इंस्टॉल किए गए सिस्टम ऐप्लिकेशन को कैमरा सेवा सिस्टम ईवेंट भेजने की अनुमति देती है."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"स्‍थायी रूप से टेबलेट अक्षम करें"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"टीवी को स्‍थायी रूप से अक्षम करना"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"फ़ोन को स्‍थायी रूप से अक्षम करें"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA टीवी सेटअप को सीधे प्रारंभ करना"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"सीधे CDMA फ़ोन सेटअप प्रारंभ करें"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"ऐप्स को CDMA प्रावधान प्रारंभ करने देता है. दुर्भावनापूर्ण ऐप्स अनावश्‍यक रूप से CDMA प्रावधान प्रारंभ कर सकते हैं."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"स्‍थान के बारे में नई जानकारी की नोटिफिकेशन को नियंत्रित करें"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"एप को रेडियो से स्‍थान के बारे में नई जानकारी की सूचनाएं सक्षम/अक्षम करने देता है. सामान्‍य ऐप्स द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"चेकइन गुणों में पहुंचें"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"अंगुली की छाप वाले टेम्पलेट का उपयोग करने के लिए जोड़ने और हटाने हेतु ऐप को विधियां प्रारंभ करने देती है."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"अंगुली की छाप के लिए हार्डवेयर का उपयोग करें"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ऐप के प्रमाणीकरण के लिए अंगुली की छाप हार्डवेयर का उपयोग करने देती है"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फ़िंगरप्रिंट की पहचान की गई. कृपया पुनः प्रयास करें."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फ़िंगरप्रिंट संसाधित नहीं हो सका. कृपया पुन: प्रयास करें."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"फ़िंगरप्रिंट संवेदक गंदा है. कृपया साफ़ करें और पुनः प्रयास करें."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"अंगुली को तेज़ी से चलाया गया. कृपया पुनः प्रयास करें."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"अंगुली को धीरे चलाया गया. कृपया पुनः प्रयास करें."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"विक्रेता-विशिष्‍ट प्राप्‍ति त्रुटि संदेश 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"संसाधित करने में असमर्थ. पुनः प्रयास करें."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"हार्डवेयर उपलब्ध नहीं है."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फ़िंगरप्रिंट को संग्रहीत नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट निकालें."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय समाप्त हो गया. पुनः प्रयास करें."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"फ़िंगरप्रिंट का समय समाप्त हो गया. पुनः प्रयास करें."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"विक्रेता-विशिष्‍ट त्रुटि संदेश."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"समन्वयन सेटिंग पढ़ें"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ऐप्स  को किसी खाते की समन्वयन सेटिंग पढ़ने देता है. उदाहरण के लिए, इससे यह निर्धारित किया जा सकता है कि लोग ऐप्स  किसी खाते के साथ समन्‍वयित है या नहीं."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"समन्‍वयन बंद या चालू टॉगल करें"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"एप्‍लिकेशन को DRM प्रमाणपत्रों को निकालने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यकता नहीं होनी चाहिए."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"किसी वाहक संदेश सेवा से आबद्ध करें"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"धारक को किसी वाहक संदेश सेवा के शीर्ष-स्‍तरीय इंटरफ़ेस से आबद्ध होने देती है. सामान्‍य ऐप्‍स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करें"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्‍क्रीन लॉक पासवर्ड तथा पिन की लंबाई और उसमें अनुमत वर्णों को नियंत्रित करें."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"स्‍क्रीन-अनलॉक के प्रयासों पर निगरानी रखें"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"एप्‍लि‍केशन को इंस्‍टॉल करने योग्‍य पैकेज सत्‍यापि‍त करने देता है."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"पैकेज प्रमाणक से आबद्ध करें"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"धारक को पैकेज प्रमाणक के अनुरोध की अनुमति‍ देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"लक्ष्य फ़िल्टर सत्यापित करें"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"ऐप को जांच करने देती है कि कोई लक्ष्य फ़िल्टर सत्यापित है या नहीं."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"लक्ष्य फ़िल्टर प्रमाणक से आबद्ध करें"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"धारक को लक्ष्य फ़िल्टर प्रमाणक के अनुरोध की अनुमति देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"सीरियल पोर्ट पर पहुंचें"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API का उपयोग करके धारक को सीरियल पोर्ट पर पहुंच प्रदान करता है."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"बाह्य रूप से सामग्री प्रदाताओं पर पहुंच"</string>
@@ -1211,9 +1251,9 @@
     <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> चल रहा है"</string>
     <string name="app_running_notification_text" msgid="4653586947747330058">"अधिक जानकारी के लिए या ऐप्स  रोकने के लिए स्पर्श करें."</string>
     <string name="ok" msgid="5970060430562524910">"ठीक है"</string>
-    <string name="cancel" msgid="6442560571259935130">"रहने दें"</string>
+    <string name="cancel" msgid="6442560571259935130">"अभी नहीं"</string>
     <string name="yes" msgid="5362982303337969312">"ठीक है"</string>
-    <string name="no" msgid="5141531044935541497">"रहने दें"</string>
+    <string name="no" msgid="5141531044935541497">"अभी नहीं"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"ध्यान दें"</string>
     <string name="loading" msgid="7933681260296021180">"लोड हो रहे हैं..."</string>
     <string name="capital_on" msgid="1544682755514494298">"चालू"</string>
@@ -1335,7 +1375,7 @@
     <string name="sms_short_code_details" msgid="5873295990846059400">"इससे आपके मोबाइल खाते पर "<b>"शुल्क लग सकता है"</b>"."</string>
     <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"इससे आपके मोबाइल खाते पर शुल्क लगेगा."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"भेजें"</string>
-    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"रहने दें"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"अभी नहीं"</string>
     <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"मेरी पसंद को याद रखें"</string>
     <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"आप इसे बाद में सेटिंग &gt; ऐप्स  में बदल सकते हैं"</string>
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"हमेशा अनुमति दें"</string>
@@ -1544,8 +1584,10 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"दिन कम करें"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"वर्ष बढ़ाएं"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"वर्ष कम करें"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"पिछला महीना"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"अगला महीना"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
-    <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"रहने दें"</string>
+    <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"अभी नहीं"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"हटाएं"</string>
     <string name="keyboardview_keycode_done" msgid="1992571118466679775">"पूर्ण"</string>
     <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"Mode change"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"मिनटों का चक्राकार स्लाइडर"</string>
     <string name="select_hours" msgid="6043079511766008245">"घंटे चुनें"</string>
     <string name="select_minutes" msgid="3974345615920336087">"मिनट चुनें"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"दिनों की माह ग्रिड"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"वर्ष की सूची"</string>
     <string name="select_day" msgid="7774759604701773332">"माह और दिन चुनें"</string>
     <string name="select_year" msgid="7952052866994196170">"वर्ष चुनें"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> चयनित"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> को हटा दिया गया"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्यस्थल का <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"इस स्क्रीन को अनपिन करने के लिए, एक ही समय में वापस जाएं और अवलोकन को स्पर्श करके रखें."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 0f39d7c..f41080b 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -125,8 +125,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Isključen je natpis roaminga"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Pretraživanje usluge"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi pozivi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije proslijeđeno"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> nakon <xliff:g id="TIME_DELAY">{2}</xliff:g> s"</string>
@@ -585,6 +596,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Aplikaciji omogućuje snimanje slika i videozapisa fotoaparatom. Ta dozvola aplikaciji omogućuje upotrebu fotoaparata u bilo kojem trenutku bez vašeg odobrenja."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"onemogućavanje lampice pokazivača prijenosa kada je fotoaparat u upotrebi"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Omogućuje unaprijed instaliranim aplikacijama sustava onemogućavanje lampice pokazivača upotrebe fotoaparata."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Omogućuje unaprijed instaliranim aplikacijama sustava slanje događaja sustava usluge fotoaparata."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"trajno onemogući tabletni uređaj"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"trajno onemogućivanje televizora"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"trajno onemogućavanje telefona"</string>
@@ -633,6 +645,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"izravno pokretanje postavljanja televizora za CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"izravno pokretanje postavke CDMA telefona"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Aplikaciji omogućuje pokretanje dodjele CDMA. Zlonamjerne aplikacije mogu nepotrebno pokrenuti dodjelu CDMA."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"obavijesti o ažuriranju kontrolne lokacije"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Omogućuje aplikaciji omogućavanje/onemogućavanje obavijesti o ažuriranju lokacije s radija. Nije namijenjena uobičajenim aplikacijama."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"pristup svojstvima prijave"</string>
@@ -747,6 +763,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Aplikaciji omogućuje pozivanje načina za dodavanje i brisanje predložaka otisaka prstiju koji će se upotrijebiti."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"upotreba hardvera za čitanje otisaka prstiju"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Aplikaciji omogućuje upotrebu hardvera za čitanje otisaka prstiju radi autentifikacije."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Otkriven je djelomični otisak prsta. Pokušajte ponovo."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Obrada otiska prsta nije uspjela. Pokušajte ponovo."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Senzor otiska prsta nije čist. Očistite ga i pokušajte ponovo."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Prebrzo pomicanje prsta. Pokušajte ponovo."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Presporo pomicanje prsta. Pokušajte ponovo."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Poruka pogreške prilikom dohvaćanja vezana uz dobavljača 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Nije obrađeno. Pokušajte ponovo."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardver nije dostupan."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisak prsta nije pohranjen. Uklonite postojeći otisak prsta."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Isteklo je vrijeme čekanja za otisak prsta. Pokušajte ponovo."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Isteklo je vrijeme čekanja za otisak prsta. Pokušajte ponovo."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Poruka pogreške vezana uz dobavljača."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čitanje postavki sinkronizacije"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Aplikaciji omogućuje čitanje postavki sinkronizacije za račun. Time se, primjerice, može utvrditi je li aplikacija Osobe sinkronizirana s računom."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"uključivanje/isključivanje sinkronizacije"</string>
@@ -823,6 +855,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Omogućuje aplikaciji uklanjanje DRM certifikata. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"povezivanje s uslugom mobilnog operatera za slanje poruka"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Omogućuje nositelju povezivanje sa sučeljem najviše razine usluge mobilnog operatera za slanje poruka. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Upravlja duljinom i znakovima koji su dopušteni u zaporkama i PIN-ovima zaključavanja zaslona."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
@@ -1120,6 +1156,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Aplikaciji omogućuje da provjeri je li paket moguće instalirati."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"vezano uz paketnu provjeru"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Nositelju omogućuje da traži paketnu provjeru. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"potvrditi filtar namjere"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Omogućuje aplikaciji da provjeri je li filtar namjere potvrđen."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"vezati se uz potvrdu filtara namjere"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Omogućuje nositelju zahtijevanje potvrde filtara namjere. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"pristup serijskim priključcima"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Rukovatelju omogućuje pristup serijskim priključcima pomoću značajke SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"pristup pružateljima sadržaja izvana"</string>
@@ -1552,6 +1592,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Smanjenje dana"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Povećanje godine"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Smanjenje godine"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Prethodni mjesec"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Sljedeći mjesec"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Odustani"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Izbriši"</string>
@@ -1803,11 +1845,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Kružni klizač minuta"</string>
     <string name="select_hours" msgid="6043079511766008245">"Odaberite sate"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Odaberite minute"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Mreža dana u mjesecu"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Popis godina"</string>
     <string name="select_day" msgid="7774759604701773332">"Odaberite mjesec i dan"</string>
     <string name="select_year" msgid="7952052866994196170">"Odaberite godinu"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Odabrana je stavka <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Izbrisan je broj <xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Da biste otkvačili ovaj zaslon, istovremeno dodirnite i zadržite Natrag i Pregled."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index adada44..80dbfa3 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Barangolást jelző szalaghirdetés kikapcsolva"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Szolgáltatás keresése"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-hívás"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nincs átirányítva"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> másodperc után"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Lehetővé teszi az alkalmazás számára, hogy a fényképezőgéppel fotókat és videókat készítsen. Az engedéllyel rendelkező alkalmazás bármikor, az Ön jóváhagyása nélkül használhatja a fényképezőgépet."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"átviteljelző LED letiltása, ha a kamera használatban van"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Lehetővé teszi egy előre telepített rendszeralkalmazás számára, hogy letiltsa a kamerahasználatot jelző LED-et."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Lehetővé teszi egy előre telepített rendszeralkalmazás számára, hogy a elküldje a kameraszolgáltatási értesítéseket a rendszerszintű eseményekről."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"a táblagép végleges deaktiválása"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"a tévé teljes letiltása"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"telefon végleges letiltása"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"a CDMA tévébeállítás közvetlen elindítása"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA-telefonbeállítás közvetlen elindítása"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Lehetővé teszi az alkalmazás számára a CDMA-szolgáltatás elindítását. A rosszindulatú alkalmazások szükségtelenül is elindíthatják ezt."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"helyaktualizálási értesítések vezérlése"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Lehetővé teszi az alkalmazás számára a rádiótól érkező helyaktualizálási értesítések engedélyezését/letiltását. Normál alkalmazások nem használhatják."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"hozzáférés a bejelentkezési tulajdonságokhoz"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Lehetővé teszi az alkalmazás számára a használni kívánt ujjlenyomatsablonok hozzáadására és törlésére szolgáló metódusok indítását."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ujjlenyomat-olvasó hardver használata"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Lehetővé teszi az alkalmazás számára az ujjlenyomat-olvasó hardver hitelesítésre való használatát"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"A rendszer az ujjlenyomatnak csak egy részletét érzékelte. Próbálkozzon újra."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nem sikerült feldolgozni az ujjlenyomatot. Próbálkozzon újra."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Az ujjlenyomat-olvasó koszos. Tisztítsa meg, majd próbálkozzon újra."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Túl hamar vette el az ujját. Próbálkozzon újra."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Túl lassan vette el az ujját. Próbálkozzon újra."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Szolgáltatóspecifikus akvizíciós hibakód 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"A feldolgozás sikertelen. Próbálkozzon újra."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"A hardver nem érhető el."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Az ujjlenyomat nem tárolható. Távolítson el egy meglévő ujjlenyomatot."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Az ujjlenyomat-beolvasási műveletkor időtúllépés történt. Próbálkozzon újra."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Az ujjlenyomat-beolvasási műveletkor időtúllépés történt. Próbálkozzon újra."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Szolgáltatóspecifikus hibaüzenet"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"szinkronizálási beállítások olvasása"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Lehetővé teszi az alkalmazás számára egy fiók szinkronizálási beállításainak beolvasását. Például ellenőrizheti, hogy a Személyek alkalmazás szinkronizálva van-e egy fiókkal."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"szinkronizálás be-és kikapcsolása"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Lehetővé teszi, hogy az alkalmazás eltávolítsa a DRM-tanúsítványokat. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"kapcsolódás egy üzenetszolgáltatáshoz"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Lehetővé teszi, hogy a tulajdonos kapcsolódjon egy üzenetszolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"A képernyőzár jelszavaiban és PIN kódjaiban engedélyezett karakterek és hosszúság vezérlése."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Lehetővé teszi az alkalmazás számára, hogy ellenőrizze, egy csomag telepíthető-e."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"egy csomaghitelesítőhöz kötődnek"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Lehetővé teszi, hogy a tulajdonos kérelmeket nyújtson be a csomag hitelesítőivel kapcsolatban. A normál alkalmazásoknak erre soha nincs szüksége."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"„intent filter” hitelesítése"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Lehetővé teszi annak ellenőrzését egy alkalmazás számára, hogy egy „intent filter” hitelesítve van-e."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"rögzítés egy „intent filter” hitelesítőhöz"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Lehetővé teszi, hogy a tulajdonos kéréseket kezdeményezzen az „intent filter” hitelesítőkkel kapcsolatban. A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"soros portok elérése"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Lehetővé teszi a tulajdonos számára a soros portok elérését a SerialManager API segítségével."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"tartalomszolgáltatók külső elérése"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Dátum értékének csökkentése"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Év értékének növelése"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Év értékének csökkentése"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Előző hónap"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Következő hónap"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Mégse"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Perc kör alakú csúszkája"</string>
     <string name="select_hours" msgid="6043079511766008245">"Óra kiválasztása"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Perc kiválasztása"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Napok havi leosztásban"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Évek listája"</string>
     <string name="select_day" msgid="7774759604701773332">"Válassza ki a hónapot és a napot"</string>
     <string name="select_year" msgid="7952052866994196170">"Válassza ki az évet"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> kiválasztva"</string>
     <string name="deleted_key" msgid="7659477886625566590">"A(z) <xliff:g id="KEY">%1$s</xliff:g> érték törölve"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"A képernyő rögzítésének feloldásához tartsa lenyomva a Vissza és az Áttekintés lehetőséget egyszerre."</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 65bacf7..64b7e68 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Ռոումինգի ազդերիզն անջատված է"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Ծառայության որոնում..."</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Զանգեր Wi-Fi-ի միջոցով"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. Չի վերահասցեավորվել"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> վայրկյանից"</string>
@@ -236,7 +247,7 @@
     <string name="permgrouplab_writeDictionary" msgid="8090237702432576788">"Գրել օգտվողի բառարանում"</string>
     <string name="permgroupdesc_writeDictionary" msgid="2711561994497361646">"Ավելացնել բառեր օգտվողի բառարանում:"</string>
     <string name="permgrouplab_bookmarks" msgid="1949519673103968229">"Էջանիշեր և պատմություն"</string>
-    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Ուղղակի մուտք դեպի էջանիշեր և դիտարկչի պատմություն:"</string>
+    <string name="permgroupdesc_bookmarks" msgid="4169771606257963028">"Ուղղակի մուտք դեպի էջանիշեր և դիտարկիչի պատմություն:"</string>
     <string name="permgrouplab_deviceAlarms" msgid="6117704629728824101">"Ազդանշան"</string>
     <string name="permgroupdesc_deviceAlarms" msgid="4769356362251641175">"Կարգավորել զարթուցիչի ժամացույցը:"</string>
     <string name="permgrouplab_voicemail" msgid="4162237145027592133">"Ձայնային փոստ"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Թույլ է տալիս հավելվածին ֆոտոխցիկով լուսանկարել և տեսանկարել: Այս թույլտվությունը հնարավորություն է տալիս հավելվածին օգտագործել ֆոտոխցիկը ցանկացած ժամանակ` առանց ձեր հաստատման:"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"անջատել փոխանցող LED ցուցիչը, երբ ֆոտոխցիկը օգտագործվում է"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Թույլ է տալիս նախապես տեղադրված համակարգային ծրագրին անջատել ֆոտոխցիկի օգտագործման LED ցուցիչը:"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Նախապես տեղադրված համակարգային հավելվածին թույլ է տալիս խցիկի ծառայությանն ուղարկել համակարգի իրադարձությունները:"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"մշտապես անջատել գրասալիկը"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"մշտապես անջատել հեռուստացույցը"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ընդմիշտ կասեցնել հեռախոսը"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"ուղղակիորեն մեկնարկել CDMA-ի կարգավորումը հեռուստացույցի վրա"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"ուղղակիորեն սկսել CDMA հեռախոսի կարգավորումը"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Թույլ է տալիս հավելվածին մեկնարկել CDMA-ի տրամադրումը: Վնասարար հավելվածները կարող են անտեղի սկսել CDMA-ի տրամադրում:"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"վերահսկել տեղանքի թարմացման ծանուցումները"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Թույլ է տալիս հավելվածին միացնել կամ անջատել տեղանքի թարմացման ծանուցումները ռադիոյից: Սովորական հավելվածների օգտագործման համար չէ:"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"մուտք գործել գրանցանշման կարգավորումներ"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Հավելվածին թույլ է տալիս կատարել այնպիսի գործառույթներ, որոնց միջոցով կարելի է օգտագործման համար ավելացնել և հեռացնել մատնահետքերի նմուշներ:"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"օգտագործել մատնահետքերի գրանցման սարքը"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Հավելվածին թույլ է տալիս նույնականացման համար օգտագործել մատնահետքերի գրանցման սարքը"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Մատնահետքը հայտնաբերվել է մասամբ: Փորձեք նորից:"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Չհաջողվեց մշակել մատնահետքը: Նորից փորձեք:"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Մատնահետքերի սենսորն աղտոտված է: Մաքրեք այն և փորձեք նորից:"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Մատը շարժեցիք շատ արագ: Փորձեք նորից:"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Մատը շարժեցիք շատ դանդաղ: Փորձեք նորից:"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Վաճառողի կողմից սահմանվող ձեռքբերման սխալի հաղորդագրություն 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Հնարավոր չէ շարունակել: Փորձեք նորից:"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Սարքն անհասանելի է:"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Հնարավոր չէ պահել մատնահետքը: Հեռացրեք առկա մատնահետքը:"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Մատնահետքի գրանցման ժամանակը սպառվել է: Փորձեք նորից:"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Մատնահետքի գրանցման ժամանակը սպառվել է: Փորձեք նորից:"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Վաճառողի կողմից սահմանվող սխալի հաղորդագրություն:"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"կարդալ համաժամեցման կարգավորումները"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Թույլ է տալիս հավելվածին կարդալ համաժամեցման կարգավորումները հաշվի համար: Օրինակ` այն կարող է որոշել, արդյոք Մարդիկ հավելվածը համաժամեցված է հաշվի հետ:"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"համաժամեցումը փոխարկել միացվածի և անջատվածի"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Ծրագրին թույլ է տալիս հեռացնել DRM վկայագրեր: Սովորական ծրագրերի համար երբեք պետք չի գալիս:"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"Կապակցում օպերատորի հաղորդագրությունների ծառայության հետ"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Թույլ է տալիս տիրոջը կապվել օպերատորի հաղորդագրությունների ծառայության վերին մակարդակի միջերեսի հետ: Սա երբեք չի պահանջվում սովորական հավելվածների համար:"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Սահմանել գաղտնաբառի կանոնները"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Կառավարել էկրանի ապակողպման գաղտնաբառերի և PIN կոդերի թույլատրելի երկարությունն ու գրանշանները:"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Վերահսկել էկրանի ապակողպման փորձերը"</string>
@@ -1100,11 +1136,11 @@
     <string name="autofill_area" msgid="3547409050889952423">"Տարածք"</string>
     <string name="autofill_emirate" msgid="2893880978835698818">"Էմիրություն"</string>
     <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"կարդալ ձեր վեբ էջանիշերը և պատմությունը"</string>
-    <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Թույլ է տալիս հավելվածին կարդալ դիտարկչի այցելած բոլոր URL-ների պատմությունը և դիտարկչի բոլոր էջանիշերը: Նշում. այս թույլտվությունը չի կարող գործածվել կողմնակի դիտարկիչների կամ վեբ զննարկման հնարավորություններով այլ հավելվածների կողմից:"</string>
+    <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Թույլ է տալիս հավելվածին կարդալ դիտարկիչի այցելած բոլոր URL-ների պատմությունը և դիտարկիչի բոլոր էջանիշերը: Նշում. այս թույլտվությունը չի կարող գործածվել կողմնակի դիտարկիչների կամ վեբ զննարկման հնարավորություններով այլ հավելվածների կողմից:"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"գրել վեբ էջանիշերը և պատմությունը"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Թույլ է տալիս հավելվածին փոփոխել դիտարկչի պատմությունը կամ ձեր գրասալիկում պահված էջանիշերը: Այն կարող է թույլ տալ հավելվածին ջնջել կամ փոփոխել դիտարկչի տվյալները: Նշում. այս թույլտվությունը չի կարող գործածվել կողմնակի դիտարկիչների կամ վեբ զննարկման հնարավորություններով այլ հավելվածների կողմից:"</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Թույլ է տալիս հավելվածին փոփոխել դիտարկիչի պատմությունը կամ ձեր գրասալիկում պահված էջանիշերը: Այն կարող է թույլ տալ հավելվածին ջնջել կամ փոփոխել դիտարկիչի տվյալները: Նշում. այս թույլտվությունը չի կարող գործածվել կողմնակի դիտարկիչների կամ վեբ զննարկման հնարավորություններով այլ հավելվածների կողմից:"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"Թույլ է տալիս հավելվածին փոփոխել դիտարկիչի պատմությունը կամ հեռուստացույցում պահված էջանիշները: Սա կարող է թույլ տալ հավելվածին ջնջել կամ փոփոխել դիտարկիչի տվյալները: Ուշադրություն. այս թույլտվությունը չի կարող հարկադրվել երրորդ կողմի դիտարկիչների կամ այլ հավելվածների կողմից, որոնք նույնպես կարողանում են վեբ էջեր բացել:"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Թույլ է տալիս հավելվածին փոփոխել դիտարկչի պատմությունը կամ ձեր հեռախոսում պահված էջանիշերը: Այն կարող է թույլ տալ հավելվածին ջնջել կամ փոփոխել դիտարկչի տվյալները: Նշում. այս թույլտվությունը չի կարող գործածվել կողմնակի դիտարկիչների կամ վեբ զննարկման հնարավորություններով այլ հավելվածների կողմից:"</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Թույլ է տալիս հավելվածին փոփոխել դիտարկիչի պատմությունը կամ ձեր հեռախոսում պահված էջանիշերը: Այն կարող է թույլ տալ հավելվածին ջնջել կամ փոփոխել դիտարկիչի տվյալները: Նշում. այս թույլտվությունը չի կարող գործածվել կողմնակի դիտարկիչների կամ վեբ զննարկման հնարավորություններով այլ հավելվածների կողմից:"</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"դնել ազդանշան"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Թույլ է տալիս հավելվածին սահմանել զարթուցիչի ծրագրում տեղադրված ազդանշանը: Զարթուցիչի որոշ հավելվածներ չեն կարող կիրառել այս հատկությունը:"</string>
     <string name="permlab_writeVoicemail" msgid="7309899891683938100">"գրել ձայնային փոստ"</string>
@@ -1113,12 +1149,16 @@
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Թույլ է տալիս հավելվածին ավելացնել հաղորդագրություններ ձեր ձայնային փոստի արկղում:"</string>
     <string name="permlab_readVoicemail" msgid="8415201752589140137">"կարդալ ձայնային փոստը"</string>
     <string name="permdesc_readVoicemail" msgid="8926534735321616550">"Ծրագրին թույլ է տալիս կարդալ ձեր ձայնային փոստը"</string>
-    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"փոփոխել դիտարկչի աշխարհագրական տեղանքի թույլտվությունները"</string>
-    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Թույլ է տալիս հավելվածին փոփոխել դիտարկչի աշխարհագրական դիրքի թույլտվությունները: Վնասարար հավելվածները կարող են օգտագործել սա` թույլատրելու ուղարկել տեղադրության վերաբերյալ տեղեկությունները կամայական վեբ կայքերին:"</string>
+    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"փոփոխել դիտարկիչի աշխարհագրական տեղանքի թույլտվությունները"</string>
+    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Թույլ է տալիս հավելվածին փոփոխել դիտարկիչի աշխարհագրական դիրքի թույլտվությունները: Վնասարար հավելվածները կարող են օգտագործել սա` թույլատրելու ուղարկել տեղադրության վերաբերյալ տեղեկությունները կամայական վեբ կայքերին:"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"հաստատել փաթեթները"</string>
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Թույլ է տալիս հավելվածին հաստատել, որ փաթեթը տեղադրելի է:"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"միանալ փաթեթի ստուգիչին"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Թույլ է տալիս սեփականատիրոջը փաթեթի ստուգիչների հարցում կատարել: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"ստուգել ինտենտ-զտիչը"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Հավելվածին թույլ է տալիս ճշտել՝ ստուգված է արդյոք ինտենտ-զտիչը, թե ոչ:"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"կապվել ինտենտ-զտիչի ստուգիչի հետ"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Թույլ է տալիս կատարել հարցումներ ինտենտ-զտիչի ստուգիչների վերաբերյալ: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"մուտք գործել հաջորդական միացքներ"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Թույլ է տալիս սեփականատիրոջը մուտք գործել հաջորդական միացքներ` օգտագործելով SerialManager API-ը:"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"դրսից մատչել բովանդակություն տրամադրողներին"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Նվազեցնել օրը"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Աճեցնել տարին"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Նվազեցնել տարին"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Նախորդ ամիս"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Հաջորդ ամիս"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Չեղարկել"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Ջնջել"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Րոպեների ընտրություն թվատախտակից"</string>
     <string name="select_hours" msgid="6043079511766008245">"Ընտրեք ժամը"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Ընտրեք րոպեն"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Ամսաթվի ընտրության պատուհան"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Տարիների ցանկ"</string>
     <string name="select_day" msgid="7774759604701773332">"Ընտրեք ամիսն ու օրը"</string>
     <string name="select_year" msgid="7952052866994196170">"Ընտրեք տարին"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Ընտրված է <xliff:g id="ITEM">%1$s</xliff:g> տարրը"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> թիվը ջնջված է"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Աշխատանքային <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Այս էկրան ապամրացնելու համար միաժամանակ հպեք և պահեք Հետ և Համատեսք կոճակները:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 2f7cb25..9e19092 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Spanduk Roaming Mati"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Mencari layanan"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Panggilan Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak diteruskan"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> setelah <xliff:g id="TIME_DELAY">{2}</xliff:g> detik"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Memungkinkan aplikasi mengambil gambar dan video dengan kamera. Izin ini memungkinkan aplikasi menggunakan kamera kapan saja tanpa konfirmasi Anda."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"nonaktifkan LED indikator transmisi saat kamera digunakan"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Izinkan aplikasi sistem yang sudah dipasang sebelumnya menonaktifkan LED indikator penggunaan kamera."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Mengizinkan aplikasi sistem yang sudah dipasang sebelumnya mengirim peristiwa sistem layanan kamera."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"noaktifkan tablet secara permanen"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"nonaktifkan TV secara permanen"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"nonaktifkan ponsel secara permanen"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"langsung mulai penyiapan TV CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"mulai penyiapan ponsel CDMA secara langsung"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Mengizinkan apl memulai penyediaan CDMA. Apl berbahaya dapat memulai penyediaan CDMA yang tidak perlu."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"mengontrol pemberitahuan pembaruan lokasi"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Mengizinkan apl mengaktifkan/menonaktifkan pemberitahuan pembaruan lokasi dari radio. Tidak untuk digunakan oleh apl normal."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"akses properti check in"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Mengizinkan aplikasi memanggil metode untuk menambahkan dan menghapus template sidik jari untuk digunakan."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"gunakan perangkat keras sidik jari"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Mengizinkan aplikasi untuk menggunakan perangkat keras sidik jari untuk otentikasi"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Sebagian sidik jari terdeteksi. Coba lagi."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Tidak dapat memproses sidik jari. Coba lagi."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sensor sidik jari kotor. Bersihkan dan coba lagi."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Jari digerakkan terlalu cepat. Coba lagi."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Jari digerakkan terlalu lambat. Coba lagi."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Pesan kesalahan akuisisi khusus vendor 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Tidak dapat memproses. Coba lagi."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Perangkat keras tidak tersedia."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Sidik jari tidak dapat disimpan. Hapus sidik jari yang ada."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Waktu sidik jari habis. Coba lagi."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Waktu sidik jari habis. Coba lagi."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Pesan kesalahan khusus vendor"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"baca setelan sinkron"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Memungkinkan aplikasi membaca setelan sinkronisasi untuk sebuah akun. Misalnya, izin ini dapat menentukan apakah aplikasi Orang disinkronkan dengan sebuah akun."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"nyalakan dan matikan sinkronisasi"</string>
@@ -822,6 +854,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Memungkinkan aplikasi membuang sertifikat DRM. Tidak pernah dibutuhkan untuk aplikasi normal."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"ikat ke layanan perpesanan operator"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Mengizinkan operator untuk mengikat ke antarmuka tingkat tinggi dari suatu layanan perpesanan operator. Fitur ini seharusnya tidak diperlukan oleh aplikasi normal."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"berinteraksi dengan layanan interaksi suara"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"Mengizinkan pemegang berinteraksi dengan layanan interaksi suara yang saat ini aktif. Tidak pernah diperlukan oleh aplikasi normal."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Mengontrol panjang dan karakter yang diizinkan dalam sandi dan PIN kunci layar."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Upaya pembukaan kunci layar monitor"</string>
@@ -1119,6 +1153,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Mengizinkan apl memverifikasi bahwa suatu paket dapat dipasang."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"mengikat ke pemverifikasi paket"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Mengizinkan pemegang mengajukan permintaan pemverifikasian paket. Tidak pernah dibutuhkan oleh apl normal."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verifikasi maksud filter"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Mengizinkan aplikasi memeriksa apakah maksud filter diverifikasi atau tidak."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"ikat ke pemverifikasi maksud filter"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Mengizinkan pemegangnya mengajukan permintaan pemverifikasi maksud filter. Tidak diperlukan untuk aplikasi normal."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"akses port serial"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Memungkinkan pemegangnya mengakses port serial menggunakan API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"mengakses penyedia konten dari luar"</string>
@@ -1544,6 +1582,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Kurangi hari"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Tambah tahun"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Kurangi tahun"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Bulan sebelumnya"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Bulan berikutnya"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Batal"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Hapus"</string>
@@ -1794,11 +1834,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Penggeser putar menit"</string>
     <string name="select_hours" msgid="6043079511766008245">"Pilih jam"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Pilih menit"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Kisi hari pada bulan"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Daftar tahun"</string>
     <string name="select_day" msgid="7774759604701773332">"Pilih bulan dan hari"</string>
     <string name="select_year" msgid="7952052866994196170">"Pilih tahun"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> dipilih"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dihapus"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Kantor <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Untuk melepas pin layar ini, sentuh lama tombol Kembali dan Ringkasan secara bersamaan."</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index a926d3d..3ea140d 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Slökkt á reikiborða"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Leitar að þjónustu"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi símtöl"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ekki áframsent"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> eftir <xliff:g id="TIME_DELAY">{2}</xliff:g> sekúndur"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Leyfir forriti að taka myndir og myndskeið með myndavélinni. Þessi heimild leyfir forritinu að nota myndavélina hvenær sem er án þinnar heimildar."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"slökkva á gaumljósi flutnings þegar myndavél er í notkun"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Leyfir foruppsettu kerfisforriti að gera gaumljós myndavélarinnar óvirkt."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Leyfir foruppsettu kerfisforriti að senda myndavélarþjónustunni kerfisatvik."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"gera spjaldtölvuna varanlega óvirka"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"gera sjónvarpið varanlega óvirkt"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"gera símann varanlega óvirkan"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"ræsa CDMA-uppsetningu sjónvarps beint"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"ræsa CDMA-uppsetningu síma beint"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Leyfir forriti að ræsa CDMA-úthlutun. Spilliforrit geta ræst CDMA-úthlutun að óþörfu."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"stjórna tilkynningum um staðsetningaruppfærslur"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Leyfir forriti að kveikja/slökkva á uppfærslutilkynningum um staðsetningu frá loftnetinu. Ekki ætlað venjulegum forritum."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"aðgangur að mætingareigindum"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Gerir forritinu kleift að beita aðferðum til að bæta við og eyða fingrafarasniðmátum til notkunar."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"nota fingrafarabúnað"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Leyfir forritinu að nota fingrafarabúnað til auðkenningar"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Hluti fingrafars greindist. Reyndu aftur."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Ekki var hægt að vinna úr fingrafarinu. Reyndu aftur."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingrafaraskynjarinn er óhreinn. Hreinsaðu hann og reyndu aftur."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Fingurinn hreyfðist of hratt. Reyndu aftur."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Fingurinn hreyfðist of hægt. Reyndu aftur."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Skráningarvilluboð 0 frá framleiðanda"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Ekki var hægt að vinna úr þessu. Reyndu aftur."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Vélbúnaður er ekki tiltækur."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ekki er hægt að vista fingrafarið. Fjarlægðu eitthvert af fingraförunum sem fyrir eru."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tímamörk runnu út fyrir fingrafar. Reyndu aftur."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Tímamörk runnu út fyrir fingrafar. Reyndu aftur."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Villuboð frá framleiðanda."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lesa samstillingar"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Leyfir forriti að lesa kosti samstillingar fyrir reikning. Þetta er til dæmis hægt að nota til að komast að því hvort forritið Fólk er samstillt við reikning."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"kveikja og slökkva á samstillingu"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Leyfir forriti að fjarlægja DRM-vottorð. Ætti aldrei að vera nauðsynlegt fyrir venjuleg forrit."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"bindast skilaboðaþjónustu símafyrirtækis"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Leyfir forriti að bindast efsta viðmótslagi skilaboðaþjónustu símafyrirtækis. Ætti aldrei að vera nauðsynlegt fyrir venjuleg forrit."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setja reglur um aðgangsorð"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Stjórna lengd og fjölda stafa í aðgangsorðum og PIN-númerum skjáláss."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Fylgjast með tilraunum til að taka skjáinn úr lás"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Leyfir forriti að staðfesta að hægt sé að setja upp pakka."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bindast pakkasannvottun"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Leyfir handhafa að búa til beiðnir fyrir pakkastaðfestingu. Ætti aldrei að vera nauðsynlegt fyrir venjuleg forrit."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"staðfesta ásetningssíu"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Leyfir forriti að athuga hvort ásetningssía er staðfest eða ekki."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"bindast staðfestingu ásetningssíu"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Leyfir handhafa að búa til beiðnir fyrir staðfestingu ásetningssíu. Ætti aldrei að vera nauðsynlegt fyrir venjuleg forrit."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"aðgangur að raðtengjum"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Leyfir forriti að fá aðgang að raðtengjum með forritaskilum SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"ytri aðgangur að efnisveitum"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Niður um dag"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Upp um ár"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Niður um ár"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Fyrri mánuður"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Næsti mánuður"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Hætta við"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Eyða"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Valskífa fyrir mínútur"</string>
     <string name="select_hours" msgid="6043079511766008245">"Veldu klukkustundir"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Veldu mínútur"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Mánaðartafla með dögum"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Áralisti"</string>
     <string name="select_day" msgid="7774759604701773332">"Veldu mánuð og dag"</string>
     <string name="select_year" msgid="7952052866994196170">"Veldu ár"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> valið"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eytt"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Til að taka lásinn af þessari skjámynd skaltu halda inni Til baka og Yfirliti samtímis."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 74ad5f7..cd7dbd1 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Banner roaming disattivato"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Ricerca servizio"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Chiamate Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: inoltro non effettuato"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> dopo <xliff:g id="TIME_DELAY">{2}</xliff:g> secondi"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Consente all\'applicazione di scattare foto e riprendere video con la fotocamera. Questa autorizzazione consente all\'applicazione di utilizzare la fotocamera in qualsiasi momento senza la tua conferma."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"disabilitazione del LED di indicazione della trasmissione quando la fotocamera è in uso"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Consente a un\'applicazione di sistema preinstallata di disabilitare il LED che indica l\'utilizzo della fotocamera."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Consente a un\'applicazione di sistema preinstallata di inviare eventi di sistema al sistema della fotocamera."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"disattivazione definitiva tablet"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"disattivazione definitiva della TV"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"disattivazione telefono"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"avvio diretto della configurazione della TV CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"avviare direttamente la configurazione del telefono CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Consente all\'applicazione di avviare il servizio di provisioning CDMA. Le applicazioni dannose potrebbero avviare il servizio di provisioning CDMA quando non è necessario."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controllo notifiche aggiornamento posizione"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Consente all\'applicazione di abilitare/disabilitare le notifiche di aggiornamento sulla posizione dal segnale radio. Da non usare per normali applicazioni."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"accesso a proprietà di archiviazione"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Consente all\'app di richiamare metodi per aggiungere e rimuovere modelli di impronte digitali da utilizzare."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"utilizza hardware per il riconoscimento delle impronte digitali"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Consente all\'app di utilizzare l\'hardware per il riconoscimento delle impronte digitali per eseguire l\'autenticazione"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Rilevata impronta digitale parziale. Riprova."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossibile elaborare l\'impronta digitale. Riprova."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Il sensore di impronte digitali è sporco. Puliscilo e riprova."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Movimento del dito troppo rapido. Riprova."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Movimento del dito troppo lento. Riprova."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Messaggio di errore di acquisizione specifico del fornitore: 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Impossibile elaborare l\'impronta. Riprova."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware non disponibile."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossibile memorizzare l\'impronta digitale. Rimuovi un\'impronta esistente."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timeout impronta digitale. Riprova."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Timeout impronta digitale. Riprova."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Messaggio di errore specifico del fornitore."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lettura impostazioni di sincronizz."</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Consente all\'applicazione di leggere le impostazioni di sincronizzazione per un account. Ad esempio, questa autorizzazione può determinare se l\'applicazione Persone è sincronizzata con un account."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"attivazione e disattivazione della sincronizzazione"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Consente a un\'applicazione di rimuovere certificati DRM. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"associazione a un servizio di messaggi dell\'operatore"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Consente l\'associazione di un servizio di messaggi dell\'operatore all\'interfaccia principale. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Impostazione regole password"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controlla la lunghezza e i caratteri ammessi nelle password e nei PIN del blocco schermo."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Controllo tentativi di sblocco dello schermo"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Consente all\'applicazione di verificare se un pacchetto è installabile."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"associazione a verifica pacchetto"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Consente al proprietario di effettuare richieste relative alle verifiche dei pacchetti. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verifica filtro di intent"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Consente all\'app di verificare se un filtro di intent è stato verificato o meno."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"collegamento a uno strumento di verifica dei filtri di intent"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Consente al proprietario di effettuare richieste relative agli strumenti di verifica dei filtri di intent. Non dovrebbe mai essere necessario per applicazioni normali."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"accesso alle porte seriali"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permette al proprietario di accedere alle porte seriali utilizzando l\'API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"accesso a fornitori di contenuti esterni"</string>
@@ -1388,7 +1428,7 @@
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Debug USB collegato"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Tocca per disattivare il debug USB."</string>
     <string name="select_input_method" msgid="8547250819326693584">"Cambia tastiera"</string>
-    <string name="configure_input_methods" msgid="4769971288371946846">"Scegli tastiere"</string>
+    <string name="configure_input_methods" msgid="4769971288371946846">"Scegli tastiera"</string>
     <string name="show_ime" msgid="9157568568695230830">"Mostra metodo immissione"</string>
     <string name="hardware" msgid="7517821086888990278">"Hardware"</string>
     <string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Seleziona layout tastiera"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Riduci giorno"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumenta anno"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Riduci anno"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Mese precedente"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Mese successivo"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Annulla"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Canc"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Dispositivo di scorrimento circolare per i minuti"</string>
     <string name="select_hours" msgid="6043079511766008245">"Seleziona le ore"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Seleziona i minuti"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Griglia di giorni per mese"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Elenco degli anni"</string>
     <string name="select_day" msgid="7774759604701773332">"Seleziona mese e giorno"</string>
     <string name="select_year" msgid="7952052866994196170">"Seleziona anno"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Elemento selezionato: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminato"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> lavoro"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Per sbloccare questa schermata, tocca e tieni premute contemporaneamente le opzioni Indietro e Panoramica."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 1e8d680..10dd8e1 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -126,8 +126,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"מודעת באנר נודדת כבויה"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"מחפש שירות"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"‏שיחות ב-Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ללא העברה"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> כעבור <xliff:g id="TIME_DELAY">{2}</xliff:g> שניות"</string>
@@ -586,6 +597,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"מאפשר לאפליקציה לצלם תמונות וסרטונים באמצעות המצלמה. אישור זה מאפשר לאפליקציה להשתמש במצלמה בכל עת ללא אישורך."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"השבת את נורית מצב השידור כשהמצלמה בשימוש"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"מתיר לאפליקציית מערכת המותקן מראש להשבית את השימוש של המצלמה בנורית המצב."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"התר לאפליקציית מערכת שהותקנה מראש לשלוח את אירועי המערכת של שירות המצלמה."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"השבת טאבלט לצמיתות"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"השבתה של הטלוויזיה לצמיתות"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"השבת טלפון לצמיתות"</string>
@@ -634,6 +646,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"‏הפעלה ישירה של הגדרת CDMA בטלוויזיה"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"‏הפעל ישירות הגדרה של טלפון CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"‏מאפשר לאפליקציה להפעיל הקצאת CDMA. אפליקציות זדוניות עלולות להפעיל הקצאת CDMA ללא צורך."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"שלוט בהתראות על עדכון מיקום"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"מאפשר לאפליקציה לאפשר/להשבית התראות לגבי עדכוני מיקום מהרדיו. לא מיועד לשימוש על ידי אפליקציות רגילות."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"גישה למאפייני כניסה"</string>
@@ -748,6 +764,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"מאפשר לאפליקציה להפעיל שיטות להוספה ומחיקה של תבניות טביעות אצבעות שבהן ייעשה שימוש."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"שימוש בחומרה של טביעות אצבעות"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"מאפשר לאפליקציה להשתמש בחומרה של טביעות אצבעות לצורך אימות"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"זוהתה טביעת אצבע חלקית. נסה שוב."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"לא ניתן היה לעבד את טביעת האצבע. נסה שוב."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"החיישן של טביעות האצבעות מלוכלך. נקה אותו ונסה שוב."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"האצבע זזה מהר מדי, נסה שוב."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"האצבע זזה לאט מדי, נסה שוב."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"הודעת שגיאה 0 של רכישה ספציפית לספק"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"אין אפשרות לעבד. נסה שוב."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"החומרה לא זמינה."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"לא ניתן לאחסן טביעת אצבע. הסר טביעת אצבע קיימת."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"חלף הזמן הקצוב לטביעת אצבע. נסה שוב."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"חלף הזמן הקצוב לטביעת אצבע. נסה שוב."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"הודעת שגיאה ספציפית לספק."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"קרא את הגדרות הסינכרון"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"מאפשר לאפליקציה לקרוא את הגדרות הסנכרון של חשבון. לדוגמה, ניתן לגלות כך האם האפליקציה \'אנשים\' מסונכרן עם חשבון כלשהו."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"הפעלת וכיבוי סנכרון"</string>
@@ -824,6 +856,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"‏הרשאה זו מאפשרת לאפליקציה להסיר אישורי DRM. באפליקציות רגילות אף פעם לא אמור להיות בה צורך."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"איגוד לשירות העברת הודעות של ספק"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"מאפשרת לבעלים לאגד לממשק ברמה העליונה של שירות העברת הודעות של ספק. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"אינטראקציה עם שירות אינטראקציה קולית"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"מאפשר לבעלים לקיים אינטראקציה עם השירות הפעיל הנוכחי של אינטראקציה קולית. לא אמורה להיות נחוצה לאפליקציות רגילות."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"‏קביעת האורך הנדרש והתווים המותרים בסיסמאות ובקודי PIN של מסך הנעילה."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"עקוב אחר ניסיונות לביטול נעילת מסך"</string>
@@ -1121,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"מאפשר לאפליקציה לאמת שחבילה ניתנת להתקנה."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"הכפפה למאמת חבילה"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"מאפשר למשתמש להגיש בקשות של מאמתי חבילות. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"אימות של מסנן כוונה"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"מאפשר לאפליקציה לבדוק אם מסנן כוונה אומת או לא."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"הכפפה אל מאמת של מסנן כוונה"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"מאפשר למשתמש להגיש בקשות של מאמתי סינון כוונה. לעולם לא אמור להיות נחוץ לאפליקציות רגילות."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"גישה ליציאות טוריות"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"‏מאפשר לבעלים לגשת ליציאות טוריות באמצעות ממשק ה- API של SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"גישה לספקי תוכן באופן חיצוני"</string>
@@ -1560,6 +1598,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"הפחת יום"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"הוסף שנה"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"הפחת שנה"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"החודש הקודם"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"החודש הבא"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"ביטול"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"מחק"</string>
@@ -1812,11 +1852,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"מחוון דקות מעגלי"</string>
     <string name="select_hours" msgid="6043079511766008245">"בחר שעות"</string>
     <string name="select_minutes" msgid="3974345615920336087">"בחר דקות"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"בחירת ימים בחודש בתצוגת רשת"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"רשימת שנים"</string>
     <string name="select_day" msgid="7774759604701773332">"בחר חודש ויום"</string>
     <string name="select_year" msgid="7952052866994196170">"בחר שנה"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> נבחר"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> נמחק"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"עבודה <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"כדי לבטל את הקפאת המסך הזה, גע בו-זמנית נגיעה ממושכת ב\'הקודם\' ו\'סקירה\'."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 5598018..a7e8cc0 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"ローミングバナーOFF"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"サービスを検索中"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi通話"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:転送できません"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g> (<xliff:g id="TIME_DELAY">{2}</xliff:g>秒後)"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"カメラでの写真と動画の撮影をアプリに許可します。これにより、アプリが確認なしでいつでもカメラを使用できるようになります。"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"カメラの使用中に通信インジケータLEDを無効にする"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"カメラ使用インジケータLEDを無効にすることをプレインストールされているシステムアプリに許可します。"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"カメラサービスにシステムイベントを送信することをプレインストールされているシステムアプリに許可します。"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"タブレットを完全に無効化"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"テレビを完全に無効化"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"端末を永続的に無効にする"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMAテレビのセットアップを直接開始"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA携帯電話のセットアップを直接開始"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"CDMAプロビジョニングの開始をアプリに許可します。この許可を悪意のあるアプリケーションに利用されると、不要なCDMAプロビジョニングが開始される恐れがあります。"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"位置情報の更新通知"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"無線からの現在地情報のアップデート通知を有効/無効にすることをアプリに許可します。通常のアプリでは使用しません。"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"チェックインプロパティへのアクセス"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"使用する指紋テンプレートの追加や削除を行う方法の呼び出しをアプリに許可します。"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"指紋ハードウェアの使用"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"指紋ハードウェアを認証に使用することをアプリに許可します"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"指紋を一部しか検出できませんでした。もう一度お試しください。"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"指紋を処理できませんでした。もう一度お試しください。"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"指紋センサーに汚れがあります。汚れを落としてもう一度お試しください。"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"指の動きが速すぎました。もう一度お試しください。"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"指の動きが遅すぎました。もう一度お試しください。"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"ベンダー固有の取得エラーメッセージ0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"処理できませんでした。もう一度お試しください。"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"ハードウェアを利用できません。"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"指紋を保存できません。既存の指紋を削除してください。"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋の読み取りがタイムアウトになりました。もう一度お試しください。"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"指紋の読み取りがタイムアウトになりました。もう一度お試しください。"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"ベンダー固有のエラーメッセージです。"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"同期設定の読み取り"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"アカウントの同期設定の読み取りをアプリに許可します。たとえば、連絡帳アプリがアカウントと同期しているかどうかをアプリから特定できるようになります。"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"同期のON/OFFの切り替え"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM証明書の削除をアプリに許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"携帯通信会社のSMSサービスへのバインド"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"携帯通信会社のSMSサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"画面ロックのパスワードとPINの長さと使用できる文字を制御します。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"画面ロック解除試行の監視"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"パッケージがインストール可能かどうか確認することをアプリに許可します。"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"パッケージベリファイアにバインド"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"パッケージベリファイアのリクエストを所有者に許可します。通常のアプリでは不要です。"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"インテントフィルタの検証"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"インテントフィルタが検証されているかどうかを確認することをアプリに許可します。"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"インテントフィルタベリファイアにバインド"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"インテントフィルタベリファイアのリクエストを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"シリアルポートへのアクセス"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager APIを使用してシリアルポートにアクセスすることを所有者に許可します。"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"コンテンツプロバイダへの外部アクセス"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"1日戻します"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"1年進めます"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"1年戻します"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"前月"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"翌月"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"キャンセル"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"削除"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"円形スライダー(分)"</string>
     <string name="select_hours" msgid="6043079511766008245">"時間を選択"</string>
     <string name="select_minutes" msgid="3974345615920336087">"分を選択"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"日グリッド(月別)"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"年リスト"</string>
     <string name="select_day" msgid="7774759604701773332">"月と日を選択"</string>
     <string name="select_year" msgid="7952052866994196170">"年を選択"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g>を選択しました"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g>を削除しました"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"仕事の<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"この画面の固定を解除するには[戻る]と[最近]を同時に押し続けます。"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index d179c28..7feaf3b 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"როუმინგის ბანერი გამორთულია"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"სერვისის ძიება"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"დარეკვა Wi-Fi-ს მეშვეობით"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: არ არის გადამისამართებული"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> წამის შემდეგ"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"აპს შეეძლება კამერით სურათისა და ვიდეოს გადაღება. ეს ნებართვა აპს უფლებას აძლევს, ნებისმიერ დროს გამოიყენოს კამერა თქვენი დადასტურების გარეშე."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"კამერის გამოყენებისას გადამცემი ინდიკატორის LED გათიშვა"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"ნებას რთავს წინასწარ დაყენებული სისტემის აპლიკაციას, გამორთოს კამერის გამოყენების ინდიკატორი LED."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"საშუალებას აძლევს წინასწარ დაყენებულ სისტემის აპლიკაციებს გააგზავნონ კამერის მომსახურების სისტემური მოვლენები."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"მუდმივად გამორთული ტაბლეტი"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"ტელევიზორის მუდმივად გამორთვა"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ტელეფონის სამუდამოდ დეაქტივაცია"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"პირდაპირ დაიწყოს CDMA ტელევიზორის დაყენება"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA ტელეფონის დაყენების პირდაპირ დაწყება"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"აპს შეეძლება, დაიწყოს CDMA უზრუნველყოფა. მავნე აპებმა შეიძლება ზედმეტად, საჭიროების გარეშე დაიწყონ CDMA უზრუნველყოფა."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"მდებარეობის განახლების შეტყობინებების კონტროლი"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"აპს შეეძლება მდებარეობის განახლების შესახებ რადიო შეტყობინებების აქტივაცია/დეაქტივაცია. ჩვეულებრივი აპები ამ ფუნქციას არ იყენებენ."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"სარეგისტრაციო პარამეტრებზე წვდომა"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"საშუალებას აძლევს აპლიკაციას დაამატოს ან ამოშალოს გამოსაყენებელი თითის ანაბეჭდის ნიმუშები,"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"თითის ანაბეჭდის აპარატის გამოყენება"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"საშუალებას აძლევს აპლიკაციას გამოიყენოს ავტენთიფიკაციისათვის თითის ანაბეჭდის აპარატი"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"აღმოჩენილია თითის ნაწილობრივი ანაბეჭდი. გთხოვთ, სცადოთ ხელახლა."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"თითის ანაბეჭდი ვერ მუშავდება. გთხოვთ, სცადოთ ხელახლა."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"თითის ანაბეჭდის სენსორი დაბინძურებულია. გთხოვთ, გაასუფთაოთ და სცადოთ ხელახლა."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"თითის აღება მეტისმეტად სწრაფად მოხდა. გთხოვთ, სცადოთ ხელახლა."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"თითის აღება მეტისმეტად ნელა მოხდა. გთხოვთ, სცადოთ ხელახლა."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"მომწოდებლის მიხედვით სპეციფიკური მოპოვების შეცდომის შეტყობინება 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"დამუშავება შეუძლებელია. სცადეთ ხელახლა."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"აპარატურა არ არის ხელმისაწვდომი."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"თითის ანაბეჭდის შენახვა ვერ ხერხდება. გთხოვთ, ამოშალოთ არსებული თითის ანაბეჭდი."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"თითის ანაბეჭდის ლოდინის დრო ამოიწურა. სცადეთ ხელახლა."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"თითის ანაბეჭდის ლოდინის დრო ამოიწურა. სცადეთ ხელახლა."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"მომწოდებლის მიხედვით სპეციფიკური შეცდომის შეტყობინება."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"სინქრონიზაციის პარამეტრების წაკითხვა"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"აპს შეეძლება, წაიკითხოს ანგარიშის სინქრონიზაციის პარამეტრები. მაგალითად, მას შეეძლება განსაზღვროს, არის თუ არა People აპი სინქრონიზებული ანგარიშთან."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"სინქრონიზაციის ჩართვა და გამორთვა"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"საშუალებას აძლევს აპლიკაციას ამოშალოს DRM სერtიფიკატები. ეს წესით ჩვეულებრივ აპებს არ უნდა დაჭირდეს."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"აკავშირებს შეტყობინების გაცვლის მომსახურებას"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"საშუალებას აძლევს მფლობელს შექმნას შეტყობინების გაცვლის მომსახურების უმახლესი დონის ინტერფეისი. არასდროს იქნება საჭირო ნორმალური აპლიკაციებისათვის."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"პაროლის წესების დაყენება"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"აკონტროლეთ ეკრანის ბლოკირების პაროლებისა და PIN-ების სიმბოლოების სიგრძე."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ეკრანის განბლოკვის მცდელობების გაკონტროლება"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"აპს შეუძლია დაადასტუროს პაკეტის დაყანების შესაძლებლობა."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"პაკეტების ვერიფიკატორებთან დაკავშირება"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"მფლობელს შეეძლება პაკეტის ვერიფიკატორების მოთხოვნა. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"სამიზნე ფილტრის დამოწმება"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"საშუალებას აძლევს აპლიკაციას შეამოწმოს დამოწმებულია თუ არა სამიზნე ფილტრი."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"სამიზნე ფილტრის დამოწმებაზე მიბმა"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"საშუალებას აძლევს მფლობელს მოითხოვოს სამიზნე ფილტრის დამოწმება. არასოდეს არის საჭირო ნორმალური აპლიკაციისას."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"სერიულ პორტებზე წვდომა"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"მფლობელს შეეძლება სერიულ პორტებზე წვდომა სერიული მენეჯერის  API-ის გამოყენებით."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"კონტენტის მომწოდებლებთან გარედან წვდომა"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"დღის მოკლება"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"წლის მომატება"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"წლის მოკლება"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"წინა თვე"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"მომდევნო თვე"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"გაუქმება"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"წაშლა"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"წუთების წრიული სლაიდერი"</string>
     <string name="select_hours" msgid="6043079511766008245">"აირჩიეთ საათები"</string>
     <string name="select_minutes" msgid="3974345615920336087">"აირჩიეთ წუთები"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"დღეების ბადე თვეზე"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"წლის სია"</string>
     <string name="select_day" msgid="7774759604701773332">"აირჩიეთ თვე და რიცხვი"</string>
     <string name="select_year" msgid="7952052866994196170">"აირჩიეთ წელი"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"არჩეულია <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> წაიშალა"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"მიმაგრების გასაუქმებლად ერთდროულად შეეხეთ და არ აუშვათ ღილაკებს „უკან“ და „მიმოხილვა“."</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index caa12d2..9f32ad4 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Роуминг баннері өшірулі"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Қызметті іздеу"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi қоңыраулары"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Басқа нөмірге бағытталмады"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>  <xliff:g id="TIME_DELAY">{2}</xliff:g> секундтан кейін"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Қолданбаға камераны қолданып, фотосурет немесе бейне жазу мүмкіндігін береді. Бұл рұқсат камераны кез келген уақытта сіздің құптауыңызды қажет етпей қолдану мүмкіндігін береді."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"камера қолданыста болғанда жарық диодты шамы бар көрсеткішті өшіру"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Алдын ала орнатылған жүйе қолданбасына камераның жарық диодты көрсеткішті қолдануын өшіру мүмкіндігін береді."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Алдын ала орнатылған жүйе қолданбасына камера қызметі жүйесінің оқиғаларын жіберуге рұқсат береді."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"планшетті мүлдем өшіру"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"ТД біржола өшіру"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"телефонды мүлдем өшіру"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA ТД параметрлерін орнатуды тікелей бастау"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"тікелей CDMA телефон орнатуларын бастау"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Қолданбаға CDMA дайындауды бастауға рұқсат береді. Зиянкес қолданбалар CDMA дайындауды қажет емес кезде бастауы мүмкін."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"аймақ жаңарту хабарларын басқару"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Қолданбаға радиодан алынатын орынды жаңарту туралы хабарландыруларды қосуға/өшіруге рұқсат береді. Қалыпты қолданбалардың пайдалануына арналмаған."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"тіркелу деректеріне кіру"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Қолданбаға пайдаланатын саусақ ізі үлгілерін қосу және жою әдістерін шақыруға мүмкіндік береді."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"саусақ ізі жабдығын пайдалану"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Қолданбаға аутентификацияалу үшін саусақ ізі жабдығын пайдалануға мүмкіндік береді"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Саусақ ізі ішінара анықталды. Әрекетті қайталаңыз."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Саусақ ізін өңдеу мүмкін емес. Әрекетті қайталаңыз."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Саусақ ізі сенсоры лас. Тазалап, әрекетті қайталаңыз."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Саусақ тым тез қозғалды. Әрекетті қайталаңыз."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Саусақ тым баяу қозғалды. Әрекетті қайталаңыз."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Жеткізушіге тән алу қатесі туралы хабар 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Өңдеу мүмкін емес. Әрекетті қайталаңыз."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Жабдық қол жетімді емес."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Саусақ ізін сақтау мүмкін емес. Бар саусақ ізін жойыңыз."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Саусақ ізін күту уақыты бітті. Әрекетті қайталаңыз."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Саусақ ізін күту уақыты бітті. Әрекетті қайталаңыз."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Жеткізушіге тән қате туралы хабар."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"синх параметрлерін оқу"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Қолданбаға есептік жазба синхрондау параметрлерін оқу мүмкіндігін береді. Мысалы, бұл арқылы People қолданбасының есептік жазбамен сихрондалғаны анықталуы мүмкін."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"синх қосу және өшіру арасында ауысу"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Қолданбаға DRM сертификаттарын жоюға рұқсат етеді. Қалыпты қолданбалар үшін ешқашан қажет болмайды."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"оператордың хабар алмасу қызметіне байластыру"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Иесіне оператордың хабар алмасу қызметінің жоғарғы деңгейлі интерфейсіне байластыруға рұқсат етеді. Қалыпты қолданбалар үшін ешқашан қажет болмайды."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Кілтсөз ережелерін тағайындау"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Экран бекітпесінің құпия сөздерінің және PIN кодтарының ұзындығын және оларда рұқсат етілген таңбаларды басқару."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Экранды ашу әркеттерін бақылау"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Қолданбаға буманы орнатуға болатынын тексеруге рұқсат береді."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"жинақ растау қызметіне байланыстыру"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Пайдаланушыға бума верификаторларының сұрауларын жасауға рұқсат береді. Қалыпты қолданбалар үшін ешқашан қажет болмайды."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"интент-сүзгіні тексеру"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Қолданбаға интент-сүзгі тексерілген не тексерілмегенін анықтау мүмкіндігін береді."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"интент-сүзгі верификаторына байланыстыру"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Пайдаланушыға интент-сүзгі верификаторларының сұрауларын жасауға рұқсат береді. Қалыпты қолданбалар үшін ешқашан қажет болмайды."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"сериялық портқа кіру"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Пайдаланушыға Сериялық Менеджер қолданба бағдарламалау интерфейсін қолданып, сериялық порттарға кіру мүмкіндігін ұсынады."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"мазмұн жабдықтаушыларға сырттан қатынасу"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Күн азайту"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Жыл арттыру"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Жыл азайту"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Алдыңғы ай"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Келесі ай"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Өшіру"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Жою"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Минут айналымын қозғалтқыш"</string>
     <string name="select_hours" msgid="6043079511766008245">"Сағат таңдау"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Минут таңдау"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Күндердің айлық торлары"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Жыл тізімі"</string>
     <string name="select_day" msgid="7774759604701773332">"Ай мен күнді таңдау"</string>
     <string name="select_year" msgid="7952052866994196170">"Жыл таңдау"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> таңдалды"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> жойылды"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Жұмыс <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Осы экранды босату үшін «Кері» және «Шолу» пәрмендерін бір уақытта түртіп, ұстап тұрыңыз."</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 3326462..5210112 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"បិទ​បដា​រ៉ូមីង"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"​ស្វែង​រក​សេវាកម្ម"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"ការហៅតាម Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិន​បាន​បញ្ជូន​បន្ត"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> បន្ទាប់​ពី <xliff:g id="TIME_DELAY">{2}</xliff:g> វិនាទី"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"ឲ្យ​កម្មវិធី​ថត​រូប និង​វីដេអូ​ដោយ​ប្រើ​ម៉ាស៊ីន​ថត។ វា​ឲ្យ​កម្មវិធី​​ប្រើ​ម៉ាស៊ីន​ថត​នៅ​ពេល​​ណាមួយ​ដោយ​គ្មាន​ការ​បញ្ជាក់​របស់​អ្នក។"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"បិទ​​ពន្លឺ​បង្ហាញ​ការ​បញ្ជូន​​ពេល​ម៉ាស៊ីន​ថត​កំពុង​ប្រើ"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"ឲ្យ​កម្មវិធី​ប្រព័ន្ធ​ដែល​បាន​ដំឡើង​រួច​បិទ​​ LED បង្ហាញ​ការ​ប្រើ​ម៉ាស៊ីន​ថត។"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"អនុញ្ញតឲ្យកម្មវិធីប្រព័ន្ធដែលបានដំឡើងជាមុនផ្ញើព្រឹត្តិការណ៍ប្រព័ន្ធសេវាកាមេរ៉ា។"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"បិទ​កុំព្យូទ័រ​បន្ទះ​ជា​អចិន្ត្រៃយ៍"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"បិទដំណើរការទូរទស្សន៍ជាអចិន្ត្រៃយ៍"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"បិទ​ទូរស័ព្ទ​ជា​អចិន្ត្រៃយ៍"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"ចាប់ផ្តើមកំណត់ទូរទស្សន៍ CDMA ដោយផ្ទាល់"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"ចាប់ផ្ដើម​រៀបចំ​កុំព្យូទ័រ​បន្ទះ CDMA ដោយ​ផ្ទាល់"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"ឲ្យ​កម្មវិធី​ចាប់ផ្ដើម​ការ​ផ្ដល់ CDMA ។ កម្មវិធី​ព្យាបាទ​អាច​មិន​ចាំបាច់​ចាប់ផ្ដើម​ការ​ផ្ដល់ CDMA ។"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"ពិនិត្យ​​ការ​ជូន​ដំណឹង​បច្ចុប្បន្ន​ភាព​ទីតាំង"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"ឲ្យ​កម្មវិធី​បិទ/បើក​ការ​ជូន​ដំណឹង​បច្ចុប្បន្នភាព​ទីតាំង​ពី​វិទ្យុ។ មិន​សម្រាប់​ប្រើ​ដោយ​កម្មវិធី​ធម្មតា​ទេ។។"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"ចូល​ដំណើរការ​លក្ខណៈ​សម្បត្តិ​ពិនិត្យ​មើល"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"អនុញ្ញាតឲ្យកម្មវិធីប្រើវិធីសាស្ត្របន្ថែម និងលុបពុម្ពម្រាមដៃសម្រាប់ប្រើប្រាស់។"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ប្រើផ្នែករឹងស្នាមម្រាមដៃ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"អនុញ្ញាតឲ្យកម្មវិធីប្រើផ្នែករឹងស្នាមម្រាមដៃសម្រាប់ការផ្ទៀងផ្ទាត់"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"បានផ្តិតយកស្នាមម្រាមដៃមិនពេញលក្ខណៈ។ សូមព្យាយាមម្តងទៀត។"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"មិនអាចដំណើរការស្នាមម្រាមដៃបានទេ។ សូមព្យាយាមម្តងទៀត។"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ឧបករណ៍ផ្តិតម្រាមដៃប្រលាក់ហើយ។ សូមសម្អាត ហើយព្យាយាមម្តងទៀត។"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"ម្រាមដៃមានចលនារហ័សពេក។ សូមព្យាយាមម្តងទៀត។"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"ម្រាមដៃមានចលនាយឺតពេក។ សូមព្យាយាមម្តងទៀត។"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"សារកំហុសនៃការទិញពីអ្នកលក់ជាក់លាក់ 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"មិនអាចដំណើរការបានទេ។ សូមព្យាយាមម្តងទៀត។"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"មិនមានផ្នែករឹងទេ។"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"មិនអាចផ្ទុកស្នាមម្រាមដៃទេ។ សូមយកស្នាមម្រាមដៃដែលមានស្រាប់ចេញ។"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ការផ្តិតម្រាមដៃបានអស់ពេល។ សូមព្យាយាមម្តងទៀត។"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"ការផ្តិតម្រាមដៃបានអស់ពេល។ សូមព្យាយាមម្តងទៀត។"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"សារកំហុសពីអ្នកលក់ជាក់លាក់។"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"អាន​ការ​កំណត់​ធ្វើ​សម​កាល​កម្ម"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ឲ្យ​កម្មវិធី​អាន​ការ​កំណត់​ធ្វើ​សម​កាល​កម្ម​សម្រាប់​គណនី។ ឧទាហរណ៍ វា​អាច​កំណត់​ថា​តើ​​​កម្មវិធី​ត្រូវ​បាន​បើក​ជា​មួយ​គណនី​ដែរ​ឬទេ។"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"បិទ/បើក​ការ​ធ្វើ​សម​កាល​កម្ម"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"អនុញ្ញាត​ឲ្យ​​កម្មវិធី​លុប​ចេញ​វិញ្ញាបនបត្រ DRM ​។ គួរ​តែ​មិន​ត្រូវការ​សម្រាប់​កម្មវិធី​ធម្មតា​។"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"ភ្ជាប់ទៅសេវាកម្មសារអ្នកផ្តល់សេវាកម្មទូរស័ព្ទ"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"អនុញ្ញាតឲ្យអ្នកប្រើភ្ជាប់ទៅអ៊ីនធឺហ្វេសកម្រិតខ្ពស់នៃសេវាកម្មសារអ្នកផ្តល់សេវាកម្មទូរស័ព្ទ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"កំណត់​ក្បួន​ពាក្យ​សម្ងាត់"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"គ្រប់គ្រងប្រវែង និងតួអក្សរដែលអនុញ្ញាតឲ្យប្រើក្នុងពាក្យសម្ងាត់ និងលេខសម្ងាត់ចាក់សោអេក្រង់។"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ពិនិត្យ​ការ​ព្យាយាម​ដោះ​សោ​អេក្រង់"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"ឲ្យ​កម្មវិធី​ផ្ទៀងផ្ទាត់​កញ្ចប់​ដែល​អាច​ដំឡើង​បាន។"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"ចង​ទៅ​កម្មវិធី​ផ្ទៀងផ្ទាត់​កញ្ចប់"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"ឲ្យ​ម្ចាស់​ស្នើ​កម្មវិធី​ផ្ទៀងផ្ទាត់​កញ្ចប់។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"ផ្ទៀងផ្ទាត់តម្រងចេតនា"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"អនុញ្ញាតឲ្យកម្មវិធីពិនិត្យមើលថាតើតម្រងចេតនាត្រូវបានផ្ទៀងផ្ទាត់ហើយឬនៅ។"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"ចងភ្ជាប់ទៅកម្មវិធីផ្ទៀងផ្ទាត់តម្រងចេតនា"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"អនុញ្ញាតឲ្យអ្នកគ្រប់គ្រងធ្វើការស្នើកម្មវិធីផ្ទៀងផ្ទាត់តម្រងចេតនា។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតានោះទេ។"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"ចូល​ដំណើរការ​ច្រក​ស៊េរី"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"អនុញ្ញាត​ឱ្យ​ចូល​ដំណើរ​ការ​ទៅ​កាន់​ច្រក​សៀរៀល​ដោយ​ប្រើ SerialManager API ។"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"ចូល​ដំណើរការ​ក្រុមហ៊ុន​ផ្ដល់​មាតិកា​ខាង​ក្រៅ"</string>
@@ -1546,6 +1586,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"បន្ថយ​ថ្ងៃ"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"បង្កើន​​ឆ្នាំ"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"បន្ថយ​ឆ្នាំ"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"ខែមុន"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"ខែក្រោយ"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់​"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"លុប"</string>
@@ -1796,11 +1838,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"គ្រាប់​រំកិល​រង្វង់​នាទី"</string>
     <string name="select_hours" msgid="6043079511766008245">"ជ្រើស​ម៉ោង"</string>
     <string name="select_minutes" msgid="3974345615920336087">"ជ្រើស​នាទី"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"ក្រឡា​​​ខែ​នៃ​ថ្ងៃ"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"បញ្ជី​ឆ្នាំ"</string>
     <string name="select_day" msgid="7774759604701773332">"ជ្រើស​ខែ និង​ថ្ងៃ"</string>
     <string name="select_year" msgid="7952052866994196170">"ជ្រើស​ឆ្នាំ"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"បាន​ជ្រើស <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"បាន​លុប <xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"កន្លែង​ធ្វើការ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"ដើម្បី​មិន​ភ្ជាប់​អេក្រង់​នេះ ប៉ះ ហើយ​សង្កត់​ថយក្រោយ និង​ទិដ្ឋភាព​នៅ​ពេល​តែ​មួយ។"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 2bd45d4..3867a3e 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"ರೋಮಿಂಗ್ ಬ್ಯಾನರ್ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"ಸೇವೆ ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"ವೈ-ಫೈ ಕರೆ ಮಾಡುವಿಕೆ"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ಫಾರ್ವರ್ಡ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> ಸೆಕೆಂಡುಗಳ ನಂತರ <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"ಕ್ಯಾಮರಾ ಮೂಲಕ ಚಿತ್ರಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಸೆರೆಹಿಡಿಯಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಈ ಅನುಮತಿಯು ನಿಮ್ಮ ಖಾತರಿ ಇಲ್ಲದೆಯೇ ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"ಕ್ಯಾಮರಾ ಬಳಕೆಯಲ್ಲಿರುವಾಗ ಪ್ರಸಾರ ಸೂಚಕ LED ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"ಕ್ಯಾಮರಾ ಬಳಕೆ ಸೂಚಕ LED ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಪೂರ್ವ-ಸ್ಥಾಪಿತ ಸಿಸ್ಟಂ ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"ಕ್ಯಾಮರಾ ಸೇವೆ ಸಿಸ್ಟಂ ಈವೆಂಟ್‌ಗಳನ್ನು ಕಳುಹಿಸಲು ಪೂರ್ವ-ಸ್ಥಾಪಿತ ಸಿಸ್ಟಂ ಅಪ್ಲಿಕೇಶನ್‌ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"ಶಾಶ್ವತವಾಗಿ ಟ್ಯಾಬ್ಲೆಟ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"ಟಿವಿಯನ್ನು ಶಾಶ್ವತವಾಗಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ಶಾಶ್ವತವಾಗಿ ಫೋನ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA ಟಿವಿ ಸೆಟಪ್ ಅನ್ನು ನೇರವಾಗಿ ಪ್ರಾರಂಭಿಸಿ"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA ಫೋನ್ ಸೆಟಪ್ ಅನ್ನು ನೇರವಾಗಿ ಪ್ರಾರಂಭಿಸಿ"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"CDMA ಒದಗಿಸುವಿಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಅನಗತ್ಯವಾಗಿ CDMA ಒದಗಿಸುವಿಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಬಹುದು."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"ಸ್ಥಾನ ನವೀಕರಣದ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿಯಂತ್ರಿಸಿ"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"ರೇಡಿಯೊದಿಂದ ಸ್ಥಳ ನವೀಕರಣ ಅಧಿಸೂಚನೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು/ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಬಳಕೆಗಲ್ಲ."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"ಚೆಕ್ಇನ್ ಗುಣಲಕ್ಷಣಗಳನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ಬಳಕೆಗೆ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಟೆಂಪ್ಲೇಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಮತ್ತು ಅಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಮನವಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಿ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ಭಾಗಶಃ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಪತ್ತೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸಾರ್ ಕೊಳೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಅದನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"ಬೆರಳನ್ನು ವೇಗವಾಗಿ ಸರಿಸಲಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"ಬೆರಳನ್ನು ನಿಧಾನವಾಗಿ ಸರಿಸಲಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"ಮಾರಾಟಗಾರ-ನಿರ್ದಿಷ್ಟ ಸ್ವಾಧೀನ ದೋಷ ಸಂದೇಶ 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"ಹಾರ್ಡ್‌ವೇರ್ ಲಭ್ಯವಿಲ್ಲ."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸಂಗ್ರಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ತೆಗೆದುಹಾಕಿ."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"ಮಾರಾಟಗಾರ-ನಿರ್ದಿಷ್ಟ ದೋಷ ಸಂದೇಶ."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ರೀಡ್‌ ಮಾಡು"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ಒಂದು ಖಾತೆಯ ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್‍‍ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, ಖಾತೆಯೊಂದಿಗೆ ಜನರ ಅಪ್ಲಿಕೇಶನ್ ಸಿಂಕ್ ಮಾಡಲಾಗಿದೆಯೇ ಎಂಬುದನ್ನು ಇದು ನಿರ್ಧರಿಸಬಹುದು."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ಸಿಂಕ್ ಆನ್ ಮತ್ತು ಸಿಂಕ್ ಆಫ್ ಟಾಗಲ್ ಮಾಡಿ"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM ಪ್ರಮಾಣಪತ್ರಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"ವಾಹಕ ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ ಸೇವೆಗೆ ಪ್ರತಿಬಂಧಿಸಿ"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"ವಾಹಕ ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ ಸೇವೆಯ ಮೇಲ್ಮಟ್ಟದ ಇಂಟರ್ಫೇಸ್‌ಗೆ ಪ್ರತಿಬಂಧಿಸಲು ಹೊಂದಿರುವವರಿಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಸಾಮಾನ್ಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗಾಗಿ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ಪಾಸ್‌ವರ್ಡ್ ನಿಮಯಗಳನ್ನು ಹೊಂದಿಸಿ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ಪರದೆ ಲಾಕ್‌ನಲ್ಲಿನ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಪಿನ್‌ಗಳ ಅನುಮತಿಸಲಾದ ಅಕ್ಷರಗಳ ಪ್ರಮಾಣವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ಪರದೆಯ-ಅನ್‌ಲಾಕ್ ಪ್ರಯತ್ನಗಳನ್ನು ಮಾನಿಟರ್ ಮಾಡಿ"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"ಪ್ಯಾಕೇಜ್‌‌‌ ಅನ್ನು ಸ್ಥಾಪಿಸಬಹುದಾದ ಪರಿಶೀಲನೆಯನ್ನು ಅಪ್ಲಿಕೇಶನ್‌‌ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"ಪ್ಯಾಕೇಜ್ ಪರಿಶೀಲಕಕ್ಕೆ ಪ್ರತಿಬಂಧಿಸಿ"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"ಪ್ಯಾಕೇಜ್‌ ಪರಿಶೀಲನಾಗಾರರ ವಿನಂತಿಗಳನ್ನು ಮಾಡಲು ಹೊಂದಿರುವವರಿಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಸಾಮಾನ್ಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"ಉದ್ದೇಶಿತ ಫಿಲ್ಟರ್ ಪರಿಶೀಲಿಸಿ"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"ಇಂಟರ್ನೆಟ್ ಫಿಲ್ಟರ್ ಅನ್ನು ಪರಿಶೀಲಿಸಲಾಗಿದೆಯೇ ಅಥವಾ ಇಲ್ಲವೆ ಎಂಬುದನ್ನು ಪರೀಕ್ಷಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"ಉದ್ದೇಶಿತ ಫಿಲ್ಟರ್ ಪರಿಶೀಲಕವನ್ನು ಪ್ರತಿಬಂಧಿಸಿ"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"ಉದ್ದೇಶಿತ ಫಿಲ್ಟರ್ ಪರಿಶೀಲನಾಗಾರರ ವಿನಂತಿಗಳನ್ನು ಮಾಡಲು ಹೊಂದಿರುವವರಿಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಸಾಮಾನ್ಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"ಸರಣಿ ಪೋರ್ಟ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API ಬಳಸಿಕೊಂಡು ಸರಣಿ ಪೋರ್ಟ್‌ಗಳಿಗೆ ಪ್ರವೇಶ ಪಡೆಯಲು ಹೊಂದಿರುವವರಿಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"ವಿಷಯ ಪೂರೈಕೆದಾರರನ್ನು ಬಾಹ್ಯ ರೀತಿಯಲ್ಲಿ ಪ್ರವೇಶಿಸಿ"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ದಿನವನ್ನು ಕಡಿಮೆಮಾಡಿ"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"ವರ್ಷವನ್ನು ಹೆಚ್ಚಿಸಿ"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ವರ್ಷವನ್ನು ಕಡಿಮೆಮಾಡಿ"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"ಹಿಂದಿನ ತಿಂಗಳು"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"ಮುಂದಿನ ತಿಂಗಳು"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"ರದ್ದುಮಾಡು"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ಅಳಿಸು"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"ನಿಮಿಷಗಳ ವೃತ್ತಾಕಾರ ಸ್ಲೈಡರ್"</string>
     <string name="select_hours" msgid="6043079511766008245">"ಗಂಟೆಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="select_minutes" msgid="3974345615920336087">"ನಿಮಿಷಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"ದಿನಗಳ ತಿಂಗಳಿನ ಗ್ರಿಡ್"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"ವರ್ಷದ ಪಟ್ಟಿ"</string>
     <string name="select_day" msgid="7774759604701773332">"ತಿಂಗಳು ಮತ್ತು ದಿನವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="select_year" msgid="7952052866994196170">"ವರ್ಷವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ಅಳಿಸಲಾಗಿದೆ"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"ಕೆಲಸ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"ಈ ಪರದೆಯನ್ನು ಅನ್‌ಪಿನ್ ಮಾಡಲು, ‘ಹಿಂದೆ’ ಮತ್ತು ‘ಸಮಗ್ರ ನೋಟ’ವನ್ನು ಏಕಕಾಲದಲ್ಲಿ ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 463f84d..702a309 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"로밍 배너 사용 안함"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"서비스 검색 중"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi 통화"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: 착신전환 안됨"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g><xliff:g id="TIME_DELAY">{2}</xliff:g>초 후"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"앱이 카메라로 사진과 동영상을 찍을 수 있도록 허용합니다. 이 권한을 사용하면 앱이 언제든지 사용자의 확인 없이 카메라를 사용할 수 있습니다."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"카메라를 사용할 때 전송 표시 LED 사용 중지"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"사전 설치된 시스템 애플리케이션에서 카메라 사용 표시 LED를 사용 중지하도록 허용합니다."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"사전 설치된 시스템 애플리케이션에서 카메라 서비스 시스템 이벤트를 전송하도록 허용합니다."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"영구적으로 태블릿 사용 안함"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"TV를 영구적으로 사용 중지"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"휴대전화를 영구적으로 사용 중지"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA TV 설정 바로 시작"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"직접 CDMA 전화 설정 시작"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"앱이 CDMA 프로비저닝을 시작할 수 있도록 허용합니다. 이 경우 악성 앱이 불필요하게 CDMA 프로비저닝을 시작할 수 있습니다."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"위치 업데이트 알림 제어"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"앱이 무선의 위치 업데이트 알림을 사용하거나 사용하지 않도록 허용합니다. 일반 앱에서는 사용하지 않습니다."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"체크인 속성 액세스"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"사용할 지문 템플릿의 추가 및 삭제 메소드를 앱에서 실행하도록 허용합니다."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"지문 하드웨어 사용"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"앱에서 지문 하드웨어를 인증에 사용하도록 허용합니다."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"지문이 일부만 인식되었습니다. 다시 시도해 주세요."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"지문을 인식할 수 없습니다. 다시 시도해 주세요."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"지문 센서를 깨끗이 닦고 다시 시도하세요."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"손가락을 너무 빨리 움직였습니다. 다시 시도해 주세요."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"손가락을 너무 느리게 움직였습니다. 다시 시도해 주세요."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"공급업체별 획득 오류 메시지 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"인식할 수 없습니다. 다시 시도하세요."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"하드웨어를 사용할 수 없습니다."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"지문을 저장할 수 없습니다. 기존 지문을 삭제하세요."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"지문 인식 시간이 초과되었습니다. 다시 시도하세요."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"지문 인식 시간이 초과되었습니다. 다시 시도하세요."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"공급업체별 오류 메시지"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"동기화 설정 읽기"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"앱이 계정의 동기화 설정을 읽을 수 있도록 허용합니다. 예를 들어, 계정에서 주소록 앱을 동기화할지 여부를 확인할 수 있습니다."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"동기화 사용 및 사용 중지 전환"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"애플리케이션이 DRM 인증서를 삭제하도록 허용합니다. 일반 앱에서는 필요하지 않습니다."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"이동통신사 메시지 서비스에 고정"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"보유자가 이동통신사 메시지 서비스의 최상위 인터페이스에 고정할 수 있습니다. 일반 앱에는 필요하지 않습니다."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"화면 잠금 비밀번호와 PIN에 허용되는 길이와 문자 수를 제어합니다."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"앱이 패키지가 설치 가능한지 확인할 수 있도록 허용합니다."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"패키지 인증 연결"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"권한을 가진 프로그램이 패키지 인증을 요청할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"인텐트 필터 인증"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"앱에서 인텐트 필터 인증 여부를 확인하도록 허용합니다."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"인텐트 필터 인증 연결"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"권한을 가진 프로그램이 인텐트 필터 인증을 요청할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"직렬 포트에 액세스"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API를 사용하여 권한을 가진 프로그램이 직렬 포트에 액세스할 수 있도록 합니다."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"외부에서 콘텐츠 제공자에 액세스"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"\'일\'을 줄입니다."</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"\'연도\'를 늘립니다."</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"\'연도\'를 줄입니다."</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"지난달"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"다음 달"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt 키"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"취소"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete 키"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"분 원형 슬라이더"</string>
     <string name="select_hours" msgid="6043079511766008245">"시간 선택"</string>
     <string name="select_minutes" msgid="3974345615920336087">"분 선택"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"월별 바둑판식 날짜 표시"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"년"</string>
     <string name="select_day" msgid="7774759604701773332">"월/일 선택"</string>
     <string name="select_year" msgid="7952052866994196170">"연도 선택"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g>이(가) 선택됨"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> 삭제됨"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"화면 고정을 해제하려면 \'뒤로\'와 \'개요\'를 동시에 길게 터치합니다."</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index fdfc442..7aeba5c 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -192,8 +192,19 @@
     <!-- no translation found for roamingTextSearching (8360141885972279963) -->
     <skip />
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi Чалуу"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <!-- no translation found for cfTemplateNotForwarded (1683685883841272560) -->
     <skip />
     <!-- no translation found for cfTemplateForwarded (1302922117498590521) -->
@@ -749,6 +760,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Колдонмого камера аркылуу видео жана сүрөт тартуу уруксатын берет. Бул уруксат, камераны каалаган убакта, сиздин ырастооңузсуз колдонуу уруксатын берет."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"өткөрүүчүнүн LED индикаторун камера иштеп жатканда өчүрүү"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Камтылган системалык колдонмолорго камеранын LED\'ди колдонуусун өчүрүү мүмкүнчүлүгүн берет."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Алдыртан орнотулган тутум колдонмосуна камера кызматынын тутумдук окуяларын жөнөтүү мүмкүнчүлүгүн берет."</string>
     <!-- no translation found for permlab_brick (2961292205764488304) -->
     <skip />
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"сыналгыны биротоло өчүрүү"</string>
@@ -814,6 +826,10 @@
     <!-- no translation found for permlab_performCdmaProvisioning (5604848095315421425) -->
     <skip />
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Колдонмого CDMA\'ды ишке киргизүү мүмкүнчүлүгүн берет. Кесепеттүү колдонмолор кереги жок CDMA\'ди ишке киргизип башташы мүмкүн."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <!-- no translation found for permlab_locationUpdates (7785408253364335740) -->
     <skip />
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Колдонмого радиодон алынган жайгашкан жердин жаңыртуулары жөнүндө эскертмелерди иштетүү/өчүрүү мүмкүнчүлүгүн берет. Кадимки колдонмолор үчүн эмес."</string>
@@ -948,6 +964,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Колдонмого пайдалануу үчүн манжа изинин үлгүлөрүн кошуу жана жок кылуу мүмкүндүгүн берет."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"манжа изинин аппараттык камсыздоосун колдонуу"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Колдонмого аныктыгын текшерүү үчүн манжа изинин аппараттык камсыздоосун пайдалануу мүмкүндүгүн берет"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Манжа изи жарым-жартылай аныкталды. Кайра аракет кылыңыз."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Манжа изи иштелбей койду. Кайра аракет кылыңыз."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Манжа изинин сенсору кирдеп калган. Тазалап, кайра аракет кылыңыз."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Манжа өтө тез жылдырылды. Кайра аракет кылыңыз."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Манжа өтө жай жылдырылды. Кайра аракет кылыңыз."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Жеткирүүчүгө тиешелүү ээ болуу катасы жөнүндө билдирүү 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Иштетилбей жатат. Кайра аракет кылыңыз."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Аппараттык камсыздоо жеткиликтүү эмес."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Манжа изин сактоо мүмкүн эмес. Учурдагы манжа изин алып салыңыз."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Манжа изин күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Манжа изин күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Жеткирүүчүгө тиешелүү ката жөнүндө билдирүү."</item>
+  </string-array>
     <!-- no translation found for permlab_readSyncSettings (6201810008230503052) -->
     <skip />
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Колдонмого эсеп менен синхрондошуу тууралоолорун окуганга уруксат берет. Мисалы, Кишилер колдонмосу эсеп менен синхрондошкондугун аныктай алат."</string>
@@ -1033,6 +1065,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Колдонмого DRM тастыктамаларын алып салуу мүмкүнчүлүгүн берет. Кадимки колдонмолорго эч качан талап кылынбайт."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"оператордун билдирүү кызматына байланышуу"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Кармоочуга оператордун билдирүү кызматынын жогорку деңгээлдеги интерфейсине байланышуу мүмкүнчүлүгүн берет. Кадимки колдонмолорго эч качан талап кылынбашы мүмкүн."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <!-- no translation found for policylab_limitPassword (4497420728857585791) -->
     <skip />
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Экран кулпусунун сырсөздөрү менен PIN\'дерине уруксат берилген узундук менен белгилерди көзөмөлдөө."</string>
@@ -1446,6 +1482,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Колдонмого топтомдун орнотула тургандыгын текшерүү мүмкүнчүлүгүн берет."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"таңгак текшерүүчүгө байлаштыруу"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Кармоочуга топтом текшергичтеринин атынан өтүнүү мүмкүнчүлүгүн берет. Кадимки колдонмолорго эч качан талап кылынбайт."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"ниет чыпкасын текшерүү"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Колдонмого ниет чыпкасы текшерилген же текшерилбегенин кароо уруксатын берет."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"ниет чыпкасын текшергичке туташуу"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Кармоочуга ниет чыпкасын текшергичтеринин атынан өтүнүү мүмкүнчүлүгүн берет. Кадимки колдонмолорго эч качан талап кылынбайт."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"сериялык портторго жетүү"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Ээсине SerialManager API\'ни колдонуп, серия портуна жеткенге уруксат берүү."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"тышкы контент провайдерлерге жетки алуу"</string>
@@ -2040,6 +2080,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Күндү азайтуу"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Жылды жогорулатуу"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Жылды азайтуу"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Мурунку ай"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Кийинки ай"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Айнуу"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Жок кылуу"</string>
@@ -2309,11 +2351,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Мүнөт жебеси"</string>
     <string name="select_hours" msgid="6043079511766008245">"Саатты тандаңыз"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Мүнөттөрдү тандаңыз"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Айдын күндөрү"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Жыл тизмеги"</string>
     <string name="select_day" msgid="7774759604701773332">"Ай жана күндү тандаңыз"</string>
     <string name="select_year" msgid="7952052866994196170">"Жылды тандаңыз"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> тандалды"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> өчүрүлдү"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Бул экранды бошотуу үчүн Артка жана Көз жүгүртүүнү чогуу басып, кармап туруңуз."</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index e565c00..24fb08d 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"ປິດໂຣມມິງແບນເນີ"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"ຊອກຫາບໍລິການ"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"ການ​ໂທ Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ບໍ່ຖືກສົ່ງຕໍ່"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> ຫຼັງຈາກ <xliff:g id="TIME_DELAY">{2}</xliff:g> ວິນາທີ"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"ອະນຸຍາດໃຫ້ແອັບຯຖ່າຍຮູບ ແລະວິດີໂອດ້ວຍກ້ອງຖ່າຍຮູບ. ການອະນຸຍາດນີ້ຈະອານຸຍາດໃຫ້ແອັບຯ ສາມາດໃຊ້ກ້ອງຖ່າຍຮູບໄດ້ຕະຫລອດເວລາ ໂດຍບໍ່ຕ້ອງຖ້າການຢືນຢັນຈາກທ່ານ."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"ປິດໄຟສັນຍານ LED ເມື່ອນຳໃຊ້ກ້ອງ"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນທີ່ມາກັບໂຕເຄື່ອງ ປິດການນຳໃຊ້ໄຟ LED ໃນກ້ອງຖ່າຍຮູບ."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ລະ​ບົບ​ທີ່​ຕິດ​ຕັ້ງ​ມາ​ກ່ອນ​ສົ່ງ​ເຫດ​ການ​ລະ​ບົບ​ການ​ບໍ​ລິ​ການ​ກ້ອງ​ຖ່າຍ​ຮູບໄດ້."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"ປິດການນຳໃຊ້ແທັບເລັດຖາວອນ"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"ປິດ​ໃຊ້​ງານໂທລະພາບຖາ​ວອນ"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ປິດການເຮັດວຽກຂອງໂທລະສັບຖາວອນ"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"ເລີ່ມ​ຕົ້ນ​ການ​ຕັ້ງ CDMA ໂທລະພາບໂດຍ​ກົງ"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"ເລີ່ມການຕັ້ງຄ່າໂທລະສັບ CDMA ໂດຍກົງ"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"ອະນຸຍາດໃຫ້ແອັບຯເລີ່ມການເຮັດວຽກຂອງ CDMA. ແອັບຯທີ່ເປັນອັນຕະລາຍອາດເລີ່ມການເຮັດວຽກຂອງ CDMA ໂດຍບໍ່ຈຳເປັນ."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"ຄວບຄຸມການແຈ້ງເຕືອນອັບເດດສະຖານທີ່"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"ອະນຸຍາດໃຫ້ແອັບຯ ເປີດ/ປິດ ການເຮັດວຽກຂອງການແຈ້ງເຕືອນອັບເດດສະຖານທີ່ຈາກວິທະຍຸ. ແອັບຯທົ່ວໄປບໍ່ຈຳເປັນຕ້ອງໃຊ້."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"ເຂົ້າເຖິງຄຸນສົມບັດການເຊັກອິນ"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ເຮັດ​ໃຫ້​ວິ​ທີ​ການ​ຕ່າງໆ​ເພີ່ມ ແລະ​ລຶບ​ແມ່​ແບບ​ລາຍ​ນີ້ວ​ມື​ສຳ​ລັບ​ການ​ໃຊ້."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ໃຊ້​ຮາດ​ແວ​ລາຍ​ນີ້ວ​ມື"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ນຳ​ໃຊ້​ຮາດ​ແວ​ລາຍ​ນີ້ວ​ມື​ສຳ​ລັບ​ການ​ຮັບ​ຮອງ"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ກວດ​ພົບ​ລາຍ​ນີ້ວ​ມື​ບາງ​ສ່ວນ​ແລ້ວ. ກະ​ລຸ​ນາ​ລອງ​ໃໝ່​ອີກ."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ບໍ່​ສາ​ມາດ​ດຳ​ເນີນ​ການ​ລາຍ​ນີ້ວ​ມື​ໄດ້. ກະ​ລຸ​ນາ​ລອງ​ໃໝ່​ອີກ."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ເຊັນ​ເຊີ​ລາຍ​ນີ້ວ​ມື​ເປື້ອນ. ກະ​ລຸ​ນາ​ທຳ​ຄວາມ​ສະ​ອາດ ແລະ​ລອງ​ໃໝ່​ອີກ."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"ຍ້າຍ​ນີ້ວ​ມື​ໄປ​ໄວ​ເກີນ​ໄປ. ກະ​ລຸ​ນາ​ລອງ​ໃໝ່​ອີກ."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"ຍ້າຍ​ນີ້ວ​ມື​ໄປ​ຊ້ເກີນ​ໄປ. ກະ​ລຸ​ນາ​ລອງ​ໃໝ່​ອີກ."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"ຂໍ້​ຄວາມ​ການ​ຜິດ​ພາດ​ການ​ໄດ້​ມາ​ສະ​ເພາະ​ຜູ້​ຂາຍ 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"ບໍ່​ສາ​ມາດ​ປະ​ມວນ​ຜົນ​ໄດ້. ລອງ​ໃໝ່​ອີກ."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"ບໍ່​ມີ​ຮາດ​ແວ​ໃຫ້​ຢູ່."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ບໍ່​ສາ​ມາດ​ເກັບ​ຮັກ​ສາ​ລາຍ​ນີ້ວ​ມື​ໄວ້​ໄດ້. ກະ​ລຸ​ນາ​ເອົາ​ລາຍ​ນີ້ວ​ມື​ທີ່​ມີ​ຢູ່​ອອກ​ໄປ."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ເວ​ລາ​ລາຍ​ນີ້ວ​ມື​ບໍ່​ເຂົ້າ​ເຖິງ​ໄດ້. ລອງ​ໃໝ່​ອີກ."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"ເວ​ລາ​ລາຍ​ນີ້ວ​ມື​ບໍ່​ເຂົ້າ​ເຖິງ​ໄດ້. ລອງ​ໃໝ່​ອີກ."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"ຂໍ້​ຄວາມ​ການ​ຂັດ​ຂ້ອງ​ສະ​ເພາະ​ຜູ້​ຂາຍ"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ອ່ານການຕັ້ງຄ່າຊິ້ງຂໍ້ມູນ"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານການຕັ້ງຄ່າການຊິ້ງຂໍ້ມູນຂອງບັນຊີໄດ້. ຕົວຢ່າງເຊັ່ນ: ມັນຈະສາມາດກວດສອບໄດ້ແອັບຯ People ຖືກຊິ້ງຂໍ້ມູນກັບບັນຊີໃດນຶ່ງແລ້ວຫຼືຍັງ."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ສະລັບການເປີດ ແລະປິດການຊິ້ງຂໍ້ມູນ"</string>
@@ -822,6 +854,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພລິ​ເຄ​ຊັນ​ລຶບ​ໃບ​ຮັບ​ຮອງ DRM. ແອັບຯ​ທົ່ວ​ໄປ​ບໍ່​ຄວນ​ຈຳ​ເປັນ​ຕ້ອງ​ໃຊ້."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"ຜູກ​ພັນ​ກັບ​ການ​ບໍ​ລິ​ການ​ສົ່ງ​ຂໍ້​ຄວາມ​ຜູ້​ໃຫ້​ບໍ​ລິ​ການ"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"ອະນຸຍາດໃຫ້ຜູ້ຖືຜູກ​ພັນ​ກັບຕົວ​ປະ​ສານລະດັບສູງສຸດຂອງບໍລິການສົ່ງ​ຂໍ້​ຄວາມ​ຜູ້​ໃຫ້​ບໍ​ລິ​ການ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"ດຳ​ເນີນ​ການ​ກັບ​ການ​ບໍ​ລິ​ການ​ດຳ​ເນີນ​ການ​ທາງ​ສຽງ"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"ອະ​ນຸ​ຍາດ​ໃຫ້​ຜູ້​ຖື​ດຳ​ເນີນ​ການ​ກັບ​ການ​ບໍ​ລິ​ການ​ດຳ​ເນີນ​ການ​ທາງ​ສຽງ​ທີ່​ເປີດ​ຢູ່​ປະ​ຈຸ​ບັນ. ບໍ່​ຈຳ​ເປັນ​ສຳ​ລັບ​ແອັບ​ປົກ​ກະ​ຕິ."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ຕັ້ງຄ່າກົດຂອງລະຫັດຜ່ານ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ຄວບຄຸມຄວາມຍາວ ແລະຕົວອັກສອນທີ່ອະ​ນຸ​ຍາດ​ໃຫ້​ຢູ່​ໃນລະ​ຫັດລັອກໜ້າຈໍ ແລະ PIN."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ຕິດຕາມການພະຍາຍາມປົດລັອກໜ້າຈໍ"</string>
@@ -1119,6 +1153,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"ອະນຸຍາດໃຫ້ແອັບຯຢືນຢັນວ່າແພັກເກດໃດນຶ່ງ ສາມາດຕິດຕັ້ງໄດ້."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"ເຊື່ອມໂຍງກັບໂຕຢືນຢັນແພັກເກດ"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຮັດການຮ້ອງຂໍໂຕຢືນຢັນແພັກເກັດ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"ຢືນ​ຢັນ​ການ​ກັ່ນ​ຕອງ​ຕາມ​ຕັ້ງ"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ກວດ​ເບິ່ງວ່າ ການ​ກັ່ນ​ຕອງ​ຕາມ​ຕັ້ງ​ໃຈ​ໄວ້​ໄດ້​ຮັບ​ການ​ຢືນ​ຢັນ ຫຼື​ບໍ່."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"ຜູກ​ມັດ​ກັບ​ໂຕ​ຢືນ​ຢັນ​ການ​ກັ່ນ​ຕອງ​ຕາມ​ຕັ້ງ​ໃຈ"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຮັດການຮ້ອງຂໍໂຕຢືນຢັນການ​ກັ່ນ​ຕອງ​ຕາມ​ຕັ້ງ​ໃຈ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"ເຂົ້າເຖິງພອດຊີຣຽວ"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສາມາດເຂົ້າເບິ່ງ serial ports ໂດຍການນຳໃຊ້ SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"ເຂົ້າເຖິງຜູ່ສະໜອງເນື້ອຫາພາຍນອກ"</string>
@@ -1544,6 +1582,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ຫຼຸດຈຳນວນມື້"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"ເພີ່ມປີຂຶ້ນ"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ຫຼຸດຈຳນວນປີ"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"​ເດືອນ​ແລ້ວ"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"ເດືອນ​ໜ້າ"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"ຍົກເລີກ"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ລຶບ"</string>
@@ -1794,11 +1834,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"ໂຕໝຸນປັບນາທີ"</string>
     <string name="select_hours" msgid="6043079511766008245">"ເລືອກ​ຊົ່ວ​ໂມງ"</string>
     <string name="select_minutes" msgid="3974345615920336087">"ເລືອກນາ​ທີ"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"ຕາຕາລາງວັນທີເດືອນປີ"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"ລາຍການປີ"</string>
     <string name="select_day" msgid="7774759604701773332">"ເລືອກເດືອນ ແລະ ວັນ"</string>
     <string name="select_year" msgid="7952052866994196170">"ເລືອກ​ປີ"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ຖືກເລືອກແລ້ວ"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ຖືກລຶບແລ້ວ"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"​ບ່ອນ​ເຮັດ​ວຽກ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"ເພື່ອ​ຖອດ​ການ​ປັກ​ໝຸດ​ໜ້າ​ຈໍ​ນີ້, ສຳ​ຜັດປຸ່ມ ​ກັບ​ຄືນ ແລະ ພາບ​ຮວມ ຄ້າງ​ໄວ້​ພ້ອມ​ກັນ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 099593c..7383320 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -126,8 +126,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Tarptinklinio ryšio reklamjuostė išjungta"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Ieškoma paslaugos"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"„Wi-Fi“ skambinimas"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neperadresuota"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sek."</string>
@@ -586,6 +597,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Leidžiama programai fotografuoti ir filmuoti kamera. Šis leidimas suteikia teisę programai naudoti kamerą bet kada be jūsų patvirtinimo."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"neleisti perduoti LED indikatoriaus, kai naudojamas fotoaparatas"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Leidžiama iš anksto įdiegtai sistemos programai išjungti fotoaparato naudojimo indikatoriaus LED."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Iš anksto įdiegtai sistemos programai leidžiama siųsti sistemos įvykius fotoaparato paslaugai."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"visam laikui neleisti planšetinio kompiuterio"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"visam laikui išjungti TV"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"visam laikui išjungti telefoną"</string>
@@ -634,6 +646,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"tiesiogiai pradėti CDMA TV sąranką"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"tiesiogiai pradėti CDMA telefono sąranką"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Leidžiama programai pradėti CDMA parengimą. Kenkėjiškos programos gali be reikalo pradėti CDMA parengimą."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"valdyti vietos atnaujinimo įspėjimus"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Leidžiama programai įgalinti vietos atnaujinimo pranešimus, gautus iš radijo, ar jų neleisti. Neskirta naudoti įprastoms programoms."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"pasiekti registravimo ypatybes"</string>
@@ -748,6 +764,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Leidžiama programai aktyvinti metodus, norint pridėti ir ištrinti naudojamus kontrolinių kodų šablonus."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"naudoti kontrolinio kodo aparatinę įrangą"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Leidžiama programai naudoti kontrolinio kodo aparatinę įrangą tapatybei nustatyti"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Aptiktas dalinis kontrolinis kodas. Bandykite dar kartą."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nepavyko apdoroti kontrolinio kodo. Bandykite dar kartą."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Kontrolinio kodo jutiklis purvinas. Nuvalykite ir bandykite dar kartą."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Per greitai judinate pirštą. Bandykite dar kartą."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Per lėtai judinate pirštą. Bandykite dar kartą."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Konkretaus paslaugų teikėjo įgijimo klaidos pranešimas (0)"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Nepavyko apdoroti. Bandykite dar kartą."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Aparatinė įranga negalima."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Negalima išsaugoti kontrolinio kodo. Pašalinkite esamą kontrolinį kodą."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Baigėsi kontrolinio kodo nustatymo skirtasis laikas. Bandykite dar kartą."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Baigėsi kontrolinio kodo nustatymo skirtasis laikas. Bandykite dar kartą."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Konkretaus paslaugų teikėjo klaidos pranešimas"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"skaityti sinchronizavimo nustatymus"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Leidžiama programai skaityti ir sinchronizuoti paskyros nustatymus. Pvz., taip gali būti nustatoma, ar su paskyra sinchronizuota Žmonių programa."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"įjungti arba išjungti sinchronizavimą"</string>
@@ -824,6 +856,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Programai leidžiama pašalinti DRM sertifikatus. Neturėtų prireikti naudojant įprastas programas."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"susaistyti su operatoriaus susirašinėjimo žinutėmis paslauga"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Leidžiama savininkui susisaistyti su aukščiausio lygio operatoriaus susirašinėjimo žinutėmis paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Valdykite, kokio ilgio ekrano užrakto slaptažodžius ir PIN kodus galima naudoti."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Stebėti bandymus atrakinti ekraną"</string>
@@ -1121,6 +1157,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Leidžiama programai patikrinti, ar paketą galima įdiegti."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"susaistyti su paketo tikrinimo programa"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Savininkui leidžiama teikti užklausas patikrinti paketą. Įprastoms programoms to neturėtų prireikti."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"patvirtinti tikslinį filtrą"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Leidžiama programai patikrinti, ar tikslinis filtras patvirtintas."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"priskirti tikslinio filtro tvirtin. pr."</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Savininkui leidžiama teikti užklausas patvirtinti tikslinį filtrą. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"pasiekti nuosekliuosius prievadus"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Leidžiama savininkui pasiekti nuosekliuosius prievadus naudojant „SerialManager“ API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"pasiekti turinio teikėjus iš išorės"</string>
@@ -1560,6 +1600,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Sumažinti dienų skaičių"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Padidinti metų skaičių"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Sumažinti metų skaičių"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Ankstesnis mėnuo"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Kitas mėnuo"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Atšaukti"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Ištrinti"</string>
@@ -1812,11 +1854,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Apskritas minučių slankiklis"</string>
     <string name="select_hours" msgid="6043079511766008245">"Pasirinkite valandas"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Pasirinkite minutes"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Mėnesio dienų tinklelis"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Metų sąrašas"</string>
     <string name="select_day" msgid="7774759604701773332">"Pasirinkite mėnesį ir dieną"</string>
     <string name="select_year" msgid="7952052866994196170">"Pasirinkite metus"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Pasirinkta: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Ištrinta: <xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Jei norite atsegti šį ekraną, vienu metu palieskite ir palaikykite „Atgal“ ir „Apžvalga“."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 9ab2772..9a14ecc 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -125,8 +125,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Viesabonēšanas reklāmkarogs ir izslēgts."</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Pakalpojuma meklēšana"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi zvani"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nav pāradresēts"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pēc <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundes(-ēm)"</string>
@@ -585,6 +596,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Ļauj lietotnei uzņemt attēlus un videoklipus ar kameru. Ar šo atļauju lietotne var jebkurā brīdī izmantot kameru bez jūsu apstiprinājuma."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"Atspējot pārraidīšanas LED indikatoru, kad kamera tiek izmantota"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Ļauj iepriekš instalētai sistēmas lietojumprogrammai atspējot LED indikatoru, izmantojot kameru."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Ļauj iepriekš instalētai sistēmas lietojumprogrammai nosūtīt sistēmas notikumu datus uz kameras pakalpojumu."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"neatgriezeniski atspējot planšetdatoru"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"neatgriezeniski atspējot televizora darbību"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"neatgriezeniski atspējot tālruni"</string>
@@ -633,6 +645,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"tieši sākt CDMA TV iestatīšanu"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"tiešā veidā sākt CDMA tālruņa iestatīšanu"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Ļauj lietotnei sākt CDMA nodrošināšanu. Ļaunprātīgas lietotnes var sākt CDMA nodrošināšanu bez vajadzības."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"kontrolēt atrašanās vietas atjauninājumu paziņojumus"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Ļauj lietotnei iespējot/atspējot paziņojumus no radio saistībā ar atrašanās vietas atjauninājumiem. Atļauja neattiecas uz parastām lietotnēm."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"piekļūt reģistrēšanās rekvizītiem"</string>
@@ -747,6 +763,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Atļauj lietotnei izsaukt metodes izmantojamo pirkstu nospiedumu veidņu pievienošanai un dzēšanai."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"lietot pirkstu nospiedumu aparatūru"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Atļauj lietotnei izmantot pirkstu nospiedumu aparatūru autentificēšanai."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Noteikts daļējs pirksta nospiedums. Lūdzu, mēģiniet vēlreiz."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nevarēja apstrādāt pirksta nospiedumu. Lūdzu, mēģiniet vēlreiz."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Pirkstu nospiedumu sensors ir netīrs. Lūdzu, notīriet to un mēģiniet vēlreiz."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Pārāk ātra pirksta kustība. Lūdzu, mēģiniet vēlreiz."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Pārāk lēna pirksta kustība. Lūdzu, mēģiniet vēlreiz."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Piegādātāja noteikts iegūšanas kļūdas ziņojums 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Nevar apstrādāt pirksta nospiedumu. Mēģiniet vēlreiz."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Aparatūra nav pieejama."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Pirkstu nospiedumu nevar saglabāt. Lūdzu, noņemiet esošu pirksta nospiedumu."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Pirkstu nospiedumu nolasīšanas aparatūras noildze. Mēģiniet vēlreiz."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Pirkstu nospiedumu nolasīšanas aparatūras noildze. Mēģiniet vēlreiz."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Piegādātāja noteikts kļūdas ziņojums"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lasīt sinhronizācijas iestatījumus"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Ļauj lietotnei lasīt konta sinhronizācijas iestatījumus. Piemēram, šādi var noteikt, vai lietotne Personas ir sinhronizēta ar kontu."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ieslēgt un izslēgt sinhronizāciju"</string>
@@ -823,6 +855,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Ļauj lietojumprogrammai noņemt DRM sertifikātus. Parastās lietotnēs tas nebūs nepieciešams."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"Savienojuma izveide ar mobilo sakaru operatora ziņojumapmaiņas pakalpojumu"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Ļauj īpašniekam izveidot savienojumu ar mobilo sakaru operatora ziņojumapmaiņas pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolēt ekrāna bloķēšanas paroļu un PIN garumu un tajos atļautās rakstzīmes."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
@@ -1120,6 +1156,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Ļauj lietotnei verificēt, vai pakotne ir instalējama."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"saistīšana ar pakotnes verificētāju"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Ļauj īpašniekam sūtīt pakotņu verificētāju pieprasījumus. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verificēt mērķa filtru"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Ļauj lietotnei pārbaudīt, vai mērķa filtrs ir verificēts."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"saistīt ar mērķa filtra verificētāju"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Ļauj īpašniekam sūtīt mērķa filtra verificētāju pieprasījumus. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"piekļuve seriālajiem portiem"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Ļauj īpašniekam piekļūt seriālajiem portiem, izmantojot SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"ārēji piekļūt satura nodrošinātājiem"</string>
@@ -1552,6 +1592,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Norādīt agrāku dienu"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Norādīt vēlāku gadu"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Norādīt agrāku gadu"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Iepriekšējais mēnesis"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Nākamais mēnesis"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alternēšanas taustiņš"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Atcelt"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Dzēšanas taustiņš"</string>
@@ -1803,11 +1845,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Minūšu apļveida slīdnis"</string>
     <string name="select_hours" msgid="6043079511766008245">"Atlasiet stundas."</string>
     <string name="select_minutes" msgid="3974345615920336087">"Atlasiet minūtes."</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Režģis ar mēneša dienām"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Gadu saraksts"</string>
     <string name="select_day" msgid="7774759604701773332">"Atlasiet mēnesi un dienu."</string>
     <string name="select_year" msgid="7952052866994196170">"Atlasiet gadu."</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Atlasīts: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> tika dzēsts."</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbā: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Lai atspraustu šo ekrānu, vienlaicīgi pieskarieties pogām “Atpakaļ” un “Pārskats” un turiet tās."</string>
diff --git a/core/res/res/values-mcc310-mnc260-af/strings.xml b/core/res/res/values-mcc310-mnc260-af/strings.xml
index e33c27b..5187a0d 100644
--- a/core/res/res/values-mcc310-mnc260-af/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-af/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi-oproepe is nie beskikbaar nie. Kontak jou diensverskaffer om Wi-Fi-oproepe te aktiveer."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi-oproep"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-am/strings.xml b/core/res/res/values-mcc310-mnc260-am/strings.xml
index 24a88097..fcfedb1 100644
--- a/core/res/res/values-mcc310-mnc260-am/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-am/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi ጥሪ ማድረጊያ አይገኝም። የ Wi-Fi ጥሪ ማድረጊያን ለማንቃት የእርስዎን አገልግሎት አቅራቢ ያነጋግሩ።"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"የ%s Wi-Fi ጥሪ"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ar/strings.xml b/core/res/res/values-mcc310-mnc260-ar/strings.xml
index 8c2e6f6..0fa7d37 100644
--- a/core/res/res/values-mcc310-mnc260-ar/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ar/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"‏الاتصال عبر Wi-Fi ليس متوفرًا. اتصل بمشغل شبكة الجوّال لتمكين الاتصال عبر Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"‏%s جارٍ الاتصال عبر Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-bg/strings.xml b/core/res/res/values-mcc310-mnc260-bg/strings.xml
index 86ad9ab..1207b2b 100644
--- a/core/res/res/values-mcc310-mnc260-bg/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-bg/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Обажданията през Wi-Fi не са налице. Свържете се с оператора си, за да ги активирате."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s – обаждания през Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-bn-rBD/strings.xml b/core/res/res/values-mcc310-mnc260-bn-rBD/strings.xml
index 97df2db..c11e704 100644
--- a/core/res/res/values-mcc310-mnc260-bn-rBD/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-bn-rBD/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi কলিং উপলব্ধ নেই৷ Wi-Fi কলিং সক্ষম করতে আপনার পরিষেবা প্রদানকারীর সাথে যোগাযোগ করুন৷"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi কলিং"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ca/strings.xml b/core/res/res/values-mcc310-mnc260-ca/strings.xml
index e7d2158..a0ca207 100644
--- a/core/res/res/values-mcc310-mnc260-ca/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ca/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Les trucades per Wi-Fi no estan disponibles. Contacta amb l\'operador de telefonia mòbil per activar-les."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Trucada de Wi-Fi de: %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-cs/strings.xml b/core/res/res/values-mcc310-mnc260-cs/strings.xml
index 987284d..dcd7125 100644
--- a/core/res/res/values-mcc310-mnc260-cs/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-cs/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Volání přes Wi-Fi není k dispozici. Kontaktujte operátora, aby volání přes Wi-Fi aktivoval."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Volání přes Wi-Fi: %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-da/strings.xml b/core/res/res/values-mcc310-mnc260-da/strings.xml
index 20532b2..5c23bb4 100644
--- a/core/res/res/values-mcc310-mnc260-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-da/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Opkald via Wi-Fi er ikke muligt. Kontakt dit mobilselskab for at aktivere Opkald via Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi-opkald"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-de/strings.xml b/core/res/res/values-mcc310-mnc260-de/strings.xml
index e69d062..5a9f9c6 100644
--- a/core/res/res/values-mcc310-mnc260-de/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-de/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"WLAN-Anrufe sind nicht möglich. Bitte kontaktieren Sie Ihren Mobilfunkanbieter bezüglich der Aktivierung der WLAN-Telefonie."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s WLAN-Anrufe"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-el/strings.xml b/core/res/res/values-mcc310-mnc260-el/strings.xml
index cd5d615..55bcda6 100644
--- a/core/res/res/values-mcc310-mnc260-el/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-el/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Η κλήση Wi-Fi δεν είναι διαθέσιμη. Επικοινωνήστε με την εταιρεία κινητής τηλεφωνίας σας για να ενεργοποιήσετε την κλήση Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Κλήση Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-en-rAU/strings.xml b/core/res/res/values-mcc310-mnc260-en-rAU/strings.xml
index 3f764c0..1d300ea 100644
--- a/core/res/res/values-mcc310-mnc260-en-rAU/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-en-rAU/strings.xml
@@ -22,7 +22,11 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi Calling isn\'t available. Contact your operator to enable Wi-Fi Calling."</item>
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="7239039348648848288">"To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings."</item>
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="483847327467331298">"Register with your operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi Calling"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-en-rGB/strings.xml b/core/res/res/values-mcc310-mnc260-en-rGB/strings.xml
index 3f764c0..1d300ea 100644
--- a/core/res/res/values-mcc310-mnc260-en-rGB/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-en-rGB/strings.xml
@@ -22,7 +22,11 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi Calling isn\'t available. Contact your operator to enable Wi-Fi Calling."</item>
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="7239039348648848288">"To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings."</item>
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="483847327467331298">"Register with your operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi Calling"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-en-rIN/strings.xml b/core/res/res/values-mcc310-mnc260-en-rIN/strings.xml
index 3f764c0..1d300ea 100644
--- a/core/res/res/values-mcc310-mnc260-en-rIN/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-en-rIN/strings.xml
@@ -22,7 +22,11 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi Calling isn\'t available. Contact your operator to enable Wi-Fi Calling."</item>
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="7239039348648848288">"To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings."</item>
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="483847327467331298">"Register with your operator"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi Calling"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-es-rUS/strings.xml b/core/res/res/values-mcc310-mnc260-es-rUS/strings.xml
index 3e13ebb..940ee00 100644
--- a/core/res/res/values-mcc310-mnc260-es-rUS/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-es-rUS/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Las llamadas con Wi-Fi no están disponibles. Comunícate con el proveedor para habilitar la función."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Llamada por Wi-Fi de %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-es/strings.xml b/core/res/res/values-mcc310-mnc260-es/strings.xml
index 9dea2f1..2bdb4a3 100644
--- a/core/res/res/values-mcc310-mnc260-es/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-es/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Las llamadas Wi-Fi no están disponibles. Ponte en contacto con tu operador para habilitarlas."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Llamada Wi-Fi de %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-et-rEE/strings.xml b/core/res/res/values-mcc310-mnc260-et-rEE/strings.xml
index 465507a..e703dcc 100644
--- a/core/res/res/values-mcc310-mnc260-et-rEE/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-et-rEE/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"WiFi-kõned pole saadaval. WiFi-kõnede lubamiseks võtke ühendust operaatoriga."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s WiFi kaudu helistamine"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-eu-rES/strings.xml b/core/res/res/values-mcc310-mnc260-eu-rES/strings.xml
index 23194ff..7edda7d 100644
--- a/core/res/res/values-mcc310-mnc260-eu-rES/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-eu-rES/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi bidezko deiak ez daude erabilgarri. Gaitzeko, jarri operadorearekin harremanetan."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi bidezko deiak"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-fa/strings.xml b/core/res/res/values-mcc310-mnc260-fa/strings.xml
index 083a613..3ed1442 100644
--- a/core/res/res/values-mcc310-mnc260-fa/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-fa/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"‏تماس از طریق Wi-Fi امکان‌پذیر نیست. برای فعال کردن تماس Wi-Fi، با شرکت مخابراتی‌تان تماس بگیرید."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"‏تماس ‪%s Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-fi/strings.xml b/core/res/res/values-mcc310-mnc260-fi/strings.xml
index 43efe46..e3b768a 100644
--- a/core/res/res/values-mcc310-mnc260-fi/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-fi/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi-puhelut eivät ole käytettävissä. Pyydä operaattoriasi ottamaan Wi-Fi-puhelut käyttöön."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Wi-Fi-puhelut: %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-fr-rCA/strings.xml b/core/res/res/values-mcc310-mnc260-fr-rCA/strings.xml
index 2d63c89..b4f0636 100644
--- a/core/res/res/values-mcc310-mnc260-fr-rCA/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-fr-rCA/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"La fonction d\'appel par Wi-Fi n\'est pas disponible. Communiquez avec votre fournisseur de services pour activer les appels par Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Appels Wi-Fi %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-fr/strings.xml b/core/res/res/values-mcc310-mnc260-fr/strings.xml
index 358bec8..b4f0636 100644
--- a/core/res/res/values-mcc310-mnc260-fr/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-fr/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Les appels Wi-Fi ne sont pas disponibles. Contactez votre opérateur pour les activer."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Appels Wi-Fi %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-gl-rES/strings.xml b/core/res/res/values-mcc310-mnc260-gl-rES/strings.xml
index 32ef3d3..4502d6d 100644
--- a/core/res/res/values-mcc310-mnc260-gl-rES/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-gl-rES/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"As chamadas por wifi non están dispoñible. Contacta co teu operador para activar as chamadas por wifi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Chamadas wifi de %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-hi/strings.xml b/core/res/res/values-mcc310-mnc260-hi/strings.xml
index 93193fd..3469e90 100644
--- a/core/res/res/values-mcc310-mnc260-hi/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-hi/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi कॉलिंग उपलब्‍ध नहीं है. वाई-फ़ाई कॉलिंग सक्षम करने के लिए अपने वाहक से संपर्क करें."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s वाई-फ़ाई कॉलिंग"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-hr/strings.xml b/core/res/res/values-mcc310-mnc260-hr/strings.xml
index 30e22f1..ffd3aa0 100644
--- a/core/res/res/values-mcc310-mnc260-hr/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-hr/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi pozivi nisu dostupni. Obratite se mobilnom operateru radi omogućivanja Wi-Fi poziva."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi pozivanje"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-hu/strings.xml b/core/res/res/values-mcc310-mnc260-hu/strings.xml
index 44b0a9e..62a4f8c 100644
--- a/core/res/res/values-mcc310-mnc260-hu/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-hu/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"A Wi-Fi-hívás nem érhető el. Engedélyezéséhez forduljon szolgáltatójához."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi-hívás"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-hy-rAM/strings.xml b/core/res/res/values-mcc310-mnc260-hy-rAM/strings.xml
index aa63f70..c5534de 100644
--- a/core/res/res/values-mcc310-mnc260-hy-rAM/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-hy-rAM/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi-ի միջոցով զանգերն անհասանելի են: Դրանք միացնելու համար դիմեք ձեր օպերատորին:"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi զանգեր"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-in/strings.xml b/core/res/res/values-mcc310-mnc260-in/strings.xml
index 669d384..6c028fb 100644
--- a/core/res/res/values-mcc310-mnc260-in/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-in/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Panggilan Wi-Fi tidak tersedia. Hubungi operator untuk mengaktifkan Panggilan Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Panggilan Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-is-rIS/strings.xml b/core/res/res/values-mcc310-mnc260-is-rIS/strings.xml
index 2549756..0b96668 100644
--- a/core/res/res/values-mcc310-mnc260-is-rIS/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-is-rIS/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi símtöl eru ekki í boði. Hafðu samband við símafyrirtækið þitt til að virkja Wi-Fi símtöl."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi símtöl"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-it/strings.xml b/core/res/res/values-mcc310-mnc260-it/strings.xml
index 7f58424..258bd35 100644
--- a/core/res/res/values-mcc310-mnc260-it/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-it/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Le chiamate Wi-Fi non sono disponibili. Contatta il tuo operatore per attivarle."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Chiamata Wi-Fi %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-iw/strings.xml b/core/res/res/values-mcc310-mnc260-iw/strings.xml
index 161c868..abfeb48 100644
--- a/core/res/res/values-mcc310-mnc260-iw/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-iw/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"‏שיחות ב-Wi-Fi אינן זמינות. צור קשר עם הספק שלך כדי להפעיל שיחות ב-Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"‏שיחות Wi-Fi של %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ja/strings.xml b/core/res/res/values-mcc310-mnc260-ja/strings.xml
index 237b606..a5ae2f8 100644
--- a/core/res/res/values-mcc310-mnc260-ja/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ja/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi通話が利用できません。携帯通信会社に連絡してWi-Fi通話を有効にしてください。"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Wi-Fi通話(%s)"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ka-rGE/strings.xml b/core/res/res/values-mcc310-mnc260-ka-rGE/strings.xml
index 53488dd..ca748da 100644
--- a/core/res/res/values-mcc310-mnc260-ka-rGE/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ka-rGE/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"დარეკვა Wi-Fi-ს მეშვეობით მიუწვდომელია. დაუკავშირდით თქვენს ოპერატორს Wi-Fi-ს მეშვეობით დარეკვის ჩასართავად."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s დარეკვა Wi-Fi-ს მეშვეობით"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-kk-rKZ/strings.xml b/core/res/res/values-mcc310-mnc260-kk-rKZ/strings.xml
index 10ce253..1dee61e 100644
--- a/core/res/res/values-mcc310-mnc260-kk-rKZ/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-kk-rKZ/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi қоңырауы қол жетімді емес. Wi-Fi қоңырауы қосу үшін жабдықтаушыға хабарласыңыз."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi арқылы қоңырау шалу"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-km-rKH/strings.xml b/core/res/res/values-mcc310-mnc260-km-rKH/strings.xml
index 7f62ff6..8682bd6 100644
--- a/core/res/res/values-mcc310-mnc260-km-rKH/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-km-rKH/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"ការហៅតាម Wi-Fi មិនមាននោះទេ។ សូមទាក់ទងទៅអ្នកផ្តល់សេវាកម្មទូរស័ព្ទរបស់អ្នកដើម្បីបើកដំណើរការហៅតាម Wi-Fi។"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"ការហៅតាមរយៈ Wi-Fi %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-kn-rIN/strings.xml b/core/res/res/values-mcc310-mnc260-kn-rIN/strings.xml
index 4977708..cece7e0 100644
--- a/core/res/res/values-mcc310-mnc260-kn-rIN/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-kn-rIN/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"ವೈ-ಫೈ ಕರೆ ಮಾಡುವಿಕೆ ಲಭ್ಯವಿಲ್ಲ. ವೈ-ಫೈ ಕರೆ ಮಾಡುವಿಕೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ನಿಮ್ಮ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಿ."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s ವೈ-ಫೈ ಕರೆ ಮಾಡುವಿಕೆ"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ko/strings.xml b/core/res/res/values-mcc310-mnc260-ko/strings.xml
index 0dcc45a..0032b35 100644
--- a/core/res/res/values-mcc310-mnc260-ko/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ko/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi 통화를 사용할 수 없습니다. Wi-Fi 통화를 사용하려면 이동통신사에 문의하세요."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi 통화"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ky-rKG/strings.xml b/core/res/res/values-mcc310-mnc260-ky-rKG/strings.xml
index b8f1e5a..24079bc 100644
--- a/core/res/res/values-mcc310-mnc260-ky-rKG/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ky-rKG/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi Чалуу жеткиликтүү эмес. Wi-Fi Чалууну иштетүү үчүн операторуңузга кайрылыңыз."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi Чалуу"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-lo-rLA/strings.xml b/core/res/res/values-mcc310-mnc260-lo-rLA/strings.xml
index 8f826e4..bb27849 100644
--- a/core/res/res/values-mcc310-mnc260-lo-rLA/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-lo-rLA/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"ການໂທ Wi-Fi ບໍ່ພ້ອມໃຊ້ງານ. ໃຫ້ຕິດຕໍ່ຫາຜູ້ໃຫ້ບໍລິການຂອງທ່ານເພື່ອເປີດໃຊ້ການໂທ Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"ການ​ໂທ %s Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-lt/strings.xml b/core/res/res/values-mcc310-mnc260-lt/strings.xml
index b4a0dbb..1aff275 100644
--- a/core/res/res/values-mcc310-mnc260-lt/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-lt/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"„Wi-Fi“ skambinimo funkcija nepasiekiama. Susisiekite su operatoriumi, kad įgalintumėte „Wi-Fi“ skambinimo funkciją."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"„%s“ „Wi-Fi“ skambinimas"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-lv/strings.xml b/core/res/res/values-mcc310-mnc260-lv/strings.xml
index 19fafeb..7abedd2 100644
--- a/core/res/res/values-mcc310-mnc260-lv/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-lv/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi zvani nav pieejami. Lai iespējotu Wi-Fi zvanus, sazinieties ar savu mobilo sakaru operatoru."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi zvani"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-mk-rMK/strings.xml b/core/res/res/values-mcc310-mnc260-mk-rMK/strings.xml
index a4125b4..f342da4 100644
--- a/core/res/res/values-mcc310-mnc260-mk-rMK/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-mk-rMK/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Повикувањето преку Wi-Fi не е достапно. Контактирајте го операторот за да овозможите Повикување преку Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Повикување преку Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ml-rIN/strings.xml b/core/res/res/values-mcc310-mnc260-ml-rIN/strings.xml
index 732e18b..923d6a3 100644
--- a/core/res/res/values-mcc310-mnc260-ml-rIN/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ml-rIN/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi കോളിംഗ് ലഭ്യമല്ല. Wi-Fi കോളിംഗ് പ്രവർത്തനക്ഷമമാക്കാൻ നിങ്ങളുടെ കാരിയറെ ബന്ധപ്പെടുക."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi കോളിംഗ്"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-mn-rMN/strings.xml b/core/res/res/values-mcc310-mnc260-mn-rMN/strings.xml
index 8b311ee..f0d294e 100644
--- a/core/res/res/values-mcc310-mnc260-mn-rMN/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-mn-rMN/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi Calling одоогоор боломжгүй байна. Wi-Fi Calling  идэвхжүүлэхийн тулд оператортойгоо холбогдоно уу."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi Дуудлага"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-mr-rIN/strings.xml b/core/res/res/values-mcc310-mnc260-mr-rIN/strings.xml
index e191a68..063e56e 100644
--- a/core/res/res/values-mcc310-mnc260-mr-rIN/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-mr-rIN/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"वाय-फाय कॉलिंग उपलब्‍ध नाही. वाय-फाय कॉलिंग सक्षम करण्‍यासाठी आपल्‍या वाहकाशी संपर्क साधा."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s वाय-फाय कॉलिंग"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ms-rMY/strings.xml b/core/res/res/values-mcc310-mnc260-ms-rMY/strings.xml
index aa13114..6c028fb 100644
--- a/core/res/res/values-mcc310-mnc260-ms-rMY/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ms-rMY/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Panggilan Wi-Fi tidak tersedia. Hubungi pembawa anda untuk mendayakan Panggilan Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Panggilan Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-my-rMM/strings.xml b/core/res/res/values-mcc310-mnc260-my-rMM/strings.xml
index 90e99af..b1a7932 100644
--- a/core/res/res/values-mcc310-mnc260-my-rMM/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-my-rMM/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"ဝိုင်ဖိုင်ခေါ်ဆိုမှု မရပါ။ ဝိုင်ဖိုင် ခေါ်နိုင်ရန် သင်၏ ဖုန်းဝန်ဆောင်မှုပေးသူအား ဆက်သွယ်ပါ။"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s ဝိုင်ဖိုင် ခေါ်ဆိုမှု"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-nb/strings.xml b/core/res/res/values-mcc310-mnc260-nb/strings.xml
index 7ece702..ee5688d 100644
--- a/core/res/res/values-mcc310-mnc260-nb/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-nb/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi-anrop er ikke tilgjengelig. Ta kontakt med operatøren din for å slå på Wi-Fi-anrop."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi-anrop"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ne-rNP/strings.xml b/core/res/res/values-mcc310-mnc260-ne-rNP/strings.xml
index 72f94f3..2bef35f 100644
--- a/core/res/res/values-mcc310-mnc260-ne-rNP/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ne-rNP/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi कलिङ उपलब्ध छैन। Wi-Fi कलिङ सक्षम पार्न तपाईँको वाहकलाई सम्पर्क गर्नुहोस्।"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi कलिङ"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-nl/strings.xml b/core/res/res/values-mcc310-mnc260-nl/strings.xml
index 1fbe404..6509ffb 100644
--- a/core/res/res/values-mcc310-mnc260-nl/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-nl/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Bellen via wifi is niet beschikbaar. Neem contact op met uw provider om bellen via wifi in te schakelen."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Bellen via wifi van %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-pl/strings.xml b/core/res/res/values-mcc310-mnc260-pl/strings.xml
index 41bb1e6..5c047f6 100644
--- a/core/res/res/values-mcc310-mnc260-pl/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-pl/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Połączenia przez Wi-Fi są niedostępne. Skontaktuj się z operatorem sieci, by je włączyć."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Połączenia przez Wi-Fi (%s)"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc260-pt-rPT/strings.xml
index bb22d9e..140b8d1 100644
--- a/core/res/res/values-mcc310-mnc260-pt-rPT/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-pt-rPT/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"As chamadas Wi-Fi não estão disponíveis. Contacte o seu operador para as ativar."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Chamadas por Wi-Fi da %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-pt/strings.xml b/core/res/res/values-mcc310-mnc260-pt/strings.xml
index d422e83..f6bf383 100644
--- a/core/res/res/values-mcc310-mnc260-pt/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-pt/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"A chamada por Wi-Fi não está disponível. Entre em contato com sua operadora para ativá-la."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s chamada Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ro/strings.xml b/core/res/res/values-mcc310-mnc260-ro/strings.xml
index 422280f..b547cd3 100644
--- a/core/res/res/values-mcc310-mnc260-ro/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ro/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Apelarea prin Wi-Fi nu este disponibilă. Contactați-vă operatorul pentru a activa Apelarea prin Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Apelare prin Wi-Fi %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ru/strings.xml b/core/res/res/values-mcc310-mnc260-ru/strings.xml
index eeceb7c..29ac79c 100644
--- a/core/res/res/values-mcc310-mnc260-ru/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ru/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Звонки по Wi-Fi недоступны. Чтобы включить эту функцию, свяжитесь со своим оператором."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Звонки по Wi-Fi (%s)"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-si-rLK/strings.xml b/core/res/res/values-mcc310-mnc260-si-rLK/strings.xml
index dd4da30..b089681 100644
--- a/core/res/res/values-mcc310-mnc260-si-rLK/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-si-rLK/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi ඇමතීම ලබාගත නොහැක. Wi-Fi ඇමතීම ක්‍රියාත්මක කිරීමට ඔබගේ වාහකයා සම්බන්ධ කරගන්න."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi අමතමින්"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-sk/strings.xml b/core/res/res/values-mcc310-mnc260-sk/strings.xml
index 527388f..eb8b5f8 100644
--- a/core/res/res/values-mcc310-mnc260-sk/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-sk/strings.xml
@@ -22,7 +22,11 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Volanie cez Wi-Fi nie je k dispozícii. Kontaktujte svojho operátora a požiadajte ho o povolenie volania cez Wi-Fi."</item>
+  <string-array name="wfcOperatorErrorAlertMessages">
+    <item msgid="7239039348648848288">"Ak chcete volať a odosielať správy prostredníctvom siete Wi-Fi, kontaktujte najskôr svojho operátora v súvislosti s nastavením tejto služby. Potom opäť zapnite v Nastaveniach volanie cez Wi-Fi."</item>
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+    <item msgid="483847327467331298">"Registrujte sa so svojím operátorom"</item>
+  </string-array>
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Volanie siete Wi-Fi %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-sl/strings.xml b/core/res/res/values-mcc310-mnc260-sl/strings.xml
index 2dc873b..e18d778 100644
--- a/core/res/res/values-mcc310-mnc260-sl/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-sl/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Klicanje prek Wi-Fi-ja ni na voljo. Obrnite se na operaterja, da vam omogoči klicanje prek Wi-Fi-ja."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Klicanje prek Wi-Fi-ja (%s)"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-sr/strings.xml b/core/res/res/values-mcc310-mnc260-sr/strings.xml
index 76f8aef..6fb8e20 100644
--- a/core/res/res/values-mcc310-mnc260-sr/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-sr/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Позивање преко Wi-Fi-ја није доступно. Контактирајте мобилног оператера да бисте омогућили позивање преко Wi-Fi-ја."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Wi-Fi позивање преко оператера %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-sv/strings.xml b/core/res/res/values-mcc310-mnc260-sv/strings.xml
index 8e0d159..c3157dc 100644
--- a/core/res/res/values-mcc310-mnc260-sv/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-sv/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Det går inte att ringa Wi-Fi-samtal. Kontakta operatören om du vill aktivera Wi-Fi-samtal."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi-samtal"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-sw/strings.xml b/core/res/res/values-mcc310-mnc260-sw/strings.xml
index ff9bf3f..ab47852 100644
--- a/core/res/res/values-mcc310-mnc260-sw/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-sw/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Huduma ya Upigaji simu kwa Wi-Fi haipatikani. Wasiliana na mtoa huduma wako ili awashe Upigaji simu kwa Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Upigaji Simu kwa Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ta-rIN/strings.xml b/core/res/res/values-mcc310-mnc260-ta-rIN/strings.xml
index d8b3130..2f15eaa 100644
--- a/core/res/res/values-mcc310-mnc260-ta-rIN/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ta-rIN/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"வைஃபை அழைப்பு கிடைக்கவில்லை. வைஃபை அழைப்பை இயக்க, மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளவும்."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s வைஃபை அழைப்பு"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-te-rIN/strings.xml b/core/res/res/values-mcc310-mnc260-te-rIN/strings.xml
index ffbab18..20dd91a 100644
--- a/core/res/res/values-mcc310-mnc260-te-rIN/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-te-rIN/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi కాలింగ్ అందుబాటులో లేదు. Wi-Fi కాలింగ్‌ను ప్రారంభించడానికి మీ క్యారియర్‌ను సంప్రదించండి."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi కాలింగ్"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-th/strings.xml b/core/res/res/values-mcc310-mnc260-th/strings.xml
index 52dc04f..4525a80 100644
--- a/core/res/res/values-mcc310-mnc260-th/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-th/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"การโทรผ่าน Wi-Fi ไม่พร้อมใช้งาน โปรดติดต่อผู้ให้บริการของคุณเพื่อเปิดใช้การโทรผ่าน Wi-Fi"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"กำลังเรียก Wi-Fi ของ %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-tl/strings.xml b/core/res/res/values-mcc310-mnc260-tl/strings.xml
index 52d97a8..29cb0a8 100644
--- a/core/res/res/values-mcc310-mnc260-tl/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-tl/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Hindi available ang Pagtawag sa pamamagitan ng Wi-Fi. Makipag-ugnayan sa iyong carrier upang i-enable ang Pagtawag sa pamamagitan ng Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Pagtawag sa Pamamagitan ng Wi-Fi ng %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-tr/strings.xml b/core/res/res/values-mcc310-mnc260-tr/strings.xml
index b28702b82..6c91869 100644
--- a/core/res/res/values-mcc310-mnc260-tr/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-tr/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Kablosuz Çağrı kullanılamıyor. Kablosuz Çağrı özelliğini etkinleştirmek için operatörünüzle iletişim kurun."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Kablosuz Çağrı"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-uk/strings.xml b/core/res/res/values-mcc310-mnc260-uk/strings.xml
index 243c7b0..72b556a 100644
--- a/core/res/res/values-mcc310-mnc260-uk/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-uk/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Ви не можете телефонувати через Wi-Fi. Щоб увімкнути цю функцію, зв’яжіться з оператором."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Дзвінок через Wi-Fi від оператора %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-ur-rPK/strings.xml b/core/res/res/values-mcc310-mnc260-ur-rPK/strings.xml
index 77ee52b..4c81ffd 100644
--- a/core/res/res/values-mcc310-mnc260-ur-rPK/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-ur-rPK/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"‏Wi-Fi کالنگ دستیاب نہیں ہے۔ Wi-Fi کالنگ فعال کرنے کیلئے اپنے کیریئر سے رابطہ کریں۔"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"‏‎%s Wi-Fi کالنگ"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-uz-rUZ/strings.xml b/core/res/res/values-mcc310-mnc260-uz-rUZ/strings.xml
index 1cd4795..4e1c98b 100644
--- a/core/res/res/values-mcc310-mnc260-uz-rUZ/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-uz-rUZ/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Wi-Fi qo‘ng‘iroq mavjud emas. Wi-Fi qo‘ng‘iroqni yoqish uchun tarmoq operatori bilan bog‘laning."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi qo‘ng‘iroqlar"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-vi/strings.xml b/core/res/res/values-mcc310-mnc260-vi/strings.xml
index d47da6d..5ffcd26 100644
--- a/core/res/res/values-mcc310-mnc260-vi/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-vi/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Tính năng Gọi qua Wi-Fi không khả dụng. Hãy liên hệ với nhà cung cấp dịch vụ để bật tính năng Gọi qua Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"Gọi điện qua Wi-Fi %s"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-zh-rCN/strings.xml b/core/res/res/values-mcc310-mnc260-zh-rCN/strings.xml
index 561484e..c50bdef 100644
--- a/core/res/res/values-mcc310-mnc260-zh-rCN/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-zh-rCN/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"WLAN 通话功能不可用。请与您的运营商联系,以便启用 WLAN 通话功能。"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s WLAN 通话功能"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-zh-rHK/strings.xml b/core/res/res/values-mcc310-mnc260-zh-rHK/strings.xml
index d93be6d..bde0baa 100644
--- a/core/res/res/values-mcc310-mnc260-zh-rHK/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-zh-rHK/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"無法使用 Wi-Fi 通話。請聯絡您的流動網絡供應商,以啟用 Wi-Fi 通話。"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi 通話"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-zh-rTW/strings.xml b/core/res/res/values-mcc310-mnc260-zh-rTW/strings.xml
index 3acfb84..bde0baa 100644
--- a/core/res/res/values-mcc310-mnc260-zh-rTW/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-zh-rTW/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"無法使用 Wi-Fi 通話功能。請與您的行動通訊業者聯絡,為您啟用 Wi-Fi 通話功能。"</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s Wi-Fi 通話"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260-zu/strings.xml b/core/res/res/values-mcc310-mnc260-zu/strings.xml
index a037bb8..8cd89a5 100644
--- a/core/res/res/values-mcc310-mnc260-zu/strings.xml
+++ b/core/res/res/values-mcc310-mnc260-zu/strings.xml
@@ -22,7 +22,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="wfcOperatorErrorMessages">
-    <item msgid="931634632269046788">"Ukushaya kwe-Wi-Fi akutholakali. Xhumana nenkampani yakho yenethiwekhi ukuze unike amandla ukushaya kwe-Wi-Fi."</item>
-  </string-array>
+    <!-- no translation found for wfcOperatorErrorAlertMessages:0 (7239039348648848288) -->
+    <!-- no translation found for wfcOperatorErrorNotificationMessages:0 (483847327467331298) -->
+    <string name="wfcSpnFormat" msgid="4982938551498609442">"%s ukushaya kwe-Wi-Fi"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260/strings.xml b/core/res/res/values-mcc310-mnc260/strings.xml
index 5cadc2a..dc79877 100644
--- a/core/res/res/values-mcc310-mnc260/strings.xml
+++ b/core/res/res/values-mcc310-mnc260/strings.xml
@@ -25,8 +25,14 @@
     <string-array name="wfcOperatorErrorCodes" translatable="false">
         <item>REG09</item>
     </string-array>
-    <!-- WFC Operator Error Messages -->
-    <string-array name="wfcOperatorErrorMessages">
-        <item>Wi-Fi Calling isn\&apos;t available. Contact your carrier to enable Wi-Fi Calling.</item>
+    <!-- WFC Operator Error Messages showed as alerts -->
+    <string-array name="wfcOperatorErrorAlertMessages">
+        <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
     </string-array>
+    <!-- WFC Operator Error Messages showed as notifications -->
+    <string-array name="wfcOperatorErrorNotificationMessages">
+        <item>Register with your carrier</item>
+    </string-array>
+    <!-- Template for showing cellular network operator name while WFC is active -->
+    <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
 </resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 2080d50..cae1d90 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Банерот со роаминг е исклучен"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Пребарување за услуга"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Повикување преку Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не е препратено"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> по <xliff:g id="TIME_DELAY">{2}</xliff:g> секунди"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Овозможува апликацијата да прави фотографии и да снима видеа со камерата. Оваа дозвола овозможува апликацијата да ја користи камерата во кое било време без ваша потврда."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"оневозможи пренесување на LED показателот при употреба на фотоапаратот"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Овозможува претходно инсталираниот систем на апликацијата да оневозможи фотоапаратот да го користи LED показателот."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Дозволува претходно инсталираната системска апликација да ги испраќа системските настани на успугата за фотоапарат."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"трајно оневозможи го таблетот"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"трајно оневозможи го телевизорот"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"трајно оневозможи го телефонот"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"директно стартувај поставување CDMA на телевизорот"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"директно вклучи подесувања за телефон CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Дозволува апликацијата да започне одредување на ЦДМА. Злонамерните апликации може непотребно да започнат со одредување на ЦДМА."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"контролирај известувања за ажурирање локација"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Дозволува апликацијата да овозможува/оневозможува известувања за ажурирање локација од радио. Да не се користи за стандардни апликации."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"пристапи кон својства за пријавување"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Дозволува апликацијата да повика начини за додавање и бришење шаблони на отпечатоци за користење."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"користи хардвер за отпечатоци"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозволува апликацијата да користи хардвер за отпечатоци за проверка"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Откриен е делумен отпечаток. Обидете се повторно."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Отпечатокот не можеше да се обработи. Обидете се повторно."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Сензорот за отпечатоци е валкан. Исчистете го и обидете се повторно."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Прстот се движеше премногу брзо. Обидете се повторно."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Прстот се движеше премногу бавно. Обидете се повторно."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Добивање порака за грешка карактеристична за снабдувачот 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Не може да се обработи. Обидете се повторно."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Хардвер не е достапен."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Отпечатокот не може да се складира. Отстранете го постоечкиот отпечаток."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Се достигна времето на истекување на отпечатокот. Обидете се повторно."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Се достигна времето на истекување на отпечатокот. Обидете се повторно."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Порака за грешка карактеристична за снабдувачот."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"прочитај синхронизирани подесувања"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Овозможува апликацијата да ги чита подесувањата за синхронизирање на сметка. На пример, така може да се утврди дали апликацијата „Луѓе“ е синхронизирана со сметка."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"вклучи и исклучи синхронизација"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Дозволува апликација да отстранува ДРМ-сертификати. Не треба да се користи за стандардни апликации."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"сврзување со давателот на услугата за пораки"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Дозволува сопственикот да се сврзе со интерфејсот од највисоко ниво на давателот на услугата за пораки. Не треба да се користи за стандардни апликации."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Подеси правила за лозинката"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролирај ги должината и знаците што се дозволени за лозинки и ПИН-броеви за отклучување екран."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Следи ги обидите за отклучување на екранот"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Дозволува апликацијата да провери дали пакетот може да се инсталира."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"врзи се со проверувач на пакет"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Дозволува сопственикот да поднесува барања до верификаторите на пакети. Не треба да се користи за стандардни апликации."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"провери го наменскиот филтер"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Дозволува апликацијата да проверува дали наменскиот филтер е проверен или не."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"врзано со наменски проверувач на филтер"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Дозволува сопственикот да поднесува барања до наменските проверувачи на филтри. Не треба да се користи за стандардни апликации."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"пристапи кон сериски порти"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Му овозможува на сопственикот да пристапи кон сериски порти употребувајќи го SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"однадвор пристапи кон обезбедувачи на содржина"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Намали ден"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Зголеми година"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Намали година"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Претходниот месец"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Следниот месец"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Копче „Alt“"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Копче „Откажи“"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Копче „Избриши“"</string>
@@ -1796,11 +1838,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Приказ на минути во кружно движење"</string>
     <string name="select_hours" msgid="6043079511766008245">"Избери часови"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Избери минути"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Рамка на месец со денови"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Список по години"</string>
     <string name="select_day" msgid="7774759604701773332">"Избери месец и ден"</string>
     <string name="select_year" msgid="7952052866994196170">"Избери година"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Избрано <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Избришано <xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Работа <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"За да го откачите екранот, допрете и задржете Назад и Краток преглед во исто време."</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 2ae1177..84aef4c 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"റോമിംഗ് ബാനർ ഓഫാക്കുക"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"സേവനത്തിനായി തിരയുന്നു"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi കോളിംഗ്"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: കൈമാറിയില്ല"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> നിമിഷത്തിനുശേഷം <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"ക്യാമറ ഉപയോഗിച്ച് ചിത്രങ്ങളും വീഡിയോകളും എടുക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ സ്ഥിരീകരണമില്ലാതെ ഏതുസമയത്തും ക്യാമറ ഉപയോഗിക്കാൻ ഈ അനുമതി അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"ക്യാമറ ഉപയോഗത്തിലായിരിക്കുമ്പോൾ ട്രാൻസ്‌മിറ്റ് ഇൻഡിക്കേറ്റർ LED പ്രവർത്തനരഹിതമാക്കുക"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"ക്യാമറയുടെ ഇൻഡിക്കേറ്റർ LED-യുടെ ഉപയോഗം പ്രവർത്തനരഹിതമാക്കാൻ മുൻകൂട്ടി ഇൻസ്റ്റാളുചെയ്‌ത സിസ്റ്റം അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"ക്യാമറ സേവന സിസ്റ്റം ഇവന്റുകൾ അയയ്‌ക്കാൻ മുൻകൂട്ടി ഇൻസ്റ്റാളുചെയ്‌ത ഒരു സിസ്റ്റം അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"ശാശ്വതമായി ടാബ്‌ലെറ്റ് പ്രവർത്തനരഹിതമാക്കുക"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"ടിവിയെ ശാശ്വതമായി പ്രവർത്തനരഹിതമാക്കുക"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ശാശ്വതമായി ഫോൺ പ്രവർത്തനരഹിതമാക്കുക"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA സജ്ജീകരണം നേരിട്ട് ആരംഭിക്കുന്നു"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA ഫോൺ സജ്ജീകരണം നേരിട്ട് ആരംഭിക്കുക"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"CDMA പ്രൊവിഷനിംഗ് ആരംഭിക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ദോഷകരമായ അപ്ലിക്കേഷനുകൾ അനാവശ്യമായി CDMA പ്രൊവിഷനിംഗ് ആരംഭിച്ചേക്കാം."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"ലൊക്കേഷൻ അപ്‌ഡേറ്റ് അറിയിപ്പുകൾ നിയന്ത്രിക്കുക"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"റേഡിയോയിൽ നിന്ന് ലൊക്കേഷൻ അപ്ഡേറ്റ് അറിയിപ്പുകൾ പ്രവർത്തനക്ഷമമാക്കുന്നതിന്/പ്രവർത്തനരഹിതമാക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. സാധാരണ അപ്ലിക്കേഷനുകൾക്കായുഌഅ ഉപയോഗത്തിനല്ല."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"ചെക്ക്ഇൻ പ്രോപ്പർട്ടികൾ ആക്‌സസ്സ് ചെയ്യുക"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ഉപയോഗിക്കാനായി വിരലടയാള ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ഫിംഗർപ്രിന്റ് ഹാർഡ്‌വെയർ ഉപയോഗിക്കുക"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"പ്രാമാണീകരണത്തിനായി വിരലടയാളം ഉപയോഗിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"വിരലടയാളം ഭാഗികമായി തിരിച്ചറിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"വിരലടയാളം പ്രോസസ്സ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"വിരലടയാള സെൻസറിന് വൃത്തിയില്ല. അത് ശുചിയാക്കി വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"വിരൽ വേഗത്തിൽ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"വിരൽ പതുക്കെ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"വെൻഡർ നിർദ്ദിഷ്‌ട നേടൽ പിശക് സന്ദേശം 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"പ്രോസസ്സ് ചെയ്യാനാവുന്നില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"ഹാർഡ്‌വെയർ ലഭ്യമല്ല."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"വിരലടയാളം സംഭരിക്കാനാവില്ല. നിലവിലുള്ള വിരലടയാളം നീക്കംചെയ്യുക."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"വിരലടയാളം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"വിരലടയാളം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"വെൻഡർ നിർദ്ദിഷ്‌ട പിശക് സന്ദേശം."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യുക"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ഒരു അക്കൗണ്ടിനായി സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഉദാഹരണത്തിന്, ആളുകൾ അപ്ലിക്കേഷൻ ഒരു അക്കൗണ്ടിൽ സമന്വയിപ്പിച്ചിട്ടുണ്ടോയെന്നത് നിർണ്ണയിക്കാൻ ഇതിനാകും."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"സമന്വയം ഓണാക്കുക, ഓഫാക്കുക ടോഗിൾചെയ്യുക"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM സർട്ടിഫിക്കറ്റുകൾ നീക്കംചെയ്യുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. സാധാരണ അപ്ലിക്കേഷനുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"കാരിയർ സന്ദേശമയയ്‌ക്കൽ സേവനത്തിലേക്ക് ബന്ധിപ്പിക്കുക"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"ഒരു കാരിയർ സന്ദേശമയയ്‌ക്കൽ സേവനത്തിന്റെ ഉയർന്ന നിലയിലുള്ള ഇന്റർഫേസിലേക്ക് ബന്ധിപ്പിക്കാൻ ദാതാവിനെ അനുവദിക്കുന്നു. സാധാരണ അപ്ലിക്കേഷനുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"പാസ്‌വേഡ് നിയമങ്ങൾ സജ്ജീകരിക്കുക"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"സ്‌ക്രീൻ ലോക്ക് പാസ്‌വേഡുകളിലും PIN-കളിലും അനുവദിച്ചിരിക്കുന്ന ദൈർഘ്യവും പ്രതീകങ്ങളും നിയന്ത്രിക്കുക."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"സ്‌ക്രീൻ അൺലോക്ക് ശ്രമങ്ങൾ നിരീക്ഷിക്കുക"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"ഒരു പാക്കേജ് ഇൻസ്റ്റാളുചെയ്യാനാവുന്നതാണോ എന്ന് പരിശോധിച്ചുറപ്പിക്കുന്നതിന് അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"ഒരു പാക്കേജ് വെരിഫയറുമായി ബന്ധപ്പെടുത്തുക"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"പാക്കേജ് പരിശോധകരുടെ അഭ്യർത്ഥനകൾക്ക് ഹോൾഡറിനെ അനുവദിക്കുന്നു. സാധാരണ അപ്ലിക്കേഷനുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"ഉദ്ദേശിക്കുന്ന ഫിൽട്ടർ പരിശോധിച്ചുറപ്പിക്കുക"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"ഒരു ഉദ്ദേശിക്കുന്ന ഫിൽട്ടർ പരിശോധിച്ചുറപ്പിച്ചോ ഇല്ലയോ എന്ന് പരിശോധിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"ഒരു ഉദ്ദേശിക്കുന്ന ഫിൽട്ടർ പരിശോധകനിലേക്ക് ബന്ധിപ്പിക്കുക"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"ഉദ്ദേശിക്കുന്ന ഫിൽട്ടർ പരിശോധകരുടെ അഭ്യർത്ഥനകൾക്ക് ഉടമയെ അനുവദിക്കുന്നു. സാധാരണ അപ്ലിക്കേഷനുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"സീരിയൽ പോർട്ടുകൾ ആക്‌സസ്സ് ചെയ്യുക"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API ഉപയോഗിക്കുന്ന സീരിയൽ പോർട്ടുകൾ ആക്‌സസ്സ് ചെയ്യാൻ ദാതാവിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"ഉള്ളടക്ക ദാതാക്കളെ ബാഹ്യമായി ആക്‌സസ്സുചെയ്യുക"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ദിവസം കുറയ്ക്കുക"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"വർഷം വർദ്ധിപ്പിക്കുക"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"വർഷം കുറയ്‌ക്കുക"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"മുമ്പത്തെ മാസം"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"അടുത്ത മാസം"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"റദ്ദാക്കുക"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ഇല്ലാതാക്കുക"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"ചാക്രികമായി മിനിറ്റുകൾ ദൃശ്യമാകുന്ന സ്ലൈഡർ"</string>
     <string name="select_hours" msgid="6043079511766008245">"മണിക്കൂർ തിരഞ്ഞെടുക്കുക"</string>
     <string name="select_minutes" msgid="3974345615920336087">"മിനിറ്റ് തിരഞ്ഞെടുക്കുക"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"മാസപ്രകാരമുള്ള ദിവസ ഗ്രിഡ്"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"വർഷങ്ങളുടെ ലിസ്റ്റ്"</string>
     <string name="select_day" msgid="7774759604701773332">"മാസവും ദിവസവും തിരഞ്ഞെടുക്കുക"</string>
     <string name="select_year" msgid="7952052866994196170">"വർഷം തിരഞ്ഞെടുക്കുക"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> തിരഞ്ഞെടുത്തു"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ഇല്ലാതാക്കി"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"ഔദ്യോഗികം <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"ഈ സ്‌ക്രീൻ അൺപിൻ ചെയ്യാൻ \'മടങ്ങുക\', \'കാഴ്ച\' എന്നിവ ഒരേ സമയം സ്‌പർശിച്ച് പിടിക്കുക."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 4a8b5b9..33fde50 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Баннергүй рүүминг"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Үйлчилгээг хайж байна…"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi Calling"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: дамжуулагдаагүй"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> секундын дараа"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Апп нь камераар зураг авах болон видео бичих боломжтой. Энэ зөвшөөрөл нь апп-д ямар ч үед таны зөвшөөрөлгүйгээр камер ашиглах боломжийг олгоно."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"камер ашиглаж байх үед дамжууллыг заагч LED-г идэвхгүй болгох"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Урьдчилан суусан систем аппликешн нь камер ашиглалтыг заасан LED-г идэвхгүй болгох боломжтой."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Урьдчилан суулгасан системийн аппликейшнд Камерын үйлчилгээний системийн ажиллагаануудыг илгээхийг зөвшөөрнө."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"таблетыг бүрмөсөн идэвхгүй болгох"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"телевиз-г бүр мөсөн идэвхгүй болгох"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"утсыг бүрмөсөн идэвхгүй болгох"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA телевиз-ийн тохиргоог шууд эхлүүлэх"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA утасны тохиргоог шууд эхлүүлэх"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Апп нь CDMA провишныг эхлүүлэх боломжтой. Хортой апп нь шаардлагагүй байхад CDMA провишныг эхлүүлж болзошгүй."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"байршил шинэчлэх мэдэгдлийг удирдах"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Апп нь радиогоос ирсэн байршил шинэчлэх мэдэгдлийг идэвхтэй/идэвхгүй болгох боломжтой. Энгийн апп-д хэрэглэглэхгүй."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"бүртгэх пропертид хандах"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Хурууны хээний загварыг нэмэх эсвэл усгтах үйлдлийг хийх зөвшөөрлийг програмд олгодог."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"хурууны хээний програм хангамжийг ашиглах"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний програм хамгамжийг ашиглах зөвшөөрлийг програмд олгодог"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Хурууны хээг дутуу уншуулсан байна. Дахин оролдоно уу."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Хурууны хээ боловсруулж чадахгүй байна. Дахин оролдоно уу."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Хурууны хээ мэдрэгч бохирдсон байна. Та цэвэрлэсний дараагаар дахин оролдоно уу."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Хурууг уншиж дуусаагүй байхад авсан байна. Та дахин уншуулна уу."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Хурууг хэт удаан уншуулсан байна. Та дахин уншуулна уу."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Борлуулагч-хурууны хээ авахад гардаг алдаа 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Мэдээллийг оруулах боломжгүй байна. Дахин оролдоно уу."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Техник хангамж бэлэн бус байна"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Хурууны хээг хадгалах боломжгүй байна. Одоо байгаа хурууны хээг арилгана уу."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Хурууны хээ оруулах хугацаа өнгөрсөн байна. Дахин оруулна уу."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Хурууны хээ оруулах хугацаа өнгөрсөн байна. Дахин оруулна уу."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Борлуулаг-тодорхой алдааны зурвас"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"синк тохиргоог унших"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Апп нь акаунтын синк тохиргоог унших боломжтой. Жишээ нь энэ нь Хүмүүс апп акаунттай синк хийгдсэн эсэхийг тодорхойлох боломжтой."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"синкийг унтрааж асаах тохиргоо"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Аппликешнд DRM сертификатыг устгахыг зөвшөөрнө. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"зөөгч зурвасын үйлчилгээнд холбох"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Эзэмшигчид зөөгч зурвасын үйлчилгээний түвшний интерфэйст холбогдохыг зөвшөөрдөг. Энгийн апп-д шаардлагагүй."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Нууц үгний дүрмийг тохируулах"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Дэлгэц түгжих нууц үг болон ПИН кодны урт болон нийт тэмдэгтийн уртыг хянах."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Дэлгэц тайлах оролдлогыг хянах"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Апп нь багцыг суулгаж болох эсэхийг шалгах боломжтой."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"багц тулгагчтэй холбох"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Эзэмшигч нь багц тулгагчдад хүсэлт тавих боломжтой. Энгийн апп-д хэрэглэгдэхгүй."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"зориулалтын шүүлтүүрийг баталгаажуулах"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Зориулалтын шүүлтүүрийг баталгаажуулсан эсэхээс үл хамааран апп-д шалгах зөвшөөрөл өгөх"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"зориулалтын шүүлтүүр шалгагч руу холбох"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Эзэмшигчид зориулалтын шүүлтүүрийг шалгах хүсэлт гаргахыг зөвшөөрөх. Энэ нь энгийн апп-уудад огт шаардлагагүй."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"сериал портруу хандах"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Эзэмшигч нь SerialManager API ашиглан сериал портод хандах боломжтой."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"контент нийлүүлэгчид гаднаас хандах"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Өдрийг бууруулах"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Жилийг өсгөх"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Жил бууруулах"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Өмнөх сар"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Дараагийн сар"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Цуцлах"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Устгах"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Минут гүйлгэгч"</string>
     <string name="select_hours" msgid="6043079511766008245">"Цаг сонгоно уу"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Минут сонгоно уу"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Өдрүүдийг сараар"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Жилийн жагсаалт"</string>
     <string name="select_day" msgid="7774759604701773332">"Сар болон өдрийг сонгоно уу"</string>
     <string name="select_year" msgid="7952052866994196170">"Жилийг сонгоно уу"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> сонгогдсон"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> устсан"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Ажлын <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Энэ дэлгэцийг цуцлахын тулд Буцах болон Тойм-д зэрэг хүрч барина."</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 3fc5663..c8a4d06 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"रोमिंग बॅनर बंद"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"सेवा शोधत आहे"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"वाय-फाय कॉलिंग"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित केला नाही"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकंदांनंतर <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"कॅमेर्‍यासह चित्रे आणि व्हिडिओ घेण्यासाठी अॅप ला अनुमती देते. ही परवानगी आपल्या पुष्टीकरणाशिवाय कोणत्याही वेळी कॅमेरा वापरण्यासाठी अॅप ला परवानगी देते."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"कॅमेरा वापरात असताना प्रक्षेपण सूचक LED अक्षम करा"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"पूर्व-स्‍थापित सिस्‍टम अनुप्रयोगाला कॅमेरा वापर सूचक LED अक्षम करण्‍याची अनुमती देते."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"पूर्व-स्थापित सिस्टीम अनुप्रयोगास कॅमेरा सेवा सिस्टीम इव्हेंट पाठविण्यासाठी अनुमती देते."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"टॅब्लेट कायमचा अक्षम करा"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"टीव्ही कायमचा अक्षम करा"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"फोन कायमचा अक्षम करा"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA TV सेटअप थेट प्रारंभ करा"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA फोन सेटअप थेट प्रारंभ करा"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"CDMA तरतूद प्रारंभ करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स CDMA तरतूद अनावश्यकपणे प्रारंभ करू शकतात."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"नियंत्रण स्थान अद्यतन सूचना"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"रेडिओवरील स्थान अद्यतन सूचना सक्षम/अक्षम करण्यासाठी अॅप ला अनुमती देते. सामान्य अॅप्सद्वारे वापरण्यासाठी नाही."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"चेकइन गुणधर्मांवर प्रवेश करा"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"वापर करण्याकरिता फिंगरप्रिंट टेम्पलेट जोडण्यासाठी आणि हटविण्यासाठी पद्धती रद्द करण्यास अॅपला अनुमती देते."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"फिंगरप्रिंट हार्डवेअर वापरा"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"प्रमाणीकरणाकरिता फिंगरप्रिंट हार्डवेअरचा वापर करण्यासाठी अॅपला अनुमती देते"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फिंगरप्रिंट आढळली. कृपया पुन्हा प्रयत्न करा."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फिंगरप्रिंटवर प्रक्रिया करणे शक्य झाले नाही. कृपया पुन्हा प्रयत्न करा."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"फिंगरप्रिंट सेन्सर खराब आहे. कृपया साफ करा आणि पुन्हा प्रयत्न करा."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"बोट लवकर हलविले. कृपया पुन्हा प्रयत्न करा."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"बोट हळू हलविले. कृपया पुन्हा प्रयत्न करा."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"व्यापारी-विशिष्‍ट प्राप्ती त्रुटी संदेश 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"प्रक्रिया करण्यात अयशस्वी. पुन्हा प्रयत्न करा."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"हार्डवेअर उपलब्ध नाही."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फिंगरप्रिंट संचयित केले जाऊ शकत नाही. कृपया विद्यमान फिंगरप्रिंट काढा."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फिंगरप्रिंट कालबाह्य झाले. पुन्हा प्रयत्न करा."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"फिंगरप्रिंट कालबाह्य झाले. पुन्हा प्रयत्न करा."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"व्यापारी-विशिष्‍ट त्रुटी संदेश."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"संकालन सेटिंग्‍ज वाचा"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"खात्याच्या संकालन सेटिंग्ज वाचण्यासाठी अॅप ला अनुमती देते. उदाहरणार्थ, हे खात्यासह लोकांचा अॅप संकालित केला आहे किंवा नाही हे निर्धारित करू शकते."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"संकालन चालू आणि बंद करा टॉगल करा"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM प्रमाणपत्रे काढण्यासाठी अनुप्रयोगास अनुमती देते. सामान्य अॅप्स साठी कधीही आवश्यकता नसते."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"एका वाहक संदेशन सेवेसाठी प्रतिबद्ध"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"वाहक संदेशन सेवेचा शीर्ष-स्तर इंटरफेस प्रतिबद्ध करण्यासाठी होल्डरला अनुमती देते. सामान्‍य अ‍ॅप्‍सकरिता कधीही आवश्‍यक नसते."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"संकेतशब्द नियम सेट करा"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रीन लॉक संकेतशब्द आणि पिन मध्ये अनुमती दिलेली लांबी आणि वर्ण नियंत्रित करा."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"स्क्रीन-अनलॉक प्रयत्नांचे परीक्षण करा"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"पॅकेज स्थापित करण्यायोग्य आहे हे सत्यापित करण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"पॅकेज सत्यापकावर प्रतिबद्ध व्हा"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"पॅकेज सत्यापित करणार्‍यांच्या विनंत्या करण्यासाठी होल्डरला अनुमती देते. सामान्य अॅप्सकरिता कधीही आवश्यक नसते."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"हेतू फिल्टर सत्यापित करा"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"हेतू फिल्टर सत्यापित केले आहे किंवा नाही हे तपासण्यासाठी अॅपला अनुमती देते."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"हेतू फिल्टर सत्यापनकर्त्यावर प्रतिबद्ध व्हा"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"हेतू फिल्टर सत्यापनकर्त्यांच्या विनंत्या करण्यासाठी होल्डरला अनुमती देते. सामान्य अॅप्सकरिता कधीही आवश्यकता नसावी."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"क्रमांक पोर्टवर प्रवेश करा"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API वापरून क्रमांक पोर्टवर प्रवेश करण्यास होल्डरला अनुमती देते."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"सामग्री प्रदात्यांवर बाह्यरित्या प्रवेश करेल"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"दिवस कमी करा"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"वर्ष वाढवा"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"वर्ष कमी करा"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"मागील महिना"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"पुढील महिना"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"रद्द करा"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"हटवा"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"मिनिटे परिपत्रक स्लायडर"</string>
     <string name="select_hours" msgid="6043079511766008245">"तास निवडा"</string>
     <string name="select_minutes" msgid="3974345615920336087">"मिनिटे निवडा"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"दिवसांची महिना ग्रिड"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"वर्ष सूची"</string>
     <string name="select_day" msgid="7774759604701773332">"महिना आणि दिवस निवडा"</string>
     <string name="select_year" msgid="7952052866994196170">"वर्ष निवडा"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> निवडले"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> हटविली"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"ही स्क्रीन अनपिन करण्यासाठी, एकाच वेळी परत आणि विहंगावलोकनास स्पर्श करा आणि धरून ठेवा."</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index d849680..77773e9 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Sepanduk Perayauan Dimatikan"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Mencari Perkhidmatan"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Panggilan Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak dimajukan"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> selepas <xliff:g id="TIME_DELAY">{2}</xliff:g> saat"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Membenarkan apl mengambil gambar dan video menggunakan kamera. Kebenaran ini membenarkan apl untuk menggunakan kamera pada bila-bila masa tanpa pengesahan anda."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"lumpuhkan LED penunjuk penghantaran semasa kamera sedang digunakan"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Membenarkan aplikasi sistem yang diprapasang untuk melumpuhkan LED penunjuk penggunaan kamera."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Membenarkan aplikasi sistem yang diprapasang menghantar acara sistem perkhidmatan kamera."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"melumpuhkan tablet secara kekal"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"lumpuhkan TV secara kekal"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"lumpuhkan telefon secara kekal"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"mulakan persediaan TV CDMA secara langsung"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"memulakan persediaan telefon CDMA secara langsung"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Membenarkan apl memulakan peruntukan CDMA. Apl hasad boleh memulakan peruntukan CDMA yang tidak perlu."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"kawal pemberitahuan kemas kini lokasi"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Membenarkan apl untuk mendayakan/melumpuhkan pemberitahuan kemas kini lokasi dari radio. Bukan untuk kegunaan apl biasa."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"akses sifat daftar masuk"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Membenarkan apl menggunakan kaedah untuk menambahkan dan memadamkan templat cap jari untuk digunakan."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"gunakan perkakasan cap jari"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Membenarkan apl menggunakan perkakasan cap jari untuk pengesahan"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Cap jari separa dikesan. Sila cuba lagi."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Tidak dapat memproses cap jari. Sila cuba lagi."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Penderia cap jari kotor. Sila bersihkan dan cuba lagi."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Jari digerakkan terlalu cepat. Sila cuba lagi."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Jari digerakkan terlalu perlahan. Sila cuba lagi."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Mesej ralat pemerolehan khusus vendor 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Tidak dapat memproses. Cuba lagi."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Perkakasan tidak tersedia."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Cap jari tidak dapat disimpan. Sila alih keluar cap jari sedia ada."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tamat masa cap jari dicapai. Cuba lagi."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Tamat masa cap jari dicapai. Cuba lagi."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Mesej ralat khusus vendor"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"membaca tetapan penyegerakan"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Membenarkan apl membaca tetapan segerak untuk akaun. Sebagai contoh, ini boleh menentukan sama ada apl Orang disegerakkan dengan akaun."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"togol segerak hidup dan mati"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Membenarkan aplikasi mengalih keluar sijil DRM. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"terikat kepada perkhidmatan pemesejan pembawa"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi perkhidmatan pemesejan pembawa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan  dan PIN kunci skrin."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Membenarkan apl untuk mengesahkan bahawa pakej boleh dipasang."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"ikat kepada pengesah pakej"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Membenarkan pemegang membuat permintaan pengesah pakej. Tidak sekali-kali diperlukan untuk apl normal."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"sahkan penapis hasrat"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Membenarkan apl untuk memeriksa sama ada penapis hasrat disahkan atau tidak."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"terikat kepada pengesah penapis hasrat"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Membenarkan pemegang membuat permintaan pengesah penapis hasrat. Tidak sekali-kali diperlukan untuk apl normal."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"akses port bersiri"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Membenarkan pemegang mengakses port bersiri menggunakan API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"akses pembekal kandungan secara luaran"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Kurangkan hari"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Tingkatkan tahun"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Kurangkan tahun"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Bulan sebelumnya"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Bulan seterusnya"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Batal"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Padam"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Penggelangsar bulatan minit"</string>
     <string name="select_hours" msgid="6043079511766008245">"Pilih jam"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Pilih minit"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Grid hari bulanan"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Senarai tahun"</string>
     <string name="select_day" msgid="7774759604701773332">"Pilih bulan dan hari"</string>
     <string name="select_year" msgid="7952052866994196170">"Pilih tahun"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> dipilih"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dipadamkan"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Kerja <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Untuk menyahsemat skrin ini, sentuh dan tahan Kembali serta Ikhtisar pada masa yang sama."</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 36a6cde..a8e22e2 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"ရုန်းမင်းစာတမ်းပိတ်ထားရန်"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"ဆားဗစ်အားရှာဖွေနေသည်"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"ဝိုင်ဖိုင် ခေါ်ဆိုမှု"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ထပ်ဆင့်မပို့နိုင်ပါ"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> နောက် <xliff:g id="TIME_DELAY">{2}</xliff:g> စက္ကန့်"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"အပလီကေးရှင်းအား အလိုအလျောက် ဓာတ်ပုံရိုက်ခွင့်၊ ဗီဒီယို ရိုက်ကူးခွင့် ပြုပါ။ ဒီခွင့်ပြုချက်က အပလီကေးရှင်းကို အချိန်မရွေး ကင်မရာအား ခွင့်ပြုချက် မလိုအပ်ပဲ သုံးခွင့်ပြုပါသည်။"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"ထုတ်လွှင့်မှုပြ အချက်ပေး မီးအား ကင်မရာ သုံးနေစဉ် ပိတ်ရန်"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"ကြိုတင်သွင်းထားသော စစ်စတန် စနစ်တစ်ခုကို ကင်မရာ သုံးနေသော မီးအား ထိန်းချုပ်ခွင့်ပေးခြင်း"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"ကြိုတင်ထည့်သွင်းထားသည့် စနစ်အပလီကေးရှင်းကို စနစ်ဖြစ်ရပ်ကင်မရာ ဝန်ဆောင်မှုကို ပို့ခွင့်ပြုပါသည်။"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"တက်ပလက်ကို အမြဲတမ်း အလုပ်မလုပ်ရန်ပိတ်ခြင်း"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"တီဗွီအား အပြီးပိတ်ရန်"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ဖုန်းကို အမြဲတမ်း အလုပ်မလုပ်ရန်ပိတ်ခြင်း"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA TV ပြင်ဆင်သတ်မှတ်မှုအား တိုက်ရိုက်စတင်ရန်"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMAဖုန်း အစသတ်မှတ်ခြင်းကို တိုက်ရိုက်စတင်ရန်"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"appအား CDMA အတွက် စီမံလုပ်ကိုင်မှုကို စတင်ခွင့် ပြုသည်။ ကြံဖန် appများက မလိုအပ်ဘဲနှင့် CDMA အတွက် စီမံလုပ်ကိုင်မှုကို စတင်နိုင်ကြသည်။"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"တည်နေရာအဆင့်မြှင့်ခြင်းသတိပေးချက်အားထိန်းချုပ်ရန်"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"appအား ရေဒီယိုထံမှ တည်နေရာ မွမ်းမံမှု အကြောင်းကြားစာများကို ပိတ်/ဖွင့်ခွင့် ပြုသည်။ သာမန် appများ အသုံးပြုရန် မဟုတ်နိုင်ပါ။"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"ချက်ခ်အင်ဂုဏ်သတ္တိများအား ဝင်ရောက်ချိတ်ဆက်ခြင်း"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"အသုံးပြုရန်အတွက် လက်ဗွေရာပုံစံများကို ပေါင်းထည့်ရန် သို့မဟုတ် ဖျက်ရန်နည်းလမ်းများကို အပ်ဖ်အား အသုံးပြုခွင့်ပြုသည်။"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"လက်ဗွေရာပစ္စည်းကို အသုံးပြုမည်"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"စစ်မှန်ကြောင်းအထောက်အထားပြသခြင်းအတွက် လက်ဗွေရာပစ္စည်းကို အသုံးပြုရန် အပ်ဖ်အားခွင့်ပြုသည်။"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"လက်ဗွေရဦ တစ်ပိုင်းတစ်စ တွေ့ရှိသည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"လက်ဗွေရာယူခြင်း မဆောင်ရွက်နိုင်ပါ။ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"လက်ဗွေရာဖတ်ကိရိယာ ညစ်ပေနေသည်။ ကျေးဇူးပြု၍ ရှင်းလင်းကာ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"လက်ရွှေ့လျားခြင်း အလွန်မြန်သည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"လက်ရွှေ့လျားခြင်း အလွန်နှေးသည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"ရောင်းသူ-တိကျသတ်မှတ်သော ရယူခြင်းဆိုင်ရာ မှားယွင်းချက် စာ ၀"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"လုပ်ဆောင်၍မရပါ။ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"ပစ္စည်းမရနိုင်ပါ။"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"လက်ဗွေရာ သိုလှောင်၍မရပါ။ ကျေးဇူးပြု၍ ရှိပြီးလက်ဗွေရာအား ဖယ်ရှားပါ။"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"လက်ဗွေရာအချိန်ကုန် သွားပါသည်။ ထပ်မံကြိုးစားပါ။"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"လက်ဗွေရာအချိန်ကုန် သွားပါသည်။ ထပ်မံကြိုးစားပါ။"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"ရောင်းသူ-တိကျသတ်မှတ်သော မှားယွင်းချက် စာ။"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ထပ်တူပြုအဆင်အပြင်အားဖတ်ခြင်း"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"အပလီကေးရှင်းအား အကောင့်တစ်ခုအတွက် ထပ်တူညီအောင် လုပ်ဆောင်မှု ဆက်တင်အား ကြည့်ခွင့် ပြုပါ။ ဥပမာ People app က အကောင့်တစ်ခုနဲ့ ထပ်တူညီအောင် လုပ်ရန် ဆက်သွယ်ထားမှု ရှိမရှိ သိရှိနိုင်ခြင်း"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ထပ်တူညီအောင် လုပ်ခြင်းအား ပြုနိုင်၊ မပြုနိုင် အပြောင်းအလဲလုပ်ခြင်း"</string>
@@ -822,6 +854,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"အပလီကေးရှင်းအား DRM လက်မှတ်များကို ဖယ်ရှားခွင့် ပြုသည်။  သာမန် appများ အတွက် ဘယ်တော့မှ မလိုအပ်နိုင်ပါ။"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"စာပို့စာယူ ဆက်သွယ်ရေးဝန်ဆောင်မှုတစ်ခုအား ပူးပေါင်းခွင့်ပြုရန်"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"စာပို့စာယူဆက်သွယ်ရေးဝန်ဆောင်မှုတစ်ခု၏ ထိပ်ဆုံးရှိအင်တာဖေ့စ်ဖြင့် ပူးပေါင်းရန် ပိုင်ရှင်အားခွင့်ပြုပါ။ ပုံမှန် app များအတွက် မလိုအပ်ပါ။"</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"အသံအပြန်အလှန်စကားပြောခြင်း ဝန်ဆောင်မှုဖြင့် ချိတ်ဆက်ရန်"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"စွဲကိုင်ထားသူအား လက်ရှိပွင့်နေသည့် အသံအပြန်လှန်စကားပြောခြင်း ဝန်ဆောင်မှုကို ချိတ်ဆက်ရန် ခွင့်ပြုသည်။ သာမန်အပ်ဖ်များအတွက် ဘယ်တော့မှ မလိုအပ်နိုင်ပါ။"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"စကားဝှက်စည်းမျဥ်းကိုသတ်မှတ်ရန်"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"မျက်နှာပြင်သော့ခတ်သည့် စကားဝှက်များနှင့် PINများရှိ ခွင့်ပြုထားသည့် စာလုံးအရေအတွက်နှင့် အက္ခရာများအား ထိန်းချုပ်ရန်။"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"မော်နီတာမျက်နှာပြင်ဖွင့်ရန် ကြိုးစားခွင့်များ"</string>
@@ -1119,6 +1153,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"appအား အထုပ် တစ်ခု၏ မတည်ငြိမ်မှုကို စိစစ်ခွင့် ပြုသည်။"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"package အတည်ပြုခြင်းနှင့် ပူးပေါင်းရန်"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"စွဲကိုင်ထားသူအား အထုပ်များအား စိစစ်ရေး တောင်းဆိုချက်များကို ပြုလုပ်ခွင့် ပေးသည်။ သာမန် appများ အတွက် ဘယ်တော့မှ မလိုအပ်နိုင်ပါ။"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"လိုအပ်သည့်စစ်ထုတ်ခြင်းကို အတည်ပြုမည်"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"လိုအပ်သည့်စစ်ထုတ်ခြင်း အတည်ပြုပြီးခြင်း ရှိမရှိ အပ်ဖ်အား စစ်ဆေးခွင့်ပြုမည်။"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"လိုအပ်သည့်စစ်ထုတ်ခြင်း အတည်ပြုကိရိယာဖြင့် ပေါင်းမည်"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"စွဲကိုင်ထားသူအား လိုအပ်အသည့်စစ်ထုတ်ခြင်း စိစစ်ရေး တောင်းဆိုချက်များကို ပြုလုပ်ခွင့် ပေးသည်။ သာမန် အပ်ဖ်များ အတွက် ဘယ်တော့မှ မလိုအပ်နိုင်ပါ။"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"အစဥ်လိုက်ပို့များကို ဝင်ရောက်ချိတ်ဆက်ခြင်း"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager APIအားအသုံးပြုကာ ကိုင်ဆောင်သူကို စီရီယာပို့မျာကို ဝင်ရောက်အသုံးပြုခြင်းအား ခွင့်ပြုသည်။"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"အချက်အလက်များ ပံ့ပိုသူများအား အပြင်ဖက်မှ ရယူခြင်း"</string>
@@ -1544,6 +1582,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ရက် လျှော့ရန်"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"ခုနှစ် တိုးရန်"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ခုနှစ် လျှော့ရန်"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"ပြီးခဲ့သော လ"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"လာမည့် လ"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Altခလုတ်"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"ပယ်ဖျက်ရန်ခလုတ်"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ဖျက်ရန်ခလုတ်"</string>
@@ -1794,11 +1834,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"မိနစ်လှည့်သော ရွေ့လျားတန်"</string>
     <string name="select_hours" msgid="6043079511766008245">"နာရီများ ရွေးပါ"</string>
     <string name="select_minutes" msgid="3974345615920336087">"မိနစ်များ ရွေးပါ"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"လအလိုက် ရွေးနိုင်သော ရက်များ"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"ခုနှစ် အစဉ်"</string>
     <string name="select_day" msgid="7774759604701773332">"လ နှင့် ရက် ရွေးပါ"</string>
     <string name="select_year" msgid="7952052866994196170">"ခုနှစ်ကို ရွေးပါ"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ခုရွေးချယ်ထားပြီး"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ကို ဖျက်ပြီးပါပြီ"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"အလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"ဒီမျက်နှာပြင် ပင်ထိုးမှုကို ဖြုတ်ရန်၊ နောက်သို့ နှင့် ခြုံကြည့်မှု ခလုတ်များကို တစ်ချိန်တည်း ထိကိုင်ထားပါ။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 022bb16..cefc331 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Roaming-banner av"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Leter etter tjeneste"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-anrop"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderekoblet"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> etter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Appen tillates å ta bilder og filme med kameraet. Det betyr at appen kan bruke kameraet når som helst uten bekreftelse fra deg."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"deaktiver LED-lyset for indikering av overføring når kameraet er i bruk"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Tillater at forhåndsinnstallerte systemapper deaktiverer LED-indikatoren for kamerabruk."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Gjør at forhåndsinstallerte systemapper kan sende systemhandlinger for kameratjenester."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"deaktivere nettbrettet permanent"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"deaktiver TV-en permanent"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"deaktivere telefonen permanent"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"start CDMA-TV-konfigurering"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"begynne CDMA-telefonoppsett direkte"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Lar appen starte CDMA-oppsett. Ondsinnede apper kan bruke dette til å starte CDMA-oppsett uten grunn."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"kontrollere varsling for plasseringsendring"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Lar appen aktivere og deaktivere varsler om posisjonsoppdatering fra radioen. Ikke beregnet på vanlige apper."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"bruke innsjekking"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Lar appen fremkalle metoder for å legge til og slette fingeravtrykkmaler for bruk."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"bruke fingeravtrykkmaskinvare"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Lar appen bruke fingeravtrykkmaskinvare til godkjenning"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Deler av fingeravtrykket er registrert. Prøv på nytt."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Kunne ikke registrere fingeravtrykket. Prøv på nytt."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingeravtrykksensoren er skitten. Rengjør den og prøv på nytt."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Fingeren ble fjernet for raskt. Prøv på nytt."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Fingeren ble fjernet for sakte. Prøv på nytt."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Feilmelding 0 for leverandørspesifikk brukeranskaffelse"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Kunne ikke behandle fingeravtrykket. Prøv på nytt."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Maskinvaren er ikke tilgjengelig."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeravtrykket kan ikke lagres. Fjern et eksisterende fingeravtrykk."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Leverandørspesifikk feilmelding."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lese synkroniseringsinnstillinger"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Lar appen lese synkroniseringsinnstillingene for en konto. For eksempel kan den finne ut om Personer-appen er synkronisert med en konto."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"slå synkronisering av og på"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Gir en app tillatelse til å fjerne sertifikater for digital rettighetsadministrasjon. Skal ikke være nødvendig for vanlige apper."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"bind til en operatørmeldingstjeneste"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Tillater at innehaveren binder seg til det øverste nivået av grensesnittet til en operatørtjeneste. Dette skal aldri være nødvendig for vanlige apper."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrollerer tillatt lengde og tillatte tegn i passord og PIN-koder for opplåsing av skjermen."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Lar appen bekrefte om en pakke kan installeres."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind til en pakkeverifikator"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Lar innehaveren sende forespørsler om pakkeverifikatorer. Skal aldri være nødvendig for normale apper."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"bekreft intensjonsfilter"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Gjør at appen kan sjekke om et bestemt intensjonsfilter er bekreftet eller ikke."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"knytt til en verifikator for intensjonsfiltre"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Lar innehaveren sende forespørsler om verifikatorer for intensjonsfiltre. Skal aldri være nødvendig for vanlige apper."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"bruke serieporter"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Gir innehaveren tilgang til serielle porter ved hjelp av SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"gå til innholdsleverandører eksternt"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reduser dager"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Øk år"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reduser år"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Forrige måned"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Neste måned"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Avbryt"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Slett"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Sirkulær glidebryter for minutter"</string>
     <string name="select_hours" msgid="6043079511766008245">"Angi timer"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Angi minutter"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Månedsrutenett med dager"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Årsliste"</string>
     <string name="select_day" msgid="7774759604701773332">"Velg måneden og dagen"</string>
     <string name="select_year" msgid="7952052866994196170">"Velg året"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> er valgt"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> er slettet"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Jobb-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Hvis du vil avslutte én-appsmodusen for denne skjermen, trykker og holder du på Tilbake og Oversikt samtidig."</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 54fe0e5..c20f749 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"रोमिङ ब्यानर बन्द छ"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"सेवाको खोजी गर्दै…"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi कलिङ"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अगाडि पठाइएको छैन"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> पछि <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकेन्ड"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"अनुप्रयोगलाई क्यामेरासँग तस्बिर र भिडियोहरू लिन अनुमति दिन्छ। यस अनुमतिले अनुप्रयोगलाई तपाईंको पुष्टिकरण बिना कुनै पनि समयमा क्यामेरा प्रयोग गर्न स्वीकृति दिन्छ।"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"क्यामेरा प्रयोगमा हुँदा सूचक LED प्रसारण असक्षम गर्नुहोस्"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"पूर्व-स्थापित प्रणाली अनुप्रयोगलाई क्यामेरा उपयोग सूचक LED अक्षम गर्न अनुमति दिन्छ।"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"एउटा पूर्व-स्थापित प्रणाली अनुप्रयोगलाई क्यामेरा सेवा प्रणाली घटनाहरू पठाउन अनुमति दिन्छ।"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"स्थायी रूपमा ट्याब्लेट असक्षम पार्नुहोस्"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"स्थायी रूपमा TV अक्षम गर्नुहोस्"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"फोनलाई स्थायी रूपमा असक्षम पार्नहोस्"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"प्रत्यक्ष CDMA TV सेटअप सुरु गर्नुहोस्"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA फोन सेटअप सिधै सुरु गर्नुहोस्"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"अनुप्रयोगलाई CDMA प्रावधान सुरu गर्न अनुमति दिन्छ। खराब अनुप्रयोगहरूले अनावश्यक रूपमा CDMA प्रावधान सुरु गर्न सक्छन्।"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"स्थान अपडेट सूचनाहरू नियन्त्रण गर्नुहोस्"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"रेडियोबाट स्थान अद्यावधिक सूचनाहरूलाई सक्षम/असक्षम गर्न अनुप्रयोगलाई अनुमति दिन्छ। सामान्य अनुप्रयोगहरूबाट प्रयोग नहुने।"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"परीक्षण विशेषताहरू पहुँच गर्नुहोस्"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"अनुप्रयोगलाई प्रयोगको लागि औठाछाप टेम्प्लेट थप्न र मेटाउने तरिका आह्वान गर्न अनुमति दिन्छ।"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"औठाछाप हार्डवेयर प्रयोग गर्नुहोस्"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"अनुप्रयोगलाई प्रमाणीकरणको लागि औठाछाप हार्डवेयर प्रयोग गर्न अनुमति दिन्छ"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक औठाछाप पत्ता लाग्यो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"औठाछाप प्रशोधन गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"औँठाछाप सेन्सर फोहोर छ। कृपया सफा गरेर फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"औंला निकै छिटो सारियो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"औंला निकै ढिला सारियो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"विक्रेता-निर्दिष्ट अधिग्रहण त्रुटि सन्देश 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"प्रसोधन गर्न असमर्थ। फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"हार्डवेयर उपलब्ध छैन।"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"औँठाछाप भण्डारण गर्न सकिँदैन। कृपया अवस्थित औठाछाप हटाउनुहोस्।"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"औँठाछापको समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"औँठाछापको समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"विक्रेता-निर्दिष्ट त्रुटि सन्देश।"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"समीकरण सेटिङहरू पढ्नुहोस्"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"अनुप्रयोगलाई खाताको लागि सिङ्क सेटिङहरू पढ्न अनुमति दिन्छ। उदाहरणको लागि यसले व्यक्तिहरको अनुप्रयोग खातासँग सिङ्क भएको नभएको निर्धारण गर्न सक्दछ।"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"टगल सिङ्क खुला र बन्द"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM प्रमाणपत्रहरू हटाउन अनुप्रयोगलाई अनुमति दिन्छ। सामान्य अनुप्रयोगहरूको लागि कहिल्यै आवश्यकता पर्दैन।"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"वाहक मेसेजिङ सेवामा आबद्ध हुनुहोस्"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"धारकलाई वाहक मेसेजिङ सेवाको उच्च-स्तरको इन्टरफेसमा आबद्ध हुन अनुमति दिनुहोस्। सामान्य एपहरूको लागि कहिल्यै आवश्यकता पर्दैन।"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियमहरू मिलाउनुहोस्"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रिन लक पासवर्ड र PIN हरूमा अनुमति दिइएको लम्बाइ र वर्णहरूको नियन्त्रण गर्नुहोस्।"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"मोनिटर स्क्रिन-अनलक प्रयत्नहरू"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"प्याकेज स्थापना योग्य छ कि भनेर रुजु गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"एउटा प्याकेज रुजुकर्तामा बाँध्नुहोस्"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"होल्डरलाई प्याकेज प्रमाणितकर्ताहरूको अनुरोधहरू बनाउन अनुमति दिन्छ। सामान्य अनुप्रयोगहरूलाई कहिले पनि आवश्यक नपर्न सक्दछ।"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"उद्देश्य फिल्टर प्रमाणिकरण गर्नुहोस्"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"एउटा उद्देश्य फिल्टर प्रमाणित भएको छ वा छैन भन्ने जाँच्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"उद्देश्य फिल्टर प्रमाणिकरणकर्ता बाँध्नुहोस्"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"होल्डरलाई उद्देश्य फिल्टर प्रमाणिकरणकर्ताहरूका अनुरोध गर्न अनुमति दिन्छ। सामान्य अनुप्रयोगहरूको लागि कहिल्यै आवश्यकता पर्दैन।"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"पहुँच सिरियल पोर्टहरू"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"होल्डरलाई SerialManager API प्रयोग गरेर सिरियल पोर्टहरू पहुँच गर्न अनुमति दिन्छ।"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"विषयसूची प्रदातालाई बाह्य रूपमा पहुँच गर्नुहोस्"</string>
@@ -1550,6 +1590,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"दिन घटाउनुहोस्"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"वर्ष बढाउनुहोस्"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"वर्ष घटाउनुहोस्"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"अघिल्लो महिना"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"अर्को महिना"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"रद्द गर्नुहोस्"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"मेट्नुहोस्"</string>
@@ -1800,11 +1842,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"मिनेट गोलाकार स्लाइडर"</string>
     <string name="select_hours" msgid="6043079511766008245">"घण्टा चयन गर्नुहोस्"</string>
     <string name="select_minutes" msgid="3974345615920336087">"मिनेट चयन गर्नुहोस्"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"दिनहरुको महिना ग्रिड"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"वर्ष सूची"</string>
     <string name="select_day" msgid="7774759604701773332">"महिना र दिन चयन गर्नुहोस्"</string>
     <string name="select_year" msgid="7952052866994196170">"वर्ष चयन गर्नुहोस्"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> चयन गरियो"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> हटाइयो"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"यस पर्दालाई अनपिन गर्न एकै समय फिर्ता र सारांशलाई छोई पक्डिनुहोस्।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 3318bff..64e9cab 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Roamingbanner uit"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Service zoeken"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Bellen via wifi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: niet doorgeschakeld"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> na <xliff:g id="TIME_DELAY">{2}</xliff:g> seconden"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Hiermee kan de app foto\'s en video\'s maken met de camera. Met deze toestemming kan de app de camera altijd gebruiken, zonder uw bevestiging."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"indicatielampje uitschakelen wanneer camera wordt gebruikt"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Staat toe dat een vooraf geïnstalleerde systeemapp het indicatielampje voor cameragebruik uitschakelt."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Hiermee kan een vooraf geïnstalleerde systeemapp systeemgebeurtenissen verzenden naar de cameraservice."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"tablet permanent uitschakelen"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"tv permanent uitschakelen"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"telefoon permanent uitschakelen"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"tv-instelling via CDMA rechtstreeks starten"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"meteen starten met CDMA-telefooninstelling"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Hiermee kan de app starten met CDMA-provisioning. Schadelijke apps kunnen de CDMA-provisioning onnodig starten."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"meldingen over locatie-updates beheren"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Hiermee kan de app locatie-updatemeldingen van de radio in- of uitschakelen. Niet voor gebruik door normale apps."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"toegang tot checkin-eigenschappen"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Hiermee kan de app methoden aanroepen om vingerafdruksjablonen toe te voegen en te verwijderen voor gebruik."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"vingerafdrukhardware gebruiken"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Hiermee kan de app vingerafdrukhardware gebruiken voor verificatie"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Gedeeltelijke vingerafdruk gedetecteerd. Probeer het opnieuw."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Kan vingerafdruk niet verwerken. Probeer het opnieuw."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"De vingerafdruksensor moet worden schoongemaakt. Probeer het daarna opnieuw."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Vinger te snel bewogen. Probeer het opnieuw."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Vinger te langzaam bewogen. Probeer het opnieuw."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Leveranciersspecifieke foutmelding voor acquisitie 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Kan niet verwerken. Probeer het opnieuw."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware niet beschikbaar."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Vingerafdruk kan niet worden opgeslagen. Verwijder een bestaande vingerafdruk."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Time-out bereikt voor vingerafdruk. Probeer het opnieuw."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Time-out bereikt voor vingerafdruk. Probeer het opnieuw."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Leveranciersspecifieke foutmelding"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"synchronisatie-instellingen lezen"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Hiermee kan de app de synchronisatie-instellingen voor een account lezen. Dit kan bijvoorbeeld bepalen of de app Personen wordt gesynchroniseerd met een account."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"synchronisatie in- en uitschakelen"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Toestaan dat een app DRM-certificaten verwijdert. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"binden aan de berichtenservice van een provider"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Hiermee wordt de houder toegestaan te binden aan de berichteninterface van een provider. Nooit vereist voor normale apps."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"De lengte en het aantal tekens beheren die zijn toegestaan in wachtwoorden en pincodes voor schermvergrendeling."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Hiermee kan de app controleren of een pakket kan worden geïnstalleerd."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"koppelen aan pakketcontroleprogramma"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Hiermee kan de houder verzoeken indienen voor pakketcontroles. Nooit vereist voor normale apps."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"intentiefilter verifiëren"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Hiermee kan de app controleren of een intentiefilter is geverifieerd."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"verbinden aan intentiefilterverificatie"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Hiermee kan de houder verzoeken indienen voor verificatie van intentiefilters. Nooit vereist voor normale apps."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"toegang krijgen tot seriële poorten"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"De houder toestaan toegang tot seriële poorten te krijgen met de SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"externe toegang tot inhoudsproviders"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Lagere waarde voor dag"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Hogere waarde voor jaar"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Lagere waarde voor jaar"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Vorige maand"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Volgende maand"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Annuleren"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Ronde schuifregelaar voor minuten"</string>
     <string name="select_hours" msgid="6043079511766008245">"Uren selecteren"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Minuten selecteren"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Maandraster van dagen"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Jaarlijst"</string>
     <string name="select_day" msgid="7774759604701773332">"Maand en dag selecteren"</string>
     <string name="select_year" msgid="7952052866994196170">"Jaar selecteren"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> geselecteerd"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> verwijderd"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Blijf \'Terug\' en \'Overzicht\' tegelijk aanraken om dit scherm los te maken."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 4e56e90..c1ac62b 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -126,8 +126,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Baner roamingu wyłączony"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Wyszukiwanie usługi"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Połączenia przez Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nieprzekierowane"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundach"</string>
@@ -586,6 +597,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Pozwala aplikacji na robienie zdjęć i nagrywanie filmów przy użyciu aparatu. Aplikacja z tym uprawnieniem może użyć aparatu w dowolnym momencie bez Twojego potwierdzenia."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"wyłącz wskaźnik LED transmisji, gdy aparat jest w użyciu"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Zezwala wstępnie zainstalowanej aplikacji systemowej na wyłączenie wskaźnika LED użycia kamery."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Zezwala wstępnie zainstalowanej aplikacji systemowej na wysyłanie zdarzeń systemowych obsługi aparatu."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"trwałe wyłączenie tabletu"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"trwałe wyłączenie telewizora"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"wyłączenie telefonu na stałe"</string>
@@ -634,6 +646,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"bezpośrednie uruchamianie konfiguracji CDMA na telewizorze"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"Bezpośrednio rozpocznij konfigurację telefonu CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Pozwala aplikacji na rozpoczęcie obsługi CDMA. Złośliwe aplikacje mogą bez potrzeby rozpoczynać obsługę CDMA."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"kontrolowanie powiadomień o aktualizacjach lokalizacji"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Pozwala aplikacji na włączanie/wyłączanie powiadomień o aktualizacji lokalizacji pobieranych z radia. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"dostęp do właściwości usługi rezerwacji"</string>
@@ -748,6 +764,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Zezwala aplikacji aktywować metody dodawania i usuwania szablonów odcisków palców."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"używanie czytnika linii papilarnych"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Zezwala aplikacji na używanie czytnika linii papilarnych na potrzeby autoryzacji"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Odcisk palca został odczytany tylko częściowo. Spróbuj ponownie."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nie udało się przetworzyć linii papilarnych. Spróbuj ponownie."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Czytnik linii papilarnych jest zabrudzony. Wyczyść go i spróbuj ponownie."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Palec został uniesiony zbyt szybko. Spróbuj ponownie."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Palec został przesunięty zbyt wolno. Spróbuj ponownie."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Komunikat o błędzie pozyskania specyficzny dla dostawcy 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Nie można przetworzyć. Spróbuj ponownie."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Czytnik jest niedostępny."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Nie można zapisać odcisku palca. Usuń istniejący odcisk palca."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Osiągnięto limit czasu odczytu linii papilarnych. Spróbuj ponownie."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Osiągnięto limit czasu odczytu linii papilarnych. Spróbuj ponownie."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Komunikat o błędzie specyficzny dla dostawcy."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"czytanie ustawień synchronizacji"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Zezwala aplikacji na odczyt ustawień synchronizacji konta. Pozwala to na przykład określić, czy aplikacja Ludzie jest zsynchronizowana z kontem."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"włączanie i wyłączanie synchronizacji"</string>
@@ -824,6 +856,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Zezwala aplikacji na usuwanie certyfikatów DRM. Nie powinno być nigdy potrzebne w zwykłych aplikacjach."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"powiąż z usługą przesyłania wiadomości przez operatora"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Zezwala posiadaczowi na tworzenie powiązania z interfejsem najwyższego poziomu w usłudze przesyłania wiadomości przez operatora. Nie powinno być nigdy potrzebne dla zwykłych aplikacji."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolowanie długości haseł blokady ekranu i kodów PIN oraz dozwolonych w nich znaków."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
@@ -1121,6 +1157,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Pozwala aplikacji na zweryfikowanie, czy pakiet można zainstalować."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"powiązanie z weryfikatorem pakietów"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Pozwala na wysyłanie żądań weryfikacji pakietu. To uprawnienie nie powinno być potrzebne zwykłym aplikacjom."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"weryfikacja filtru intencji"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Zezwala aplikacji na sprawdzenie, czy filtr intencji został zweryfikowany."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"tworzenie powiązania z weryfikacją filtru intencji"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Zezwala na wysyłanie żądań weryfikacji filtrów intencji. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"dostęp do portów szeregowych"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Umożliwia posiadaczowi dostęp do portów szeregowych przy użyciu interfejsu API narzędzia SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"Dostęp do dostawców treści z zewnątrz"</string>
@@ -1560,6 +1600,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Zmień dzień na wcześniejszy"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Zmień rok na późniejszy"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Zmień rok na wcześniejszy"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Poprzedni miesiąc"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Następny miesiąc"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Anuluj"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1812,11 +1854,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Kołowy suwak minut"</string>
     <string name="select_hours" msgid="6043079511766008245">"Wybierz godziny"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Wybierz minuty"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Siatka miesięczna z dniami"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Lista lat"</string>
     <string name="select_day" msgid="7774759604701773332">"Wybierz miesiąc i dzień"</string>
     <string name="select_year" msgid="7952052866994196170">"Wybierz rok"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Wybrałeś <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> usunięte"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (praca)"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Aby odpiąć ten ekran, naciśnij i przytrzymaj jednocześnie Wstecz i Przegląd."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 1ddef71..54bc02a 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Faixa de Roaming desativada"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"A procurar Serviço"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Chamadas Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não reencaminhado"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Permite que a aplicação tire fotografias e grave vídeos com a câmara. Esta autorização permite que a aplicação utilize a câmara sem a sua confirmação em qualquer altura."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"desativar LED indicador de transmissão com a câmara em utilização"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Permite que uma aplicação de sistema pré-instalada desative o LED indicador de utilização da câmara."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Permite que uma aplicação de sistema pré-instalada envie eventos do sistema para o serviço da câmara."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"desativar tablet de forma permanente"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"desativar a TV permanentemente"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"desativar telefone de forma permanente"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"iniciar diretamente a configuração da TV CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar diretamente a configuração do telefone CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Permite que a aplicação inicie a administração CDMA. As aplicações maliciosas podem iniciar a administração CDMA desnecessariamente."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar notificações de actualização de localização"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permite que a aplicação ative/desative as notificações de atualização de localização do rádio. Não se destina a utilização por aplicações normais."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"aceder a propriedades de verificação"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que a aplicação invoque métodos para adicionar e eliminar modelos de impressão digital para utilização."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"utilizar o hardware de impressão digital"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que a aplicação utilize o hardware de impressão digital para autenticação"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Impressão digital detetada. Tente novamente."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Não foi possível processar a impressão digital. Tente novamente."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"O sensor de impressões digitais está sujo. Limpe-o e tente novamente."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"O dedo moveu-se demasiado rápido. Tente novamente."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"O dedo moveu-se demasiado devagar. Tente novamente."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Mensagem de erro de aquisição específica do fornecedor 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Não é possível processar. Tente novamente."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware não disponível."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não é possível armazenar a impressão digital. Remova uma impressão digital existente."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Foi atingido o limite de tempo da impressão digital. Tente novamente."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Foi atingido o limite de tempo da impressão digital. Tente novamente."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Mensagem de erro específica do fornecedor."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler definições de sincronização"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permite que a aplicação leia as definições de sincronização de uma conta. Por exemplo, pode determinar se a aplicação Pessoas está sincronizada com uma conta."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ativar e desativar a sincronização"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permite que uma aplicação remova certificados DRM. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"ligar ao serviço de mensagens de um operador"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permite ao titular ligar à interface de nível superior do serviço de mensagens de um operador. Nunca deve ser necessário para aplicações normais."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controlar o comprimento e os carateres permitidos nos PINs e nas palavras-passe do bloqueio de ecrã."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite que a aplicação verifique se um pacote é instalável."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"vincular a um verificador de pacotes"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite ao titular solicitar verificadores de pacotes. Nunca deverá ser necessário para aplicações normais."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"validar filtro de intenções"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Permite que uma aplicação verifique se um filtro de intenções está ou não validado."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"vincular a um verif. de filtros intenç."</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Permite ao titular solicitar verificadores de filtros de intenções. Nunca deve ser necessário para aplicações normais."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"aceder a portas série"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite ao titular aceder a portas de série através da API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"aceder a fornecedores de conteúdos externamente"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Diminuir dia"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumentar ano"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Diminuir ano"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Mês anterior"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Mês seguinte"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Cancelar"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Controlo de deslize circular dos minutos"</string>
     <string name="select_hours" msgid="6043079511766008245">"Selecionar horas"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Selecionar minutos"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Grelha de dias do mês"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Lista de anos"</string>
     <string name="select_day" msgid="7774759604701773332">"Selecionar mês e dia"</string>
     <string name="select_year" msgid="7952052866994196170">"Selecionar ano"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selecionado"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Para soltar este ecrã, toque sem soltar em Retroceder e Visão geral em simultâneo."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 35ae345..fc3bf6c 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Banner de roaming desativado"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Pesquisando serviço"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Chamadas por Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Permite que o app tire fotos e filme vídeos com a câmera. Esta permissão autoriza o app a usar a câmera a qualquer momento sem sua confirmação."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"desativar a transmissão do LED indicador quando a câmera estiver em uso"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Permite que um app do sistema pré-instalado desative o LED indicador de uso da câmera."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Permite que um app pré-instalado do sistema envie os eventos do sistema de serviço de câmera."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"desativar permanentemente o tablet"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"desativar TV permanentemente"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"desativar permanentemente o telefone"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"iniciar diretamente a configuração CDMA da TV"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar a configuração do telefone CDMA diretamente"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Permite que o app inicie o provisionamento CDMA. Apps maliciosos podem iniciar o provisionamento CDMA de maneira desnecessária."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar as notificações de atualização do local"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permite que o app ative/desative as notificações de atualização de local do rádio. Não deve ser usado em apps normais."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"acessar propriedades de verificação"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que o app execute métodos para adicionar e excluir modelos de impressão digital para uso."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"usar hardware de impressão digital"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que o app use hardware de impressão digital para autenticação."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Impressão digital parcial detectada. Tente novamente."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Não foi possível processar a impressão digital. Tente novamente."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"O sensor de impressão digital está sujo. Limpe-o e tente novamente."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"O dedo foi retirado rápido demais. Tente novamente."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"O movimento do dedo está muito lento. Tente novamente."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Mensagem de erro de aquisição específica de fornecedor 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Não foi possível concluir o processo. Tente novamente."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware indisponível."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Não foi possível armazenar a impressão digital. Remova uma impressão digital já existente."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Mensagem de erro específica de fornecedor."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler as configurações de sincronização"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permite que o app leia as configurações de sincronização de uma conta. Por exemplo, pode determinar se o app People está sincronizado com uma conta."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ativar e desativar sincronização"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permite que um app remova certificados de DRM. Não deve ser necessário para apps comuns."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"vincular a um serviço de mensagens de operadora"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permite que o proprietário use a interface de nível superior de um serviço de mensagens de operadora. Não deve ser necessária para apps comuns."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla o tamanho e os caracteres permitidos nos PINs e nas senhas do bloqueio de tela."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite que o app verifique se um pacote pode ser instalado."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"vincular a um verificador de pacote"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite que o titular solicite verificadores de pacote. Nunca deve ser necessário para apps normais."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verificar filtro de intenção"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Permite que o app verifique se um filtro de intenção foi confirmado ou não."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"usar verificador de filtro de intenção"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Permite que o titular solicite verificadores de filtro de intenção. Nunca é necessário para apps normais."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"acessar portas seriais"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite que o detentor tenha acesso a portas seriais usando a API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"acessar fornec. de conteúdo externamente"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Diminuir dia"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumentar ano"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Diminuir ano"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Mês passado"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Próximo mês"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Cancelar"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Excluir"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Controle deslizante circular dos minutos"</string>
     <string name="select_hours" msgid="6043079511766008245">"Selecione as horas"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Selecione os minutos"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Grade mensal de dias"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Lista de anos"</string>
     <string name="select_day" msgid="7774759604701773332">"Selecione o mês e o dia"</string>
     <string name="select_year" msgid="7952052866994196170">"Selecione o ano"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selecionado"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> excluído"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Para liberar esta tela, toque e mantenha pressionados \"Voltar\" e \"Visão geral\" ao mesmo tempo."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 360b966..648da9a 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -125,8 +125,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Banner roaming dezactivat"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Se caută serviciul"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Apelare prin Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecţionată"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> după <xliff:g id="TIME_DELAY">{2}</xliff:g> (de) secunde"</string>
@@ -585,6 +596,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Permite aplicației să realizeze fotografii și videoclipuri cu camera foto. Cu această permisiune aplicația utilizează camera foto oricând și fără confirmare."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"dezactivează ledul care indică când este utilizată camera foto"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Permite unei aplicații de sistem preinstalate să dezactiveze ledul care indică utilizarea camerei foto."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Permite unei aplicații de sistem preinstalate să trimită evenimentele de sistem către serviciul Cameră foto."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"dezactivarea permanentă a computerului tablet PC"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"dezactivează definitiv televizorul"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"dezactivare permanentă a telefonului"</string>
@@ -633,6 +645,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"pornește direct configurarea televizorului pentru CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"pornire directă a configuraţiei CDMA a telefonului"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Permite aplicației să pornească asigurarea accesului la CDMA. Aplicaţiile rău intenţionate pot să pornească asigurarea accesului la CDMA, fără ca aceasta să fie necesară."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlare notificări de actualizare a locaţiei"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permite aplicației să activeze/dezactiveze notificările privind actualizarea locaţiei primite de la radio. Nu se utilizează de aplicațiile obişnuite."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"accesare proprietăţi checkin"</string>
@@ -747,6 +763,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite aplicației să invoce metode pentru a adăuga și pentru a șterge șabloane de amprentă pentru utilizare."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"folosește hardware-ul pentru amprentă"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite aplicației să folosească hardware pentru amprentă pentru autentificare"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"S-a detectat parțial amprenta. Încercați din nou."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Amprenta nu a putut fi procesată. Încercați din nou."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Senzorul pentru amprente este murdar. Curățați-l și încercați din nou."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Ați mișcat degetul prea repede. Încercați din nou."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Ați mișcat degetul prea încet. Încercați din nou."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Mesaj de eroare 0 specific furnizorului pentru achiziție"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Nu se poate procesa. Încercați din nou."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardware-ul nu este disponibil."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Amprenta nu poate fi stocată. Eliminați o amprentă existentă."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timpul pentru amprentare a expirat. Încercați din nou."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Timpul pentru amprentare a expirat. Încercați din nou."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Mesaj de eroare specific furnizorului."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"citire setări sincronizare"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permite aplicației să citească setările de sincronizare ale unui cont. De exemplu, cu această permisiune aplicația poate determina dacă aplicația Persoane este sincronizată cu un anumit cont."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activează/dezactivează sincronizarea"</string>
@@ -823,6 +855,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permite unei aplicații să elimine certificatele DRM. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"se conectează la un serviciu de mesagerie oferit de operator"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permite aplicației să se conecteze la interfața de nivel superior a unui serviciu de mesagerie oferit de operator. Nu ar trebui să fie niciodată necesară pentru aplicațiile obișnuite."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Stabiliți lungimea și tipul de caractere permise pentru parolele și codurile PIN de blocare a ecranului."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
@@ -1120,6 +1156,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Permite aplicației să verifice dacă un pachet poate fi instalat."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"conectare la un verificator de pachete"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Permite proprietarului să efectueze solicitări pentru verificatori de pachete. Nu ar trebui să fie niciodată necesară pentru aplicațiile obişnuite."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verifică filtrul de intenții"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Permite aplicației să afle dacă filtrul de intenții este verificat sau nu."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"se conectează la verificator de filtre de intenții"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Permite aplicației să facă solicitări pentru verificatorii filtrelor de intenții. Nu ar trebui să fie niciodată necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"acces la porturi seriale"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite posesorului accesul la porturile serial utilizând API-ul SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"accesaţi furniz. de conţin. din exterior"</string>
@@ -1552,6 +1592,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reduceţi valoarea pentru zi"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Creşteţi valoarea pentru an"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reduceţi valoarea pentru an"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Luna trecută"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Luna viitoare"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Anulați"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Ștergeţi"</string>
@@ -1803,11 +1845,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Selector circular pentru minute"</string>
     <string name="select_hours" msgid="6043079511766008245">"Selectați orele"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Selectați minutele"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Afișare pe luni"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Listă de ani"</string>
     <string name="select_day" msgid="7774759604701773332">"Selectați luna și ziua"</string>
     <string name="select_year" msgid="7952052866994196170">"Selectați anul"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selectat"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> a fost șters"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de serviciu"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Pentru a anula fixarea pe ecran, apăsați lung, simultan, pe Înapoi și pe Vizualizare generală."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 5aa3b39..9c4ee2b 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -126,8 +126,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Баннер роуминга выключен"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Поиск службы"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Звонки по Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не переадресовано"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> через <xliff:g id="TIME_DELAY">{2}</xliff:g> с."</string>
@@ -586,6 +597,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Приложение сможет снимать фотографии и видеоролики с помощью камеры в любое время без вашего разрешения."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"Отключать светодиодный индикатор во время использования камеры"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Предустановленное системное приложение сможет отключать светодиодный индикатор использования камеры."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Предустановленное приложение сможет отсылать информацию о системных событиях в службу поддержки камеры."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"Выключение планшета"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"навсегда отключать телевизор"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"Отключение телефона"</string>
@@ -634,6 +646,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"выполнять настройку CDMA на телевизоре"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"Прямой запуск настройки телефона CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Приложение сможет запускать настройку CDMA. Вредоносные программы также смогут делать это без необходимости."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"Управление уведомлениями об обновлении местоположения"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Приложение сможет включать и отключать уведомления об обновлении местоположения на основе данных приемопередачика. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"Доступ к регистрационным данным"</string>
@@ -748,6 +764,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Приложение сможет добавлять и удалять шаблоны отпечатков пальцев."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"использование сканера отпечатков"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Приложение сможет использовать сканер отпечатков пальцев для аутентификации."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Отсканирована только часть пальца. Повторите попытку."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не удалось распознать отпечаток. Повторите попытку."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Очистите сканер и повторите попытку."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Вы слишком быстро убрали палец. Повторите попытку."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Вы слишком долго удерживали палец. Повторите попытку."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Сообщение об ошибке при сканировании отпечатка (0)"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Не удалось распознать отпечаток. Повторите попытку."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Сканер недоступен."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Чтобы сохранить новый отпечаток, удалите существующий."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Превышено время ожидания. Повторите попытку."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Превышено время ожидания. Повторите попытку."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Сообщение об ошибке."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Просмотр настроек синхронизации"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Приложение сможет просматривать настройки синхронизации аккаунта, например определять, включена ли синхронизация для приложения \"Контакты\"."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"Включение/выключение синхронизации"</string>
@@ -824,6 +856,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Удаление сертификатов DRM. Большинству приложений это разрешение не требуется."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"Подключение к службе обмена сообщениями"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Подключение к базовому интерфейсу службы обмена сообщениями, предоставляемой оператором связи. Это разрешение обычно используется только специальными приложениями."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Правила выбора паролей"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролировать длину и символы при вводе пароля и PIN-кода."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Отслеживать попытки снятия блокировки экрана"</string>
@@ -1121,6 +1157,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Приложение сможет проверять возможность установки пакетов."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"Подключение к верификаторам пакетов"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Приложение сможет запрашивать проверку пакетов. Это разрешение не используется обычными приложениями."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"Проверка фильтров намерений"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Приложение сможет узнавать, проверен ли фильтр намерений."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"Подключение к проверке фильтров намерений"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Приложение сможет запрашивать проверку фильтров намерений. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"Доступ к последовательным портам"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Открыть владельцу доступ к последовательным портам с помощью SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"Доступ к контенту без приложения"</string>
@@ -1560,6 +1600,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"На день назад"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"На год вперед"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"На год назад"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Прошлый месяц"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Следующий месяц"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Клавиша ALT"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Отмена"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Клавиша удаления"</string>
@@ -1812,11 +1854,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Выбор минут на циферблате"</string>
     <string name="select_hours" msgid="6043079511766008245">"Выберите часы"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Выберите минуты"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Окно выбора даты"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Меню выбора года"</string>
     <string name="select_day" msgid="7774759604701773332">"Выберите месяц и число"</string>
     <string name="select_year" msgid="7952052866994196170">"Выберите год"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Выбран элемент <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Цифра <xliff:g id="KEY">%1$s</xliff:g> удалена"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Рабочий <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Чтобы открепить экран, нажмите и удерживайте кнопки \"Назад\" и \"Обзор\" одновременно."</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 8a83db9..6c9d4a0 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"රෝමිං බැනරය අක්‍රියයි"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"සේවාව සඳහා සොයමින්"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi ඇමතීම"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ඉදිරියට නොයවන ලදි"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: තත්පර <xliff:g id="TIME_DELAY">{2}</xliff:g> ට පසුව <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"කැමරාවෙන් පින්තූර ගැනීමට සහ වීඩියෝ කිරීමට යෙදුමට අවසර දෙන්න. මෙම අවසරය මඟින් ඔබගේ අනුදැනුමකින් තොරව ඕනෑම වේලාවකදී කැමරාව භාවිතා කිරීමට යෙදුමට අවසර දෙන්න."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"කැමරාව භාවිතයේදී LED දර්ශක සම්ප්‍රේෂණය අබල කරන්න"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"කැමරා භාවිතය පිළිබඳ LED දර්ශකය අක්‍රිය කිරීමට, කලින් පිහිටුවා ඇති පද්ධති යෙදුමට අවසර දෙන්න."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"කැමරා සේවා පද්ධති සිද්ධි යැවීමට, පූර්ව-ස්ථාපිත පද්ධති යෙදුමකට අවසර දෙයි."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"ටැබ්ලටය ස්ථිරවම අබල කිරීම"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"රූපවාහිනිය ස්ථිරවම අබල කරන්න"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"දුරකථනය ස්ථිරව අබල කිරීම"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"කෙළින්ම CDMA රුපවාහිනී ස්ථාපනය ආරම්භ කරන්න"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA දුරකථන පිහිටුම සෘජුව ඇරඹීම"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"යෙදුමට CDMA ප්‍රතිපාදන ආරම්භ කිරීමට ඉඩදෙන්න. අනිෂ්ට යෙදුම් අනවශ්‍ය ලෙස CDMA ප්‍රතිපාදන ආරම්භ කළ හැක."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"ස්ථාන යාවත්කාලීන දැනුම්දීම් පාලනය කරන්න"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"ස්ථානීය යාවත්කාලින දැනුම්දීම් රේඩියෝවෙන් සබල/අබල කිරීමට යෙදුමට අවසර දෙන්න. සාමාන්‍ය යෙදුම්වල භාවිතය සඳහා නොවේ."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"පිරික්සුම් ගුණාංග වෙත ප්‍රවේශය"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ඇඟිලි සලකුණු සැකිලි එකතු කිරීමට සහ ඉවත් කිරීමට අදාළ විධික්‍රම භාවිතය සඳහා මෙම යෙදුමට අවසර දෙයි."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ඇඟිලි සලකුණු දෘඩාංග භාවිතා කරන්න."</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"අනන්‍යතාවය තහවුරු කරගැනීමට ඇඟිලි සලකුණු දෘඩාංග භාවිතා කිරීමට මෙම යෙදුමට ඉඩ දෙන්න."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ඇඟිලි සලකුණ අඩ වශයෙන් අනාවරණය කර ගැනිණි. කරුණාකර නැවත උත්සාහ කරන්න."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ඇඟිලි සලකුණ පිරිසැකසීමට නොහැකි විය. කරුණාකර නැවත උත්සාහ කරන්න."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ඇඟිලි සලකුණු සංවේදකය අපිරිසිදුයි. කරුණාකර පිරිසිදු කර නැවත උත්සාහ කරන්න."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"ඇඟිල්ල වේගයෙන් ගෙනයන ලදි. කරුණාකර නැවත උත්සාහ කරන්න."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"ඇඟිල්ල සෙමින් ගෙන යන ලදී. කරුණාකර නැවත උත්සාහ කරන්න."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"විකුණුම්කරු-විශේෂිත අත්පත්පත් කර ගැනීමේ දෝෂ පණිවිඩය 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"ක්‍රියාවලිය සම්පූර්ණ කිරීමට නොහැක. නැවත උත්සාහ කරන්න."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"දෘඪාංගය ලද නොහැකිය."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ඇඟිලි සලකුණ ගබඩා කළ නොහැක. දැනට පවතින ඇඟිලි සලකුණක් ඉවත් කරන්න."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ඇඟිලි සලකුණු කාල නිමාව ළඟා විය. නැවත උත්සාහ කරන්න."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"ඇඟිලි සලකුණු කාල නිමාව ළඟා විය. නැවත උත්සාහ කරන්න."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"විකුණුම්කරු-විශේෂිත දෝෂ පණිවිඩය."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"සමමුහුර්ත සැකසීම් කියවන්න"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ගිණුම සඳහා සමමුහුර්ත සැකසීම් කියවීමට යෙදුමට අවසර දෙන්න. උදාහරණයක් ලෙස, ගිණුමක් සමඟ පුද්ගල යෙදුම සමමුහුර්ත දැයි මෙයට හඳුනා ගත හැක."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"සමමුහුර්ත කිරීම සක්‍රිය කරන්න සහ අක්‍රිය කරන්න"</string>
@@ -822,6 +854,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"යෙදුමකට DRM  සහතික ඉවත් කිරීමට ඉඩ දේ. සාමාන්‍ය යෙදුම් වලට කිසිදා අවශ්‍ය නොවේ."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"වාහක පණිවිඩ යැවීමේ සේවාවට බදින්න"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"වාහක සේවාව ඉහල මට්ටමේ අතුරු මුහුණතක් වෙත සම්බන්ධ කිරීමට ධාරකයාට අවසර දෙන්න. සාමාන්‍ය යෙදුම්වලට කිසි විටෙක අවශ්‍ය නොවෙයි."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"හඬ අන්තර්ක්‍රියා සේවාව සමග අන්තර්ක්‍රියා කරන්න"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"දැනට සක්‍රිය හඬ අන්තර්ක්‍රියා සේවාව සමග අන්තර්ක්‍රියා කිරීමට හිමිකරුට ඉඩ දෙයි. සාමාන්‍ය යෙදුම් සඳහා කිසිදා අවශ්‍ය නොවිය යුතුය."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"මුරපද නීති සකස් කිරීම"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"තිර අගුලු මුරපද සහ PIN තුළ ඉඩ දෙන දිග සහ අනුලකුණු පාලනය කිරීම."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"තිරය අගුළු ඇරීමේ උත්සාහයන් නිරීක්ෂණය කරන්න"</string>
@@ -1121,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"ස්ථාපිත කොට ඇති පැකේජයක් සත්‍යාපනයට යෙදුමට අවසර දෙන්න."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"පැකේජ සත්‍යාපකයක් වෙත බඳින්න"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"පැකේජ සත්‍යාපක ඉල්ලීම් වලට දරන්නාට ඉඩ ලබා දේ. සාමාන්‍ය යෙදුම් සඳහා කිසිසේත් අවශ්‍ය නොවේ."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"චේතනාන්විත පෙරහන සත්‍යාපනය කරන්න"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"චේතනාන්විත පෙරහනක් සත්‍යාපනය කර තිබේද නැද්ද යන්න පරීක්ෂා කිරීමට යෙදුමට ඉඩ දෙයි."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"චේතනාන්විත පෙරහන් සත්‍යාපනකාරකයක් වෙත බඳින්න"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"චේතනාන්විත පෙරහන් සත්‍යාපනකාරකවල ඉල්ලීම් සිදු කිරීමට දරන්නාට ඉඩ දෙයි. සාමාන්‍ය යෙදුම් සඳහා කිසිදා අවශ්‍ය නොවිය යුතුය."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"ශ්‍රේණිගත පොට ප්‍රවේශ කිරීම"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API භාවිතයෙන් අනුක්‍රම තොට වෙත ප්‍රවේශ වීමට රඳවනයට අවසර දෙන්න."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"බාහිර අන්තර්ගත සැපයුම්කරුවන් වෙත ප්‍රවේශය"</string>
@@ -1546,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"දවස අඩු කරන්න"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"වසර වැඩි කරන්න"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"වසර අඩු කරන්න"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"පෙර මාසය"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"ඊළඟ මාසය"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"අවලංගු කරන්න"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"මකන්න"</string>
@@ -1796,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"මිනිත්තු කවාකාර සර්පනය"</string>
     <string name="select_hours" msgid="6043079511766008245">"පැය තෝරන්න"</string>
     <string name="select_minutes" msgid="3974345615920336087">"මිනිත්තු තෝරන්න"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"දින ජාලයකින් මාසය"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"වසර ලැයිස්තුව"</string>
     <string name="select_day" msgid="7774759604701773332">"මාසය සහ දිනය තෝරන්න"</string>
     <string name="select_year" msgid="7952052866994196170">"වසර තෝරන්න"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> තෝරාගෙන ඇත"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> මකා දමන ලදි"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"මෙම තීරයේ ඇමුණුම ඉවත් කිරීමට, ආපසු සහ දළ විශ්ලේෂණය එකම වේලාවේ ස්පර්ශ කර අල්ලා සිටින්න."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 676ffe2..c43cda2 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -126,8 +126,15 @@
     <string name="roamingText12" msgid="1189071119992726320">"Banner roamingu je vypnutý"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Vyhľadávanie služby"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Volanie cez Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Vypnuté"</string>
+    <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Uprednostniť Wi-Fi"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="5920549484600758786">"Uprednostniť mobilné pripojenie"</string>
+    <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Len Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepresmerované"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> s"</string>
@@ -586,6 +593,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Umožňuje aplikácii fotografovať a nahrávať videá pomocou fotoaparátu. Toto povolenie umožňuje aplikácii používať fotoaparát kedykoľvek a bez vášho potvrdenia."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"Zakázať indikátor LED prenosu pri používaní fotoaparátu"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Umožňuje v predinštalovanej systémovej aplikácii zakázať indikátor LED používania fotoaparátu."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Umožňuje predinštalovanej systémovej aplikácii odosielať systémové udalosti služby fotoaparátu."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"trvalé zakázanie tabletu"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"trvalé zakázanie televízora"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"trvalé vypnutie telefónu"</string>
@@ -634,6 +642,8 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"priame zapnutie nastavenia štandardu CDMA v televízore"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"priamo spustiť nastavenie telefónu CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Umožňuje aplikácii spustiť poskytovanie CDMA. Škodlivé aplikácie môžu spustiť poskytovanie CDMA samovoľne."</string>
+    <string name="permlab_performSimActivation" msgid="1651116521896665009">"spustiť nastavenie SIM karty"</string>
+    <string name="permdesc_performSimActivation" msgid="1778214876348917401">"Povolí aplikácii spracovávať žiadosti o aktiváciu SIM karty. Aplikácia môže aktiváciu vykonať priamo alebo na to môže delegovať na inú aplikáciu."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"ovládanie upozornení na aktualizáciu polohy"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Umožňuje aplikácii povoliť alebo zakázať upozornenia s aktualizáciami polohy z rádia. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"prístup k vlastnostiam nahlásenia"</string>
@@ -748,6 +758,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Umožňuje aplikácii zavolať metódy, ktoré pridávajú a odstraňujú vzory odtlačkov prstov."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"použiť hardvér na snímanie odtlačkov prstov"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Umožňuje aplikácii používať na overenie totožnosti hardvér na snímanie odtlačkov prstov."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Podarilo sa rozpoznať iba časť odtlačku prsta. Skúste to znova."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Odtlačok prsta sa nepodarilo spracovať. Skúste to znova."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Snímač odtlačkov je špinavý. Vyčistite ho a skúste to znova."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Pohli ste prstom príliš rýchlo. Skúste to znova."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Pohli ste prstom príliš pomaly. Skúste to znova."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Chybové hlásenie o akvizícii týkajúcej sa konkrétneho dodávateľa 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Došlo k chybe spracovania. Skúste to znova."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hardvér nie je k dispozícii"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Odtlačok prsta nie je možné uložiť. Odstráňte existujúci odtlačok."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit rozpoznania odtlačku vypršal. Skúste to znova."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Časový limit rozpoznania odtlačku vypršal. Skúste to znova."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Chybové hlásenie týkajúce sa konkrétneho dodávateľa"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čítať nastavenia synchronizácie"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Umožňuje aplikácii čítať nastavenia synchronizácie v účte. Môže napríklad určiť, či je s účtom synchronizovaná aplikácia Ľudia."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"zapnúť alebo vypnúť synchronizáciu"</string>
@@ -824,6 +850,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Umožňuje aplikácii odstraňovať certifikáty DRM. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"viazať sa na službu na odosielanie správ SMS a MMS operátora"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby na odosielanie správ SMS a MMS operátora. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"interagovať so službou hlasovej interakcie"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"Umožňuje držiteľovi interagovať s momentálne aktívnymi službami hlasovej interakcie. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Nastavte dĺžku hesiel na odomknutie obrazovky aj kódov PIN a v nich používané znaky."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovať pokusy o odomknutie obrazovky"</string>
@@ -1121,6 +1149,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Umožňuje aplikácii overiť, či je možné balík nainštalovať."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"naviazať na overovateľa balíka"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Umožňuje držiteľovi podávať žiadosti o overenie balíkov. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"overiť filter intencií"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Umožňuje aplikácii overiť, či bol filter intencií overený."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"viazať na overenie filtra intencií"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Umožňuje držiteľovi podávať žiadosti o overenie filtra intencií. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"prístup k sériovým portom"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Držiteľa oprávňuje na prístup k sériovým portom pomocou rozhrania API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"externý prístup k poskytovateľom obsahu"</string>
@@ -1560,6 +1592,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Ubrať deň"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Pridať rok"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Ubrať rok"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Predchádzajúci mesiac"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Nasledujúci mesiac"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Zrušiť"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Odstrániť"</string>
@@ -1812,11 +1846,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Kruhový posúvač minút"</string>
     <string name="select_hours" msgid="6043079511766008245">"Vyberte hodiny"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Vyberte minúty"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Tabuľka dní v mesiaci"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Zoznam rokov"</string>
     <string name="select_day" msgid="7774759604701773332">"Vyberte mesiac a deň"</string>
     <string name="select_year" msgid="7952052866994196170">"Vyberte rok"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Bola vybratá položka <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Číslo <xliff:g id="KEY">%1$s</xliff:g> bolo odstránené"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Práca – <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Ak chcete uvoľniť túto obrazovku, súčasne klepnite na tlačidlá Späť a Prehľad a podržte ich."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 07d4bb7..93ef764 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -126,8 +126,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Pasica za gostovanje je izklopljena"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Iskanje storitve"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Klicanje prek Wi-Fi-ja"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ni posredovano"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po toliko sekundah: <xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
@@ -586,6 +597,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Aplikaciji omogoča fotografiranje in snemanje videoposnetkov s kamero. S tem dovoljenjem lahko aplikacija kadar koli uporablja kamero brez vaše potrditve."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"onemogoči LED-indikator prenašanja, ko je fotoaparat v uporabi"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Dovoli že nameščeni sistemski aplikaciji, da onemogoči LED-indikator uporabe fotoaparata."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Dovoli vnaprej nameščeni sistemski aplikaciji pošiljanje obvestil sistema storitve fotoaparata."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"trajno onemogočenje tabličnega računalnika"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"trajno onemogočanje televizorja"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"trajno onemogočenje telefona"</string>
@@ -634,6 +646,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"neposreden zagon nastavitve CDMA-ja za televizor"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"neposredni zagon nastavitve telefona CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Aplikaciji omogoča zagon omogočanja uporabe CDMA. Zlonamerne aplikacije lahko po nepotrebnem zaženejo omogočanje uporabe CDMA."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"nadzor obvestil o posodobitvi lokacije"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Aplikaciji dovoljuje omogočanje ali onemogočanje obvestil o posodobitvi lokacije radia. Ni za uporabo z navadnimi aplikacijami."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"dostop do lastnosti sprostitve"</string>
@@ -748,6 +764,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Aplikaciji omogoča sprožanje načinov za dodajanje in brisanje predlog s prstnimi odtisi za uporabo."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"uporaba strojne opreme za prstne odtise"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Aplikaciji omogoča uporabo strojne opreme za prstne odtise za preverjanje pristnosti"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Zaznan delni prstni odtis. Poskusite znova."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Prstnega odtisa ni bilo mogoče obdelati. Poskusite znova."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Tipalo prstnih odtisov je umazano. Očistite ga in poskusite znova."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Prehiter premik prsta. Poskusite znova."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Prepočasen premik prsta. Poskusite znova."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Vendor-specific acquisition error message 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Obdelava ni mogoča. Poskusite znova."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Strojna oprema ni na voljo."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Prstnega odtisa ni mogoče shraniti. Odstranite obstoječi prstni odtis."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Dosežena časovna omejitev za prstni odtis. Poskusite znova."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Dosežena časovna omejitev za prstni odtis. Poskusite znova."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Vendor-specifc error message."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"branje nastavitev sinhronizacije"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Aplikaciji omogoča branje nastavitev sinhronizacije za račun. S tem lahko aplikacija na primer ugotovi, ali je aplikacija Ljudje sinhronizirana z računom."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"vklop in izklop sinhronizacije"</string>
@@ -824,6 +856,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Aplikaciji omogoča odstranjevanje potrdil za upravljanje digitalnih pravic. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"povezovanje z operaterjevo sporočilno storitvijo"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Imetniku omogoča povezovanje z vmesnikom operaterjeve sporočilne storitve najvišje ravni. To naj ne bi bilo nikoli potrebno za navadne aplikacije."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih in kodah PIN za odklepanje zaslona."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string>
@@ -1121,6 +1157,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Aplikaciji omogoča, da preveri, ali je paket mogoče namestiti."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"poveži s preverjanjem paketov"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Imetniku omogoča zahtevanje preverjanja paketov. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"preverjanje filtra namena"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Aplikaciji omogoča, da preveri, ali je filter namena preverjen ali ne."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"povez. s preverjevalnikom filtra namena"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Imetniku omogoča zahtevanje preverjevalnikov filtra namena. Tega se ne sme nikoli uporabiti za navadne aplikacije."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"dostop do serijskih vrat"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Imetniku omogoča, da z API-jem za SerialManager dostopa do serijskih vrat."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"zunanji dostop do ponudnikov vsebine"</string>
@@ -1560,6 +1600,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Zmanjšanje vrednosti za dan"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Povečanje vrednosti za leto"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Zmanjšanje vrednosti za leto"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Prejšnji mesec"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Naslednji mesec"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Tipka Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Prekliči"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Tipka Delete"</string>
@@ -1812,11 +1854,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Okrogli drsnik za minute"</string>
     <string name="select_hours" msgid="6043079511766008245">"Izberite ure"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Izberite minute"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Mesečna mreža dni"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Seznam let"</string>
     <string name="select_day" msgid="7774759604701773332">"Izberite mesec in dan"</string>
     <string name="select_year" msgid="7952052866994196170">"Izberite leto"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Izbrano: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Številka <xliff:g id="KEY">%1$s</xliff:g> je izbrisana"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za delo"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Če želite odpeti ta zaslon, se hkrati dotaknite tipk Nazaj in Pregled ter ju pridržite."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 54da9a4..cd109a1 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -125,8 +125,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Банер роминга је искључен"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Претраживање услуге"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Позивање преко Wi-Fi-ја"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Није прослеђено"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> након <xliff:g id="TIME_DELAY">{2}</xliff:g> секунде(и)"</string>
@@ -585,6 +596,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Дозвољава апликацији да снима слике и видео снимке камером. Ова дозвола омогућава апликацији да у било ком тренутку користи камеру без ваше потврде."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"онемогући пренос LED осветљења индикатора док се камера користи"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Дозвољава унапред инсталираној системској апликацији да онемогући LED осветљење индикатора за коришћење камере."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Дозвољава унапред инсталираној системској апликацији да шаље догађаје система за услугу камере."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"трајно онемогућавање таблета"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"трајно онемогућавање ТВ-а"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"трајно онемогућавање телефона"</string>
@@ -633,6 +645,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"директно покретање CDMA подешавања ТВ-а"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"директно покретање подешавања CDMA телефона"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Дозвољава апликацији да покрене доделу кодираног вишеструког приступа (CDMA). Злонамерне апликације могу да покрећу CDMA без потребе."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"контрола обавештења о ажурирању локације"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Дозвољава апликацији да омогући/онемогући обавештења о ажурирању локација са радија. Не користе је уобичајене апликације."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"приступ својствима провере"</string>
@@ -747,6 +763,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Дозвољава апликацији да активира методе за додавање и брисање шаблона отисака прстију који ће се користити."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"користи хардвер за отиске прстију"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозвољава апликацији да користи хардвер за отиске прстију ради потврде аутентичности"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Откривен је делимични отисак прста. Покушајте поново."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Није успела обрада отиска прста. Покушајте поново."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Сензор за отиске прстију је прљав. Очистите га и покушајте поново."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Превише брзо сте померили прст. Покушајте поново."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Превише споро сте померили прст. Покушајте поново."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Порука о грешци за аквизицију специфична за произвођача 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Обрада није могућа. Покушајте поново."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Хардвер није доступан."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Није могуће сачувати отисак прста. Уклоните неки од постојећих отисака прстију."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Временско ограничење за отисак прста је истекло. Покушајте поново."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Временско ограничење за отисак прста је истекло. Покушајте поново."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Порука о грешци специфична за произвођача."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"читање подешавања синхронизације"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Дозвољава апликацији да чита подешавања синхронизације за налог. На пример, овако може да се утврди да ли је апликација Људи синхронизована са налогом."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"укључивање и искључивање синхронизације"</string>
@@ -823,6 +855,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Дозвољава апликацији да уклања DRM сертификате. Никада не би требало да се користи за обичне апликације."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"повезивање са услугом за размену порука мобилног оператера"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Дозвољава власнику да се повеже са интерфејсом највишег нивоа за услугу за размену порука мобилног оператера. Никада не би требало да буде потребно за стандардне апликације."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролише дужину и знакове дозвољене у лозинкама и PIN-овима за закључавање екрана."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Надгледање покушаја откључавања екрана"</string>
@@ -1120,6 +1156,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Дозвољава апликацији да верификује да ли је пакет могуће инсталирати."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"обавезивање на верификатор пакета"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Омогућава да власник упућује захтеве верификаторима пакета. Уобичајене апликације никада не би требало да је користе."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"верификација intent филтера"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Дозвољава апликацији са провери да ли је intent филтер верификован."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"повезив. са верификатором intent филтера"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Дозвољава власнику да упућује захтеве верификаторима intent филтера. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"приступ серијским портовима"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Омогућава власнику да приступи серијским портовима помоћу SerialManager API-ја."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"приступ добављачима садржаја споља"</string>
@@ -1552,6 +1592,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Смањивање дана"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Повећавање године"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Смањивање године"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Претходни месец"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Следећи месец"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Откажи"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Избриши"</string>
@@ -1803,11 +1845,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Кружни клизач за минуте"</string>
     <string name="select_hours" msgid="6043079511766008245">"Изаберите сате"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Изаберите минуте"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Приказ дана у месецу у виду мреже"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Листа година"</string>
     <string name="select_day" msgid="7774759604701773332">"Изаберите месец и дан"</string>
     <string name="select_year" msgid="7952052866994196170">"Изаберите годину"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Изабрали сте <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Избрисали сте <xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> на послу"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Да бисте откачили овај екран, истовремено додирните и задржите Назад и Преглед."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index dd8a883..3f028ac 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Roamingbanner av"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Söker efter tjänst"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-samtal"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Vidarebefordras inte"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> efter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Tillåter att appen tar bilder och spelar in videor med kameran. Med den här behörigheten tillåts appen att använda kameran när som helst utan ditt godkännande."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"inaktivera LED-sändningsindikator när kameran används"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Tillåter att en förinstallerad systemapp inaktiverar LED-indikatorn för kameranvändning."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Tillåter att en förinstallerad systemapp skickar systemmeddelanden till kameratjänsten."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"inaktivera surfplattan permanent"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"inaktivera tv:n permanent"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"inaktivera telefonen permanent"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"starta konfiguration av CDMA-tv direkt"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"starta CDMA-telefoninställningar direkt"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Tillåter att appen startar CDMA-anslutning. Skadliga appar kan starta CDMA-anslutningar i onödan."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"styra meddelanden för platsuppdatering"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Tillåter att appen aktiverar/inaktiverar meddelanden om platsuppdateringar från radion. Används inte av vanliga appar."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"få åtkomst till incheckningsegenskaper"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Tillåter att appen anropar metoder för att lägga till och radera fingeravtrycksmallar."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"använda maskinvara för fingeravtryck"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Tillåter att appen använder maskinvara för fingeravtryck vid autentisering"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Ofullständigt fingeravtryck. Försök igen."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Det gick inte att bearbeta fingeravtrycket. Försök igen."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingeravtryckssensorn är smutsig. Rengör den och försök igen."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Du flyttade fingret för snabbt. Försök igen."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Du flyttade fingret för långsamt. Försök igen."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Leverantörsspecifikt felmeddelande om förvärv 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Det går inte att bearbeta fingeravtrycket. Försök igen."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Maskinvaran är inte tillgänglig."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingeravtrycket kan inte lagras. Ta bort ett befintligt fingeravtryck."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsgränsen för fingeravtrycket har uppnåtts. Försök igen."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Tidsgränsen för fingeravtrycket har uppnåtts. Försök igen."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Leverantörsspecifikt felmeddelande"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"läsa synkroniseringsinställningar"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Tillåter att appen läser synkroniseringsinställningarna för ett konto. Detta kan användas till exempel för att avgöra om appen Personer är synkroniserad med ett konto."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"aktivera/inaktivera synkronisering"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Tillåter ett program att ta bort DRM-certifikat. Behövs inte för vanliga appar."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"binda till en operatörs meddelandetjänst"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en operatörs meddelandetjänst. Ska inte behövas för vanliga appar."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Styr tillåten längd och tillåtna tecken i lösenord och pinkoder för skärmlåset."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Tillåter att appen kontrollerar om ett paket går att installera."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"binda till en paketverifierare"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Tillåter att innehavaren skickar förfrågningar till paketverifierare. Det ska inte behövas för vanliga appar."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"verifiera intent-filter"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Tillåter att appen kontrollerar om ett intent-filter har verifierats eller inte."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"binda till en intent-filterverifierare"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Tillåter att innehavaren skickar begäranden till intent-filterverifierare. Behövs inte för vanliga appar."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"åtkomst till serieportar"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Innebär att innehavaren får åtkomst till serieportar med programmeringsgränssnittet för SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"komma åt innehållsleverantörer externt"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Minska dagar"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Öka år"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Minska år"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Föregående månad"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Nästa månad"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Avbryt"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Cirkelreglage för minuter"</string>
     <string name="select_hours" msgid="6043079511766008245">"Välj timmar"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Välj minuter"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Rutnät för månad"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Lista över år"</string>
     <string name="select_day" msgid="7774759604701773332">"Välj månad och dag"</string>
     <string name="select_year" msgid="7952052866994196170">"Välj år"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> har markerats"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> har tagits bort"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> för arbetet"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Om du vill lossa skärmen trycker du länge på Tillbaka och Översikt samtidigt."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index cfa56de..8532fbd 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Zima Bango la Uzururaji"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Inatafuta Huduma"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Upigaji Simu kwa Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Haijatumiwa mwingine"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> baada ya sekunde <xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Inaruhusu programu kupiga picha na video kwa kamera. Kibali hiki kinaruhusu programu kutumia kamera kwa wakati wowote bila uthibitisho wako."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"zima LED ya kisambaza kiashirio wakati kamera inatumika"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Huruhusu mfumo wa programu iliyosakinishwa awali kuzima kamera isitumie kiashirio cha LED."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Huruhusu mfumo wa programu iliyosakinishwa awali kutuma kwenye kamera matukio ya mfumo wa huduma."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"zima kompyuta ndogo kabisa"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"zima runinga kabisa"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"simu iliyolemazwa kabisa"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"anzisha usanidi wa runinga ya CDMA moja kwa moja"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"anzisha moja kwa moja usanidi wa simu ya CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Inaruhusu programu kuanza ugawaji wa CDMA. Programu hasidi zinaweza anza ugawaji wa CDMA usio wa lazima."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"dhibiti arifa za usasishaji mahali"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Huruhusu kuwasha au kuzima arifa za masasisho ya mahali kutoka kwa redio. Sio ya kutumiwa kwenye programu za kawaida."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"fikia mipangilio ya ukaguzi"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Huruhusu programu kuomba njia za kuongeza na kufuta violezo vya kitambulisho kwa matumizi."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"tumia maunzi ya kitambulisho"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Huruhusu programu kutumia maunzi ya kitambulisho kwa uthibitisho"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Kihisi kimegundua sehemu ya kitambulisho. Tafadhali jaribu tena."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Haikuweza kuchakata kitambulisho. Tafadhali jaribu tena."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Kihisi kitambulisho ni kichafu. Tafadhali kisafishe na ujaribu tena."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Ulisogeza kidole kwa kasi mno. Tafadhali jaribu tena."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Ulisogeza kidole pole pole mno. Tafadhali jaribu tena."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Ujumbe maalum kwa muuzaji kuhusu hitilafu ya uletaji wa kitambulisho 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Haikuweza kuchakata. Jaribu tena."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Maunzi hayapatikani."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Kitambulisho hakiwezi kuhifadhiwa. Tafadhali ondoa kitambulisho kilichopo."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Muda wa kitambulisho umekwisha. Jaribu tena."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Muda wa kitambulisho umekwisha. Jaribu tena."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Ujumbe maalum kwa muuzaji kuhusu hitilafu."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"kusoma mipangilio ya usawazishaji"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Inaruhusu programu kusoma mipangilio ya upatanishi wa akaunti. Kwa mfano, huku kunaweza kuamua kama programu ya Watu imepatanishwa na akaunti."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"kuwasha na kuzima usawazishaji"</string>
@@ -822,6 +854,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Huruhusu programu kuondoa vyeti vya DRM. Haipaswi kuhitajika kwa programu za kawaida kamwe."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"Shurutisha kwa huduma ya ujumbe ya mtoa huduma"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Huruhusu kishikiliaji kushurutisha kwa kiolesura cha hali ya juu cha huduma ya ujumbe ya mtoa huduma. Haipaswi kuhitajika kwa programu za kawaida."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"tumia huduma ya muingiliano wa sauti"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"Humruhusu mmiliki kutumia huduma ya muingiliano wa sauti inayotumika kwa sasa. Isihitajike kamwe kwa programu za kawaida."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Kuweka kanuni za nenosiri"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Dhibiti urefu na maandishi yanayokubalika katika nenosiri la kufunga skrini na PIN."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Kuhesabu mara ambazo skrini inajaribu kufunguliwa"</string>
@@ -1119,6 +1153,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Inaruhusu programu kuthibitisha kuwa furushi linaweza kusakinishwa."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"Funga kwa kithibitishaji cha furushi"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Inaruhusu mmiliki kutuma maombi ya vibainishi furushi. Kamwe hazitahitajika kwa programu za kawaida."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"thibitisha kichujio cha kutoa maagizo"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Inaruhusu programu kukagua ikiwa kuchujio cha kutoa maagizo kimethibitishwa au bado."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"funga kwenye kithibitishaji cha kichujio cha kutoa maagizo."</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Inaruhusu mmiliki kutuma maombi ya vithibitishaji vya kichujio cha kutoa maagizo. Haviwezi kuhitajika katika programu za kawaida."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"kituo tambulishi cha ufikivu"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Inaruhusu mmiliki kufikia vituo tambulishi kwa kutumia KisimamiziTambulishi cha API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"fikia watoa huduma nje"</string>
@@ -1544,6 +1582,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Punguza siku"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Ongeza mwaka"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Punguza mwaka"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Mwezi uliopita"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Mwezi ujao"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Ghairi"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Futa"</string>
@@ -1794,11 +1834,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Kitelezi cha mviringo wa dakika"</string>
     <string name="select_hours" msgid="6043079511766008245">"Chagua saa"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Chagua dakika"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Gridi ya mwezi ya siku"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Orodha ya miaka"</string>
     <string name="select_day" msgid="7774759604701773332">"Chagua mwezi na siku"</string>
     <string name="select_year" msgid="7952052866994196170">"Chagua mwaka"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> kimechaguliwa"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> kimefutwa"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Ya kazini <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Ili ubanue skrini hii, gusa na ushikilie Nyuma na Muhtasari kwa wakati mmoja."</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 0e5bf3c..c6bea48 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"ரோமிங் பேனர் முடக்கப்பட்டது"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"சேவையைத் தேடுகிறது"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"வைஃபை அழைப்பு"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: பகிரப்படவில்லை"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> வினாடிகளுக்குப் பிறகு <xliff:g id="DIALING_NUMBER">{1}</xliff:g> ஐப் பகிர்"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"கேமரா மூலமாகப் படங்களையும், வீடியோக்களையும் எடுக்க பயன்பாட்டை அனுமதிக்கிறது. உங்கள் உறுதிப்படுத்தல் இன்றி கேமராவை எந்நேரத்திலும் பயன்படுத்தப் பயன்பாட்டை இது அனுமதிக்கிறது."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"கேமரா பயன்பாட்டில் இருக்கும்போது டிரான்ஸ்மிட் இன்டிகேட்டர் LED ஐ முடக்குதல்"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"இன்டிகேட்டர் LED ஐ கேமரா பயன்படுத்துவதை முடக்க, முன்நிறுவப்பட்ட அமைப்பு பயன்பாட்டை அனுமதிக்கிறது."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"முறைமை நிகழ்வுகள் பற்றிய கேமரா சேவை அறிவிப்புகளை அனுப்ப, முன்நிறுவப்பட்ட முறைமை பயன்பாட்டை அனுமதிக்கும்."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"டேப்லெட்டை நிரந்தரமாக முடக்குதல்"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"டிவியை நிரந்தரமாக முடக்குதல்"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"தொலைபேசியை நிரந்தரமாக முடக்குதல்"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA TV அமைவிலிருந்து நேரடியாக தொடங்குதல்"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA தொலைபேசி அமைவை நேரடியாகத் தொடங்குதல்"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"CDMA வழங்கலைத் தொடங்க, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் தேவையில்லாமல் CDMA வழங்கலைத் தொடங்கலாம்."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"இட புதுப்பிப்பு அறிவிப்புகளைக் கட்டுப்படுத்துதல்"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"ரேடியோவிலிருந்து இருப்பிட புதுப்பிப்பு அறிவிப்புகளை இயக்க/முடக்க பயன்பாட்டை அனுமதிக்கிறது. சாதாரண பயன்பாடுகள் பயன்படுத்தாது."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"செக்இன் பண்புகளின் அணுகல்"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"பயன்படுத்துவதற்காக, கைரேகை டெம்ப்ளேட்களைச் சேர்க்க மற்றும் நீக்குவதற்கான செயல்முறைகளை இயக்குவதற்குப் பயன்பாட்டை அனுமதிக்கும்."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"கைரேகை வன்பொருளைப் பயன்படுத்து"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"அங்கீகரிப்பதற்கு, கைரேகை வன்பொருளைப் பயன்படுத்த, பயன்பாட்டை அனுமதிக்கும்"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"கைரேகையை ஓரளவுதான் கண்டறிய முடிந்தது. மீண்டும் முயலவும்."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"கைரேகையைச் செயலாக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"கைரேகை உணர்வியில் தூசி உள்ளது. சுத்தம் செய்து, முயலவும்."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"விரலை வேகமாக எடுத்துவிட்டீர்கள். மீண்டும் முயலவும்."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"விரலை மெதுவாக எடுத்துவிட்டீர்கள். மீண்டும் முயலவும்."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"விற்பனையாளர் சார்ந்த பெறுதல் தொடர்பான பிழைச் செய்தி 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"செயல்படுத்த முடியவில்லை. மீண்டும் முயலவும்."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"வன்பொருள் இல்லை."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"கைரேகையைச் சேமிக்க முடியவில்லை. ஏற்கனவே உள்ள கைரேகையை அகற்றவும்."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"கைரேகைக்கான நேரம் முடிந்தது. மீண்டும் முயலவும்."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"கைரேகைக்கான நேரம் முடிந்தது. மீண்டும் முயலவும்."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"விற்பனையாளர் சார்ந்த பிழைச் செய்தி."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ஒத்திசைவு அமைப்புகளைப் படித்தல்"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"கணக்கிற்கான ஒத்திசைவு அமைப்புகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது. எடுத்துக்காட்டாக, பீப்பிள் பயன்பாடு கணக்குடன் ஒத்திசைக்கப்பட்டுள்ளதா என்பதை இது தீர்மானிக்கலாம்."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ஒத்திசைவை இயக்குவதையும், முடக்குவதையும் மாற்றுதல்"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM சான்றிதழ்களை அகற்ற, பயன்பாட்டை அனுமதிக்கிறது. சாதாரண பயன்பாடுகளுக்கு எப்போதுமே தேவைப்படாது."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"மொபைல் நிறுவனச் செய்தியிடல் சேவையுடன் இணைத்தல்"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"மொபைல் நிறுவனச் செய்தியிடல் சேவையின் உயர்-நிலை இடைமுகத்துடன் ஹோல்டரை இணைக்க அனுமதிக்கும். இயல்பான பயன்பாடுகளுக்குத் தேவைப்படாது."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"கடவுச்சொல் விதிகளை அமைக்கவும்"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"திரைப் பூட்டின் கடவுச்சொற்கள் மற்றும் பின்களில் அனுமதிக்கப்படும் நீளத்தையும் எழுத்துக்குறிகளையும் கட்டுப்படுத்தும்."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"திரைத் திறக்க முயற்சிகளைக் கண்காணித்தல்"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"பேக்கேஜ் நிறுவுவதற்கு ஏற்றதா என்பதைச் சரிபார்க்க, பயன்பாட்டை அனுமதிக்கிறது."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"தொகுப்பு சரிபார்ப்பானுடன் இணைத்தல்"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"தொகுப்பைச் சரிபார்ப்பிற்கான கோரிக்கைகளை உருவாக்க, ஹோல்டரை அனுமதிக்கிறது. சாதாரண பயன்பாடுகளுக்கு எப்போதுமே தேவைப்படாது."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"இன்டென்ட் வடிப்பானைச் சரிபார்த்தல்"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"இன்டென்ட் வடிப்பான் சரிபார்க்கப்பட்டதா அல்லது இல்லையா என்பதைச் சோதிக்க, பயன்பாட்டை அனுமதிக்கும்."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"இன்டென்ட் வடிப்பான் சரிபார்ப்பியுடன் இணைத்தல்"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"இன்டென்ட் வடிப்பான் சரிபார்ப்பிகளின் கோரிக்கைகளை உருவாக்க ஹோல்டரை அனுமதிக்கும். சாதாரணப் பயன்பாடுகளுக்கு எப்போதுமே தேவைப்படாது."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"தொடர் போர்ட்களின் அணுகல்"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API ஐப் பயன்படுத்தி தொடர் போர்ட்களை அணுக ஹோல்டரை அனுமதிக்கிறது."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"வெளிப்புறமாக வழங்கப்படும் உள்ளடக்கத்திற்கான அணுகல்"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"நாளினைக் குறை"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"வருடத்தை அதிகரி"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"வருடத்தைக் குறை"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"முந்தைய மாதம்"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"அடுத்த மாதம்"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"ரத்துசெய்"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"நீக்கு"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"நிமிடங்களுக்கான வட்டவடிவ ஸ்லைடர்"</string>
     <string name="select_hours" msgid="6043079511766008245">"மணிநேரத்தைத் தேர்ந்தெடுக்கவும்"</string>
     <string name="select_minutes" msgid="3974345615920336087">"நிமிடத்தைத் தேர்ந்தெடுக்கவும்"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"நாட்களின் மாதக் கட்டம்"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"ஆண்டு பட்டியல்"</string>
     <string name="select_day" msgid="7774759604701773332">"மாதம் மற்றும் தேதியைத் தேர்ந்தெடுக்கவும்"</string>
     <string name="select_year" msgid="7952052866994196170">"ஆண்டைத் தேர்ந்தெடுக்கவும்"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> தேர்ந்தெடுக்கப்பட்டது"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> நீக்கப்பட்டது"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"பணியிடம் <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"இந்தத் திரையை விலக்க, பின் மற்றும் மேலோட்டப் பார்வையை ஒரே நேரத்தில் தொட்டுப் பிடித்திருக்கவும்."</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 4684adf..26e018f 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"రోమింగ్ బ్యానర్ ఆఫ్‌లో ఉంది"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"సేవ కోసం శోధిస్తోంది"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi కాలింగ్"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వార్డ్ చేయబడలేదు"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> సెకన్ల తర్వాత <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"కెమెరాతో చిత్రాలు మరియు వీడియోలను తీయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి మీ నిర్ధారణ లేకుండానే ఎప్పుడైనా కెమెరాను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"కెమెరా ఉపయోగంలో ఉన్నప్పుడు ప్రసరణ సూచీ LEDని నిలిపివేయడం"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"కెమెరా వినియోగ సూచీ LEDని నిలిపివేయడానికి ముందే ఇన్‌స్టాల్ చేయబడిన సిస్టమ్ అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"కెమెరా సేవకి సిస్టమ్ ఈవెంట్‌లను పంపడానికి ముందే ఇన్‌స్టాల్ చేసిన సిస్టమ్ అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"టాబ్లెట్‌ను శాశ్వతంగా నిలిపివేయడం"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"టీవీని శాశ్వతంగా నిలిపివేయడం"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ఫోన్‌ను శాశ్వతంగా నిలిపివేయడం"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA టీవీ సెటప్‌ను నేరుగా ప్రారంభించడం"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA ఫోన్ సెటప్‌ను నేరుగా ప్రారంభించడం"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"CDMA కేటాయింపును ప్రారంభించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన అనువర్తనాలు CDMA కేటాయింపును అనవసరంగా ప్రారంభించవచ్చు."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"స్థాన నవీకరణ నోటిఫికేషన్‌లను నియంత్రించడం"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"రేడియో నుండి స్థానం నవీకరణ నోటిఫికేషన్‌లను ప్రారంభించడానికి/నిలిపివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సాధారణ అనువర్తనాల ద్వారా ఉపయోగించడానికి ఉద్దేశించినది కాదు."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"ప్రవేశ లక్షణాలను ప్రాప్యత చేయడం"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"వినియోగం కోసం వేలిముద్ర టెంప్లేట్‌లను జోడించే మరియు తొలగించే పద్ధతులను అమలు చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"వేలిముద్ర హార్డ్‌వేర్‌ని ఉపయోగించడానికి అనుమతి"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ప్రామాణీకరణ కోసం వేలిముద్ర హార్డ్‌వేర్‌ను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"పాక్షిక వేలిముద్ర గుర్తించబడింది. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"వేలిముద్రను ప్రాసెస్ చేయడం సాధ్యపడలేదు. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"వేలిముద్ర సెన్సార్ మురికిగా ఉంది. దయచేసి శుభ్రపరిచి, మళ్లీ ప్రయత్నించండి."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"వేలిని చాలా తొందరగా కదిలించారు. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"వేలిని చాలా నిదానంగా కదిలించారు. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"విక్రేత-నిర్దిష్ట సేకరణ లోప సందేశం 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"ప్రాసెస్ చేయడం సాధ్యపడలేదు. మళ్లీ ప్రయత్నించండి."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"హార్డ్‌వేర్ అందుబాటులో లేదు."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"వేలిముద్రను నిల్వ చేయడం సాధ్యపడదు. దయచేసి ఇప్పటికే ఉన్న వేలిముద్రను తీసివేయండి."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"వేలిముద్ర గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"వేలిముద్ర గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"విక్రేత-నిర్దిష్ట లోప సందేశం."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"సమకాలీకరణ సెట్టింగ్‌లను చదవడం"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ఖాతా యొక్క సమకాలీకరణ సెట్టింగ్‌లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఉదాహరణకు, వ్యక్తుల అనువర్తనం ఖాతాతో సమకాలీకరించబడాలా లేదా అనే విషయాన్ని ఇది నిశ్చయించవచ్చు."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"సమకాలీకరణను ఆన్ మరియు ఆఫ్‌కు టోగుల్ చేయడం"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM ప్రమాణపత్రాలను తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"క్యారియర్ సందేశ సేవకు అనుబంధించడం"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"క్యారియర్ సందేశ సేవ యొక్క అగ్ర-స్థాయి ఇంటర్‌ఫేస్‌కు అనుబంధించడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"పాస్‌వర్డ్ నియమాలను సెట్ చేయండి"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"స్క్రీన్ లాక్ పాస్‌వర్డ్‌లు మరియు PINల్లో అనుమతించబడిన పొడవు మరియు అక్షరాలను నియంత్రిస్తుంది."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"స్క్రీన్-అన్‌లాక్ ప్రయత్నాలను పర్యవేక్షించండి"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"ప్యాకేజీ ఇన్‌స్టాల్ చేయవచ్చని ధృవీకరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"ప్యాకేజీ తనిఖీదారుకు అనుబంధించడం"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"ప్యాకేజీ తనిఖీదారుల యొక్క అభ్యర్థనలు చేయడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"ఉద్దేశిత ఫిల్టర్‌ను ధృవీకరించడం"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"ఉద్దేశిత ఫిల్టర్ ధృవీకరించబడిందో లేదో తనిఖీ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"ఉద్దేశిత ఫిల్టర్ వెరిఫైయర్‌కి నిర్బంధించడం"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"ఉద్దేశిత ఫిల్టర్ వెరిఫైయర్‌ల అభ్యర్థనలు చేయడానికి హోల్డర్‌ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"శ్రేణి పోర్ట్‌లను ప్రాప్యత చేయడం"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"శ్రేణి నిర్వాహికి APIని ఉపయోగించి శ్రేణి పోర్ట్‌లను ప్రాప్యత చేయడానికి హోల్డర్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"కంటెంట్ ప్రదాతలను బాహ్యంగా ప్రాప్యత చేయడం"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"రోజును తగ్గించండి"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"సంవత్సరాన్ని పెంచండి"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"సంవత్సరాన్ని తగ్గించండి"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"మునుపటి నెల"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"తదుపరి నెల"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"రద్దు చేయి"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"తొలగించు"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"నిమిషాల వృత్తాకార స్లయిడర్"</string>
     <string name="select_hours" msgid="6043079511766008245">"గంటలను ఎంచుకోండి"</string>
     <string name="select_minutes" msgid="3974345615920336087">"నిమిషాలను ఎంచుకోండి"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"రోజుల యొక్క నెల గ్రిడ్"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"సంవత్సర జాబితా"</string>
     <string name="select_day" msgid="7774759604701773332">"నెల మరియు రోజును ఎంచుకోండి"</string>
     <string name="select_year" msgid="7952052866994196170">"సంవత్సరాన్ని ఎంచుకోండి"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ఎంచుకోబడింది"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> తొలగించబడింది"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"ఈ స్క్రీన్‌ను అన్‌పిన్ చేయడానికి, వెనుకకు మరియు అవలోకనం బటన్‌లను ఒకేసారి నొక్కి, ఉంచండి."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 39be8c7..b5bbc83 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"ปิดโรมมิ่งแบนเนอร์"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"กำลังค้นหาบริการ"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"การโทรผ่าน Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ไม่ได้โอนสาย"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> หลังผ่านไป <xliff:g id="TIME_DELAY">{2}</xliff:g> วินาที"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"อนุญาตให้แอปพลิเคชันถ่ายภาพและวิดีโอด้วยกล้องถ่ายรูปนี้ การอนุญาตนี้จะทำให้แอปพลิเคชันสามารถใช้กล้องถ่ายรูปได้ทุกเมื่อโดยไม่ต้องรอการยืนยันจากคุณ"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"ปิดไฟสัญญาณ LED เมื่อใช้งานกล้อง"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"อนุญาตให้แอปพลิเคชันระบบที่ติดตั้งล่วงหน้าปิดไฟสัญญาณ LED ของกล้อง"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"อนุญาตให้แอปพลิเคชันระบบที่ติดตั้งล่วงหน้าส่งกิจกรรมระบบไปยังบริการของกล้อง"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"ปิดการใช้งานแท็บเล็ตอย่างถาวร"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"ปิดใช้ทีวีถาวร"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ปิดการใช้งานโทรศัพท์ถาวร"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"เริ่มตั้งค่าทีวี CDMA โดยตรง"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"เริ่มการตั้งค่าโทรศัพท์ CDMA โดยตรง"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"อนุญาตให้แอปพลิเคชันเริ่มการให้บริการ CDMA แอปพลิเคชันที่เป็นอันตรายอาจเริ่มการให้บริการ CDMA โดยไม่จำเป็นได้"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"ควบคุมการแจ้งเตือนการอัปเดตตำแหน่ง"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"อนุญาตให้แอปพลิเคชันเปิด/ปิดใช้งานการแจ้งเตือนการอัปเดตตำแหน่งจากวิทยุ ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"เข้าถึงคุณสมบัติการเช็คอิน"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"อนุญาตให้แอปเรียกใช้วิธีการเพื่อเพิ่มและลบเทมเพลตลายนิ้วมือสำหรับการใช้งาน"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ใช้ฮาร์ดแวร์ลายนิ้วมือ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"อนุญาตให้แอปใช้ฮาร์ดแวร์ลายนิ้วมือเพื่อตรวจสอบสิทธิ์"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ตรวจพบลายนิ้วมือเพียงบางส่วน โปรดลองอีกครั้ง"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ไม่สามารถประมวลผลลายนิ้วมือได้ โปรดลองอีกครั้ง"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"เซ็นเซอร์ลายนิ้วมือไม่สะอาด โปรดทำความสะอาดและลองอีกครั้ง"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"เคลื่อนนิ้วเร็วเกินไป โปรดลองอีกครั้ง"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"เคลื่อนนิ้วช้าเกินไป โปรดลองอีกครั้ง"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"ข้อความแสดงข้อผิดพลาดการกระทำเฉพาะผู้ขาย 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"ไม่สามารถดำเนินการได้ โปรดลองอีกครั้ง"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"ฮาร์ดแวร์ไม่พร้อมใช้งาน"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ไม่สามารถเก็บลายนิ้วมือได้ โปรดนำลายนิ้วมือที่มีอยู่ออก"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"หมดเวลาใช้ลายนิ้วมือแล้ว โปรดลองอีกครั้ง"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"หมดเวลาใช้ลายนิ้วมือแล้ว โปรดลองอีกครั้ง"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"ข้อความแสดงข้อผิดพลาดเฉพาะผู้ขาย"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"อ่านการตั้งค่าการซิงค์แล้ว"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"อนุญาตให้แอปพลิเคชันอ่านการตั้งค่าการซิงค์ของบัญชี ตัวอย่างเช่น การอนุญาตนี้สามารถระบุได้ว่าแอปพลิเคชัน People ซิงค์กับบัญชีหรือไม่"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"สลับระหว่างเปิดและปิดการซิงค์"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"อนุญาตให้แอปพลิเคชันนำใบรับรอง DRM ออก แอปทั่วไปไม่จำเป็นต้องใช้"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"เชื่อมโยงกับบริการรับส่งข้อความของผู้ให้บริการ"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"อนุญาตให้แอปพลิเคชันเชื่อมโยงกับอินเทอร์เฟซระดับบนสุดของบริการรับส่งข้อความของผู้ให้บริการ ไม่ควรใช้สำหรับแอปธรรมดาทั่วไป"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ควบคุมความยาวและอักขระที่สามารถใช้ในรหัสผ่านของการล็อกหน้าจอและ PIN"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"อนุญาตให้แอปพลิเคชันยืนยันว่าแพ็กเกจสามารถติดตั้งได้หรือไม่"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"เชื่อมโยงกับการยืนยันแพ็กเกจ"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"อนุญาตให้ผู้ใช้ส่งคำขอให้มีการยืนยันแพ็กเกจ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"ยืนยันตัวกรองความตั้งใจ"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"อนุญาตให้แอปตรวจสอบว่ามีการยืนยันตัวกรองความตั้งใจหรือไม่"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"เชื่อมโยงกับการยืนยันตัวกรองความตั้งใจ"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"อนุญาตให้แอปส่งคำขอการยืนยันตัวกรองความตั้งใจ แอปทั่วไปไม่จำเป็นต้องใช้"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"เข้าถึงพอร์ตอนุกรม"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"อนุญาตให้ผู้ถือสามารถเข้าถึงพอร์ตอนุกรมโดยใช้ SerialManager API"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"เข้าถึงผู้ให้บริการเนื้อหาจากภายนอก"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ลดวัน"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"เพิ่มปี"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ลดปี"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"เดือนที่แล้ว"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"เดือนหน้า"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"ยกเลิก"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ลบ"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"ตัวเลื่อนหมุนระบุนาที"</string>
     <string name="select_hours" msgid="6043079511766008245">"เลือกชั่วโมง"</string>
     <string name="select_minutes" msgid="3974345615920336087">"เลือกนาที"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"ตารางเดือนของวัน"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"รายการปี"</string>
     <string name="select_day" msgid="7774759604701773332">"เลือกเดือนและวัน"</string>
     <string name="select_year" msgid="7952052866994196170">"เลือกปี"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"เลือก <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"ลบ <xliff:g id="KEY">%1$s</xliff:g> แล้ว"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g>ที่ทำงาน"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"หากต้องการเลิกตรึงหน้าจอนี้ แตะ \"กลับ\" และ \"ภาพรวม\" ค้างไว้พร้อมกัน"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 95a1480..230d9fd 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Naka-off ang Banner ng Roaming"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Naghahanap ng Serbisyo"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Pagtawag sa pamamagitan ng Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Hindi naipasa"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pagkatapos ng <xliff:g id="TIME_DELAY">{2}</xliff:g> (na) segundo"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Pinapayagan ang app na kumuha ng mga larawan at video gamit ang camera. Pinapayagan ng pahintulot na ito ang app na gamitin ang camera anumang oras nang wala ng iyong kumpirmasyon."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"i-disable ang LED na tagapagpahiwatig kapag ginagamit ang camera"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Pinapayagan ang isang paunang na-install na application ng system na i-disable ang LED na tagapagpahiwatig ng paggamit sa camera."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Pinapayagan ang isang pre-installed na system application na ipadala ang mga kaganapan ng system sa serbisyo ng camera."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"permanenteng huwag paganahin ang tablet"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"permanenteng i-disable ang TV"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"permanenteng huwag paganahin ang telepono"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"direktang simulan ang pag-setup ng CDMA TV"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"direktang simulan ang pag-set up ng CDMA na telepono"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Pinapayagan ang app na simulan ang paglalaan ng CDMA. Maaaring simulan nang hindi kinakailangan ng nakakahamak na apps ang paglalaan ng CDMA."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"kotrolin ang mga notification ng pag-update ng lokasyon"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Pinapayagan ang app na paganahin/huwag paganahain ang mga notification ng update sa lokasyon mula sa radyo. Hindi para sa paggamit ng normal na apps."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"i-access ang mga katangian ng checkin"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Pinapayagan ang app na mag-invoke ng mga paraan upang magdagdag at mag-delete ng mga template ng fingerprint na magagamit."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"gamitina ng hardware ng fingerprint"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Pinapayagan ang app na gumamit ng hardware ng fingerprint para sa pagpapatotoo"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Hindi buo ang natukoy na fingerprint. Pakisubukang muli."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Hindi maproseso ang fingerprint. Pakisubukang muli."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Marumi ang sensor ng fingerprint. Pakilinis at subukang muli."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Masyadong mabilis ang paggalaw ng daliri. Pakisubukang muli."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Masyadong mabagal ang paggalaw ng daliri. Pakisubukang muli."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Mensahe ng error sa pagkuha na partikular sa vendor 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Hindi maproseso. Subukang muli."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Hindi available ang hardware."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Hindi maiimbak ang fingerprint. Mangyaring mag-alis ng umiiral nang fingerprint."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Nag-time out ang fingerprint. Subukang muli."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Nag-time out ang fingerprint. Subukang muli."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Mensahe ng error na partikular sa vendor."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"basahin ang mga setting ng sync"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Pinapayagan ang app na basahin ang mga setting ng pag-sync para sa isang account. Halimbawa, matutukoy nito kung naka-sync ang app na Mga Tao sa isang account."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"I-toggle on at off ang pag-sync"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Nagbibigay-daan sa isang application na alisin ang mga DRM certficate. Hindi dapat kailanman kailanganin para sa karaniwang apps."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"sumailalim sa isang serbisyo ng pagmemensahe ng carrier"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Binibigyang-daan ang may-ari na sumailalim sa interface sa nangungunang antas ng isang serbisyo ng pagmemensahe ng carrier. Hindi kailanman dapat kailanganin para sa mga normal na app."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolin ang haba at ang mga character na pinapayagan sa mga password at PIN sa lock ng screen."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Pinapayagan ang app na i-verify kung ang isang package ay nai-install."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"sumailalim sa taga-verify ng package"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Pinapayagan ang may-ari na gumawa ng mga kahilingan ng mga taga-verify ng package. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"i-verify ang intent filter"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Nagbibigay-daan sa app na suriin kung na-verify o hindi ang isang intent filter."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"isailalim sa verifier ng intent filter"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Nagbibigay-daan sa may-ari na gumawa ng mga kahilingan ng mga verifier ng intent filter. Hindi kailanman dapat kailanganin para sa mga normal na app."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"mag-access sa mga serial port"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Binibigyang-daan ang may-ari na mag-access ng mga serial port gamit ang SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"panlabas na mag-access ng mga provider ng nilalaman"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Bawasan ang araw"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Dagdagdan ang taon"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Bawasan ang taon"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Nakaraang buwan"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Susunod na buwan"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Kanselahin"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Tanggalin"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Pabilog na slider ng mga minuto"</string>
     <string name="select_hours" msgid="6043079511766008245">"Pumili ng mga oras"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Pumili ng mga minuto"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Grid ng mga araw ayon sa buwan"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Listahan ng taon"</string>
     <string name="select_day" msgid="7774759604701773332">"Pumili ng buwan at araw"</string>
     <string name="select_year" msgid="7952052866994196170">"Pumili ng taon"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Napili ang <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Tinanggal ang <xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Upang i-unpin ang screen na ito, pindutin nang matagal ang Bumalik at Overview nang sabay-sabay."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 373ef66..5d69803 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Dolaşım Başlığı Kapalı"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Hizmet Aranıyor"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Kablosuz Çağrı"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönlendirilmedi"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> saniye sonra <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Uygulamaya kamerayla fotoğraf ve video çekme izni verir. Bu izin, uygulamanın sizin onayınız olmadan istediği zaman kamerayı kullanmasına olanak sağlar."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"Kamera kullanımda iken iletim göstergesi LED\'ini devre dışı bırak"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Önceden yüklenmiş bir sistem uygulamasına kamera kullanım göstergesi LED\'ini devre dışı bırakma izni verir."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Önceden yüklü sistem uygulamalarının, sistem etkinliklerini kamera hizmetine göndermesine izin verir."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"tableti kalıcı olarak devre dışı bırak"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"TV\'yi kalıcı olarak devre dışı bırakma"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"telefonu tamamen devre dışı bırak"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"CDMA TV kurulumunu doğrudan başlatma"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA telefon kurulumunu doğrudan başlat"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Uygulamaya, CDMA provizyon uygulaması başlatma izni verir. Kötü amaçlı uygulamalar gereksiz yere CDMA provizyon uygulaması başlatabilir."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"konum güncelleme bildirimlerini denetle"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Uygulamaya, radyo iletişimiyle konum güncelleme bildirimlerini etkinleştirme/devre dışı bırakma izni verir. Normal uygulamaların kullanımına yönelik değildir."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"erişim giriş özellikleri"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Uygulamanın, kullanılacak parmak izi şablonlarını ekleme ve silme yöntemlerini başlatmasına izin verir."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"parmak izi donanımını kullanma"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Uygulamanın kimlik doğrulama için parmak izi donanımını kullanmasına izin verir."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Parmak izinin tümü algılanamadı. Lütfen tekrar deneyin."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Parmak izi işlenemedi. Lütfen tekrar deneyin."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Parmak izi sensörü kirli. Lütfen temizleyin ve tekrar deneyin."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Parmak hareketi çok hızlıydı. Lütfen tekrar deneyin."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Parmak hareketi çok yavaştı. Lütfen tekrar deneyin."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Tedarikçi firmaya özel edinme hata iletisi 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"İşlenemedi. Tekrar deneyin."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Donanım yok."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Parmak izi depolanamıyor. Lütfen mevcut parmak izlerinden birini kaldırın."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Parmak izi için zaman aşımı oluştu. Tekrar deneyin."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Parmak izi için zaman aşımı oluştu. Tekrar deneyin."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Tedarikçi firmaya özel hata iletisi."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"senk. ayarlarını okuma"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Uygulamaya bir hesaba ait senkronizasyon ayarlarını okuma izni verir. Örneğin, bu izne sahip bir uygulama Kişiler uygulamasının bir hesapla senkronize olup olmadığını belirleyebilir."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"senkronizasyonu açma/kapatma"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Uygulamaya, DRM sertifikalarını kaldırma izin verir. Normal uygulamalar için asla gerekmemelidir."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"operatör mesajlaşma hizmetine bağlan"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"İzin sahibinin, operatör mesajlaşma hizmetinin üst düzey arayüzüne bağlanmasına olanak verir. Normal uygulamalarda hiçbir zaman gerekmez."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ekran kilidini açma şifrelerinde ve PIN\'lerde izin verilen uzunluğu ve karakterleri denetleyin."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Uygulamaya, bir paketin yüklenebilir olduğunu doğrulama izni verir."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"paket doğrulayıcıya bağlan"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Cihazın sahibine, paket doğrulayıcıları için istek yapma izni verir. Normal uygulamalar için gerekli olmaz."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"amaç filtresini doğrula"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Uygulamaya, amaç filtresinin doğrulanıp doğrulanmadığını kontrol etme izni verir."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"amaç filtresi doğrulayıcıya bağlan"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"İzin sahibine, amaç doğrulayıcılar için istekte bulunma izni verir. Normal uygulamalar için gerekli değildir."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"seri bağlantı noktalarına eriş"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"İzin sahibinin, SerialManager API\'sını kullanarak seri bağlantı noktalarına erişmesine olanak sağlar."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"içerik sağlayıcılara harici olarak eriş"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Günü azalt"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Yılı artır"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Yılı azalt"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Önceki ay"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Sonraki ay"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"İptal"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Sil"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Dakika kaydırma çemberi"</string>
     <string name="select_hours" msgid="6043079511766008245">"Saati seçin"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Dakikayı seçin"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Ayın günleri tablosu"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Yıl listesi"</string>
     <string name="select_day" msgid="7774759604701773332">"Ayı ve günü seçin"</string>
     <string name="select_year" msgid="7952052866994196170">"Yılı seçin"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seçildi"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> silindi"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (İş)"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Bu ekranın sabitlemesini kaldırmak için Geri ve Genel Bakış\'a aynı anda dokunup basılı tutun."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index c3cfe6d..8159c0a7 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -126,8 +126,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Банер роум-гу вимк."</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Пошук служби"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Дзвінок через Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не переслано"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> після <xliff:g id="TIME_DELAY">{2}</xliff:g> сек."</string>
@@ -586,6 +597,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Дозволяє програмі фотографувати та знімати відео за допомогою камери. Такий дозвіл дає програмі змогу будь-коли використовувати камеру без вашого підтвердження."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"вимикати світлодіодний індикатор передавання, коли використовується камера"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Дозволяє попередньо встановленій системній програмі вимикати світлодіодний індикатор використання камери."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Попередньо встановлений системний додаток може надсилати в сервіс камери сповіщення про події системи."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"остаточно вимкнути пристрій"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"назавжди вимкнути телевізор"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"остаточно вимкнути телефон"</string>
@@ -634,6 +646,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"безпосередньо запускати налаштування телевізора CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"безпосер. поч. налашт-ня CDMA тел."</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Дозволяє програмі запускати ініціалізацію CDMA. Шкідливі програми можуть без потреби запускати ініціалізацію CDMA."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"контрол. сповіщ. про оновлення місцезн."</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Дозволяє програмі вмикати/вимикати сповіщення про оновлення місцезнаходження з радіо. Не для використання звичайними програмами."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"отр. дост. до власт. реєстр."</string>
@@ -748,6 +764,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Увімкнути в додатку функції для додавання й видалення шаблонів цифрових відбитків."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"користуватися апаратним забезпеченням для цифрових відбитків"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозволити додатку використовувати апаратне забезпечення для автентифікації"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Відбиток розпізнано частково. Повторіть спробу."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не вдалось обробити відбиток. Повторіть спробу."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Датчик відбитків забруднився. Очистьте його та повторіть спробу."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Ви забрали палець надто швидко. Повторіть спробу."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Ви забрали палець надто повільно. Повторіть спробу."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Повідомленя про помилку: 0. Не отримано відбиток постачальника"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Не вдалось обробити. Повторіть спробу."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Апаратне забезпечення недоступне."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Не вдалося зберегти відбиток. Видаліть наявний відбиток."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час очікування відбитка минув. Повторіть спробу."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Час очікування відбитка минув. Повторіть спробу."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Повідомлення про помилку щодо відбитка постачальника."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"читати налаштування синхронізації"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Дозволяє програмі читати налаштування синхронізації для облікового запису, наприклад, визначати, чи програма Люди синхронізується з обліковим записом."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"вмикати й вимикати синхронізацію"</string>
@@ -824,6 +856,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Власник може видаляти сертифікати DRM. Ніколи не застосовується для звичайних додатків."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"підключатися до служби надсилання повідомлень через оператора"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Додаток зможе підключатися до інтерфейсу верхнього рівня служби надсилання повідомлень через оператора. Звичайні додатки ніколи не використовують цей дозвіл."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Укажіть максимальну довжину та кількість символів для паролів розблокування екрана та PIN-кодів."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Відстежув. спроби розблок. екрана"</string>
@@ -1121,6 +1157,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Дозволяє програмі перевіряти можливість встановлення пакета."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"прив’язуватися до програми перевірки пакетів"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Дозволяє власникові робити запити на програми перевірки пакетів. Ніколи не застосовується для звичайних програм."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"перевірка фільтра команд"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Додаток може визначати, чи перевірено фільтр команд."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"пов’язувати з перевіркою фільтра команд"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Власник може перевірити фільтр команд. Ніколи не застосовується для звичайних додатків."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"отримувати доступ до послідовних портів"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Дозволяє власнику отримувати доступ до послідовних портів за допомогою API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"отримув. ззовні доступ до постач. вмісту"</string>
@@ -1560,6 +1600,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"На день назад"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"На рік уперед"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"На рік назад"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Попередній місяць"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Наступний місяць"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Скасувати"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1812,11 +1854,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Вибір хвилин на циферблаті"</string>
     <string name="select_hours" msgid="6043079511766008245">"Виберіть години"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Виберіть хвилини"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Вікно вибору дати"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Меню вибору року"</string>
     <string name="select_day" msgid="7774759604701773332">"Виберіть місяць і день"</string>
     <string name="select_year" msgid="7952052866994196170">"Виберіть рік"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Вибрано: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> видалено"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Робоча <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Щоб відкріпити екран, одночасно натисніть і утримуйте кнопки \"Назад\" та \"Огляд\"."</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index f315112..95149fe 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"رومنگ بینر آف"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"سروس کی تلاش کر رہا ہے"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"‏Wi-Fi کالنگ"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"‎%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : فارورڈ نہیں کی گئی"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> بعد از <xliff:g id="TIME_DELAY">{2}</xliff:g> سیکنڈ"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"ایپ کو کیمرے سے تصویریں لینے اور ویڈیوز بنانے کی اجازت دیتا ہے۔ یہ اجازت ایپ کو آپ کی تصدیق کے بغیر کسی بھی وقت کیمرا استعمال کرنے کی اجازت دیتی ہے۔"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"‏کیمرا استعمال میں ہونے پر ٹرانسمیٹ انڈیکیٹر LED کو غیر فعال کریں"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"‏پہلے سے انسٹال کردہ کسی سسٹم ایپلیکیشن کو کیمرا کے استعمال کے انڈیکیٹر LED کو غیر فعال کرنے کی اجازت دیتا ہے۔"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"پہلے سے انسٹال سسٹم ایپلیکیشن کو کیمرہ سروس سسٹم ایونٹس بھیجنے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"ٹیبلیٹ کو مستقل طور پر غیر فعال کریں"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"‏مستقل طور پر TV غیر فعال کریں"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"فون کو مستقل طور پر غیر فعال کریں"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"‏براہ راست CDMA TV سیٹ اپ شروع کریں"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"‏CDMA فون سیٹ اپ کو براہ راست شروع کریں"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"‏ایپ کو CDMA فراہمی شروع کرنے کی اجازت دیتا ہے۔ نقصان دہ ایپس بغیر ضرورت کے CDMA فراہمی شروع کر سکتی ہیں۔"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"مقام کے اپ ڈیٹ کی اطلاعات کو کنٹرول کریں"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"ایپ کو ریڈیو سے مقام کی اپ ڈیٹ کی اطلاعات فعال کرنے/غیر فعال کرنے کی اجازت دیتا ہے۔ عام ایپس کے استعمال کیلئے نہیں ہے۔"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"چیک ان کی خصوصیات تک رسائی حاصل کریں"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ایپ کو استعمال کیلئے فنگر پرنٹ کی تمثیلات شامل کرنے اور حذف کرنے کیلئے طریقوں کو کالعدم قرار دینے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"فنگر پرنٹ ہارڈ ویئر استعمال کریں"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ایپ کو توثیق کیلئے فنگر پرنٹ ہارڈ ویئر استعمال کرنے کی اجازت دیتا ہے"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"جزوی فنگر پرنٹ کی شناخت ہوئی۔ براہ کرم دوبارہ کوشش کریں۔"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"فنگر پرنٹ پر کارروائی نہیں کی جا سکی۔ براہ کرم دوبارہ کوشش کریں۔"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"فنگر پرنٹ سینسر گندا ہے۔ براہ کرم صاف کریں اور دوبارہ کوشش کریں۔"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"انگلی کو کافی تیزی سے ہٹا لیا گیا۔ براہ کرم دوبارہ کوشش کریں۔"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"انگلی کو بہت آہستہ ہٹا لیا گیا۔ براہ کرم دوبارہ کوشش کریں۔"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"وینڈر کیلئے مخصوص حصول کی خرابی کا پیغام 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"کارروائی کرنے سے قاصر ہے۔ دوبارہ کوشش کریں۔"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"ہارڈ ویئر دستیاب نہیں ہے۔"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"فنگر پرنٹ اسٹور نہیں کیا جا سکتا ہے۔ براہ کرم ایک موجودہ فنگر پرنٹ ہٹائیں۔"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"وینڈر کیلئے مخصوص خرابی کا پیغام۔"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"مطابقت پذیری کی ترتیبات پڑھیں"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"‏ایپ کو کسی اکاؤنٹ کیلئے مطابقت پذیری کی ترتیبات پڑھنے کی اجازت دیتا ہے۔ مثلا، یہ تعین کرسکتا ہے کہ آیا People ایپ کسی اکاؤنٹ کے ساتھ مطابقت پذیر ہے۔"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"مطابقت پذیری آن اور آف ٹوگل کریں"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"‏ایک ایپلیکیشن کو DRM سرٹیفکیٹس کو ہٹانے کی اجازت دیتا ہے۔ عام ایپس کیلئے کبھی بھی اس کی ضرورت نہیں ہونی چاہیے۔"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"ایک کیریئر پیغام رسانی سروس کا پابند بنیں"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"حامل کو ایک کیریئر پیغام رسانی سروس کے اعلی سطحی انٹرفیس کا پابند ہونے کی اجازت دیتی ہے۔ عام ایپس کیلئے کبھی بھی اس کی ضرورت نہیں ہونی چاہیے۔"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"پاس ورڈ کے اصول سیٹ کریں"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"‏اسکرین لاک پاس ورڈز اور PINs میں اجازت یافتہ لمبائی اور حروف کو کنٹرول کریں۔"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"اسکرین غیر مقفل کرنے کی کوششیں مانیٹر کریں"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"ایپ کو اس بات کی توثیق کرنے کی اجازت دیتا ہے کہ پیکج انسٹال کرنے قابل ہے۔"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"پیکج کے ایک توثیق کار کے پابند بنیں"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"حامل کو پیکیج کے توثیق کاروں کی درخواستیں کرنے دیتا ہے۔ عام ایپس کیلئے کبھی بھی اس کی ضرورت نہيں ہونی چاہئے۔"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"انٹنٹ فلٹر کی توثیق کریں"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"ایپ کو یہ چیک کرنے کی اجازت دیتا ہے کہ آیا انٹنٹ فلٹر توثیق شدہ ہے یا نہیں۔"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"انٹنٹ فلٹر توثیق کار کے پابند بنیں"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"حامل کو انٹنٹ فلٹر کے توثیق کاروں کی درخواستیں کرنے کی اجازت دیتا ہے۔ عام ایپس کیلئے کبھی بھی اس کی ضرورت نہیں ہونی چاہیے۔"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"سیریل پورٹس تک رسائی حاصل کریں"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"‏SerialManager API کا استعمال کرکے حامل کو سیریل پورٹز تک رسائی دیتا ہے۔"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"مواد فراہم کنندگان تک خارجی رسائی حاصل کریں"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"دن گھٹائیں"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"سال بڑھائیں"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"سال گھٹائیں"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"پچھلا مہینہ"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"اگلا مہینہ"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"منسوخ کریں"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"حذف کریں"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"منٹس سرکلر سلائیڈر"</string>
     <string name="select_hours" msgid="6043079511766008245">"گھنٹے منتخب کریں"</string>
     <string name="select_minutes" msgid="3974345615920336087">"منٹ منتخب کریں"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"دنوں کا ماہ کا گرڈ"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"سال کی فہرست"</string>
     <string name="select_day" msgid="7774759604701773332">"ماہ اور دن منتخب کریں"</string>
     <string name="select_year" msgid="7952052866994196170">"سال منتخب کریں"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> کو منتخب کیا گیا"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> کو حذف کر دیا گیا"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"دفتر <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"اس اسکرین سے پن ہٹانے کیلئے، واپس جائیں اور مجموعی جائزہ کو ایک ساتھ ٹچ کریں اور دبا کر رکھیں۔"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 78bad61..0b5e963 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Rouming banneri o‘chirilgan"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Xizmatlar qidirilmoqda"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi qo‘ng‘iroq"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yo‘naltirilmadi"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>  <xliff:g id="TIME_DELAY">{2}</xliff:g> soniyadan so‘ng"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Ilovaga kameradan foydalanib rasm va videoga olishga ruxsat beradi. Bu ruxsat ilovaga sizdan tasdiqlashni so‘ramasdan kameradan foydalanishga imkon beradi."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"LED ko‘rsatkichni kamera faolligida boshqarish imkoniyatini o‘chirish"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Zavodda o‘rnatilgan tizim dasturiga kamerani o‘chirish uchun LED ko‘rsatkichidan foydalanish imkonini beradi."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Oldindan o‘rnatilgan tizimga oid ilovaga tizimdagi o‘zgarishlar bo‘yicha kamera xizmati bildirishnomalarini yuborish uchun ruxsat beradi."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"doimo planshetni o‘chirish"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"televizorni butunlay o‘chirib qo‘yish"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"doimo telefonni o‘chirish"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"bevosita CDMA televizorni sozlashni boshlash"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA telefonni moslashni to‘g‘ridan to‘g‘ri boshlash"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Ilova CDMA sozlamasini ishga tushirishi mumkin. Zararli dasturlar uning yordamida zarurat bo‘lmaganda ham CDMA sozlamasini ishga tushirishi mumkin."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"manzilni boshqarish yangiliklari eslatmalari"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Ilova qabul qilish-uzatish moslamasi ma’lumotlari asosida joylashuvning yangilangani to‘g‘risidagi bildirishnomalarni yoqishi yoki o‘chirib qo‘yishi mumkin. Oddiy ilovalar tomonidan foydalanilmaydi."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"tasdiqdan o‘tib kirish xossalari"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Ilova foydalanish uchun barmoq izi namunalarini qo‘shish va o‘chirish usullarini qo‘llashi mumkin."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"barmoq izi sensoridan foydalanish"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Ilova haqiqiylikni tekshirish uchun barmoq izi sensoridan foydalanishi mumkin"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmoq izi qisman aniqlandi. Qayta urinib ko‘ring."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Barmoq izi aniqlanmadi. Qayta urinib ko‘ring."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Barmoq izi sensori kirlangan. Uni tozalab, keyin qayta urinib ko‘ring."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Barmoq juda tez harakatlandi. Qayta urinib ko‘ring."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Barmoq juda sekin harakatlandi. Qayta urinib ko‘ring."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Sotuvchidan barmoq izini olishda sodir bo‘ladigan xatolik xabari 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Barmoq izini aniqlab bo‘lmadi. Qayta urinib ko‘ring."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Barmoq izi sensoridan foydalanib bo‘lmaydi."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Barmoq izini saqlab bo‘lmadi. Mavjud barmoq izlaridan birini o‘chirib tashlang."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmoq izini aniqlash vaqti tugab qoldi. Qayta urinib ko‘ring."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Barmoq izini aniqlash vaqti tugab qoldi. Qayta urinib ko‘ring."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Xizmat bilan bog‘liq xatolik xabari."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"sinx-sh sozlamalarini o‘qish"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Ilovaga hisobning sinxronlash sozlamalarini o‘qish uchun ruxsat beradi. Masalan, bu \"Odamlar\" ilovasi hisob bilan sinxronlangan yoki aksini aniqlay oladi."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"sinx.ni yoqish/o‘chirish"</string>
@@ -822,6 +854,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Ilovaga DRM sertifikatlarini o‘chirib tashlash uchun ruxsat beradi. Oddiy ilovalar uchun talab qilinmaydi."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"aloqa operatorining xabar almashinuv xizmatiga bog‘lanish"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Egasiga aloqa operatorining xabar almashinuv xizmatining yuqori darajali interfeysiga bog‘lanish uchun ruxsat beradi. Oddiy ilovalar uchun hech qachon kerak bo‘lmaydi."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"ovozli muloqot xizmatidan foydalanish"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"Egasiga joriy ovozli muloqot xizmatidan foydalanishga ruxsat beradi. Oddiy ilovalarda hech qachon kerak bo‘lmaydi."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parol qoidalarini o‘rnatish"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ekran qulfi paroli va PIN kodlari uchun qo‘yiladigan talablarni (belgilar soni va uzunligi) nazorat qiladi."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Ekranni qulfdan chiqarish urinishlarini nazorat qilish"</string>
@@ -1119,6 +1153,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Ilova paketlarni o‘rnatish imkoniyatini tekshirishi mumkin."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"paketni tekshirgichga bog‘lash"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Ilova paketlarni tekshirishni talab qilishi mumkin. Oddiy ilovalar uchun talab qilinmaydi."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"intent-filtrni tekshirish"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Ilovaga intent-filtr holatini tekshirish uchun ruxsat beradi."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"intent-filtrni tekshirgichga biriktirish"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Egasiga intent-filtr tekshiruvi so‘rovlarini yuborish uchun ruxsat beradi. Oddiy ilovalarda hech qachon kerak bo‘lmaydi."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"serial portlarga kirish"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Foydalanuvchiga SerialManager API’dan foydalanib, serial portlarga kirishga ruxsat beradi."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"kontent provayderiga tashqi ruxsat"</string>
@@ -1544,6 +1582,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Kunni kamaytirish"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Yilni ko‘paytirish"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Yilni kamaytirish"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Avvalgi oy"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Keyingi oy"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Bekor qilish"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"O‘chirish"</string>
@@ -1794,11 +1834,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Doiradan daqiqani tanlang"</string>
     <string name="select_hours" msgid="6043079511766008245">"Soatlarni tanlash"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Daqiqalarni tanlash"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Oy kunlari (jadval ko‘rinishida)"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Yil ro‘yxati"</string>
     <string name="select_day" msgid="7774759604701773332">"Oy va kunni tanlash"</string>
     <string name="select_year" msgid="7952052866994196170">"Yilni tanlash"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> tanlandi"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> o‘chirildi"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Ish <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Ushbu ekrandan chiqish uchun “Orqaga” va “Umumiy nazar” tugmalarini bir vaqtda bosib turing."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index a2ebfd4..6e1ef92 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Biểu ngữ Chuyển vùng Tắt"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Đang tìm kiếm Dịch vụ"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Gọi qua Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Không được chuyển tiếp"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> sau <xliff:g id="TIME_DELAY">{2}</xliff:g> giây"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Cho phép ứng dụng chụp ảnh và quay video bằng máy ảnh. Quyền này cho phép ứng dụng sử dụng máy ảnh bất kỳ lúc nào mà không cần sự xác nhận của bạn."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"vô hiệu hóa tính năng phát đèn LED chỉ báo khi máy ảnh đang được sử dụng"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Cho phép cài đặt trước ứng dụng hệ thống để vô hiệu hóa việc máy ảnh sử dụng đèn LED chỉ báo."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Cho phép cài đặt trước ứng dụng hệ thống để gửi sự kiện về hệ thống dịch vụ máy ảnh."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"vô hiệu hóa vĩnh viễn máy tính bảng"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"tắt vĩnh viễn TV"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"vĩnh viễn vô hiệu hóa điện thoại"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"trực tiếp bắt đầu thiết lập TV CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"trực tiếp bắt đầu thiết lập điện thoại CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Cho phép ứng dụng bắt đầu cấp phép CDMA. Ứng dụng độc hại có thể bắt đầu cấp phép CDMA một cách không cần thiết."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"kiểm soát thông báo cập nhật vị trí"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Cho phép ứng dụng bật/tắt thông báo cập nhật vị trí của radio. Không dành cho ứng dụng thông thường."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"truy cập thuộc tính đăng nhập"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Cho phép ứng dụng gọi các phương pháp để thêm và xóa các mẫu vân tay để sử dụng."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"sử dụng phần cứng vân tay"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Cho phép ứng dụng sử dụng phần cứng vân tay để xác thực"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Đã phát hiện được một phần vân tay. Vui lòng thử lại."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Không thể xử lý vân tay. Vui lòng thử lại."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Cảm biến vân tay bị bẩn. Hãy làm sạch và thử lại."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Ngón tay đã di chuyển quá nhanh. Vui lòng thử lại."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Ngón tay đã di chuyển quá chậm. Vui lòng thử lại."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Thông báo lỗi lấy vân tay từ người bán cụ thể 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Không thể xử lý. Hãy thử lại."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Phần cứng không có sẵn."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Không thể lưu vân tay. Vui lòng xóa vân tay hiện có."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Đã hết thời gian chờ vân tay. Hãy thử lại."</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Đã hết thời gian chờ vân tay. Hãy thử lại."</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Thông báo lỗi cho người bán cụ thể."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"đọc cài đặt đồng bộ hóa"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Cho phép ứng dụng đọc cài đặt đồng bộ hóa cho tài khoản. Ví dụ: việc này có thể xác định liệu ứng dụng Mọi người đã được đồng bộ hóa với tài khoản chưa."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"chuyển đổi bật và tắt đồng bộ hóa"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Cho phép ứng dụng xóa chứng chỉ DRM. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"liên kết với dịch vụ nhắn tin của nhà cung cấp dịch vụ"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ nhắn tin của nhà cung cấp dịch vụ. Không cần thiết cho các ứng dụng thông thường."</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Đặt quy tắc mật khẩu"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kiểm soát độ dài và ký tự được phép trong mật khẩu khóa màn hình và mã PIN."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Giám sát những lần thử mở khóa màn hình"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Cho phép ứng dụng xác minh gói có thể cài đặt."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"liên kết với trình xác minh gói"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Cho phép chủ sở hữu yêu cầu trình xác minh gói. Không cần thiết cho các ứng dụng thông thường."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"xác minh bộ lọc theo mục đích"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Cho phép ứng dụng kiểm tra xem bộ lọc theo mục đích đã được xác minh hay chưa."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"liên kết với trình xác minh bộ lọc theo mục đích"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Cho phép chủ sở hữu yêu cầu trình xác minh bộ lọc theo mục đích. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"truy cập cổng nối tiếp"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Cho phép chủ sở hữu truy cập cổng nối tiếp sử dụng API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"truy cập vào nhà cung cấp nội dung từ bên ngoài"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Giảm ngày"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Tăng năm"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Giảm năm"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Tháng trước"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Tháng sau"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Hủy"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Xóa"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Thanh trượt phút hình tròn"</string>
     <string name="select_hours" msgid="6043079511766008245">"Chọn giờ"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Chọn phút"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Lưới ngày theo tháng"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Danh sách năm"</string>
     <string name="select_day" msgid="7774759604701773332">"Chọn tháng và ngày"</string>
     <string name="select_year" msgid="7952052866994196170">"Chọn năm"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"Đã chọn <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Đã xóa <xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> làm việc"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Để bỏ khóa màn hình này, chạm và giữ Quay lại và Tổng quan cùng lúc."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index e7c6bee..aaf9d90 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"禁用漫游横幅"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"正在搜索服务"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"WLAN 通话"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:无法转接"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g>秒后<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"允许该应用使用相机拍摄照片和视频。此权限可让该应用随时使用相机,而无需您的确认。"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"在相机使用过程中停用传输指示灯 LED"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"允许预装的系统应用禁止相机使用指示灯 LED。"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"允许预装的系统应用发送相机服务系统事件。"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"永久停用平板电脑"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"永久停用电视"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"永久停用手机"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"直接启动 CDMA 电视设置"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"直接启动 CDMA 电话设置"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"允许应用启动 CDMA 配置。恶意应用可能会无端启动 CDMA 配置。"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"控制位置更新通知"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"允许应用启用/停用来自无线装置的位置更新通知。普通应用不应使用此权限。"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"访问检入属性"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"允许该应用调用方法来添加和删除可用的指纹模板。"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"使用指纹硬件"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"允许该应用使用指纹硬件进行身份验证"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"仅检测到部分指纹,请重试。"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"无法处理指纹,请重试。"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"指纹传感器有脏污。请擦拭干净,然后重试。"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"手指移动太快,请重试。"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"手指移动太慢,请重试。"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"针对供应商的指纹获取错误消息 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"无法处理指纹,请重试。"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"硬件无法使用。"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"无法存储指纹。请移除一个现有的指纹。"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指纹录入操作超时,请重试。"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"指纹录入操作超时,请重试。"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"针对供应商的错误消息。"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"读取同步设置"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"允许该应用读取某个帐户的同步设置。例如,此权限可确定“联系人”应用是否与某个帐户同步。"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"启用和停用同步"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"允许应用移除DRM证书。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"绑定到运营商消息传递服务"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允许应用绑定到运营商消息传递服务的顶级接口。普通应用绝不需要此权限。"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"控制锁屏密码和 PIN 码所允许的长度和字符。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"允许应用验证软件包是否可安装。"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"绑定到软件包验证程序"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"允许应用申请使用软件包验证程序。普通应用绝不需要此权限。"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"验证 Intent 过滤器"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"允许该应用检查 Intent 过滤器是否已经过验证。"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"绑定至 Intent 过滤器验证程序"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"允许应用请求使用 Intent 过滤器验证程序。普通应用绝不需要此权限。"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"访问串行端口"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"允许应用通过SerialManager API使用串行端口。"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"从外部访问内容提供程序"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"减小日期值"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"增大年份值"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"减小年份值"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"上个月"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"下个月"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"取消"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"分钟转盘"</string>
     <string name="select_hours" msgid="6043079511766008245">"选择小时"</string>
     <string name="select_minutes" msgid="3974345615920336087">"选择分钟"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"按月份划分的日期网格"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"年份列表"</string>
     <string name="select_day" msgid="7774759604701773332">"选择月份和日期"</string>
     <string name="select_year" msgid="7952052866994196170">"选择年份"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"已选择<xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"已删除<xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"要取消固定此屏幕,请同时触摸并按住“返回”和“概览”按钮。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index a62cf11..5d7d55b 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"漫遊橫幅關閉"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"正在搜尋服務"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi 通話"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:尚未轉接"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> 於 <xliff:g id="TIME_DELAY">{2}</xliff:g> 秒後轉接"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"允許應用程式使用相機拍照和錄影。這項權限允許應用程式隨時使用相機,而不需經您確認。"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"使用相機時停用傳輸指示燈"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"允許預先安裝的系統應用程式停用相機指示燈。"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"允許預先安裝的系統應用程式傳送相機服務系統活動。"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"永久停用平板電腦"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"永遠停用電視"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"永久停用手機"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"直接啟動 CDMA 電視設定"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"直接啟動 CDMA 手機設定程序"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"允許應用程式啟動 CDMA 佈建功能。惡意應用程式可能會在非必要的情況下啟動 CDMA 佈建功能。"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"控制位置更新通知"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"允許應用程式啟用/停用來自無線電的位置更新通知 (不建議一般應用程式使用)。"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"存取登錄屬性"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"允許應用程式調用加入和刪除指紋模板的方法以供使用。"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"使用指紋硬件"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"允許應用程式使用指紋硬件驗證"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"只偵測到部分指紋。請再試一次。"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"無法處理指紋。請再試一次。"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"指紋感應器不乾淨。請清潔後再試一次。"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"手指移動太快。請再試一次。"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"手指移動太慢。請再試一次。"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"供應商專用採集錯誤訊息 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"無法處理。請再試一次。"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"硬件無法使用。"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"指紋無法儲存。請移除現有指紋。"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋已逾時。請再試一次。"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"指紋已逾時。請再試一次。"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"供應商專用錯誤訊息。"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"讀取同步處理設定"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"允許應用程式讀取帳戶的同步設定,例如確定「通訊錄」應用程式是否和某個帳戶保持同步。"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"開啟和關閉同步功能"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"允許應用程式移除 DRM 憑證 (一般應用程式並不需要)。"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"繫結至流動網絡供應商短訊服務"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允許應用程式繫結至流動網絡供應商短訊服務的頂層介面 (不建議一般應用程式使用)。"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"控制螢幕鎖定密碼和 PIN 所允許的長度和字元。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"監控螢幕解鎖嘗試次數"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"允許應用程式驗證套件是否可安裝。"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"繫結至套件驗證程序"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"允許應用程式要求驗證套件 (不建議一般應用程式使用)。"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"驗證意圖篩選器"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"允許應用程式檢查意圖篩選器是否已通過驗證。"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"繫結至意圖篩選器驗證"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"允許應用程式要求驗證意圖篩選器 (不建議一般應用程式使用)。"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"接入串列通訊埠"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"允許應用程式使用 SerialManager API 接入串列通訊埠。"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"從外部存取內容供應商"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"減少日數"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"增加年數"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"減少年數"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"上個月"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"下個月"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"取消"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"刪除"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"分鐘環形滑桿"</string>
     <string name="select_hours" msgid="6043079511766008245">"選取小時"</string>
     <string name="select_minutes" msgid="3974345615920336087">"選取分鐘"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"顯示每日的月曆方格"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"年份清單"</string>
     <string name="select_day" msgid="7774759604701773332">"選取月份和日期"</string>
     <string name="select_year" msgid="7952052866994196170">"選取年份"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"已選取<xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> 已刪除"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"如要取消固定這個畫面,請同時輕觸並按住 [返回] 和 [概覽]。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5d1821a..174e944 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"漫遊橫幅關閉"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"正在搜尋服務"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi 通話"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:未轉接"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g> 秒後 <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"允許應用程式使用相機拍照和錄影。這項權限可讓應用程式隨時使用相機,而不需請求您進行確認。"</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"使用攝影機時停用傳輸指示器 LED"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"允許預先安裝的系統應用程式停用攝影機指示器 LED。"</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"允許預先安裝的系統應用程式傳送相機服務系統事件。"</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"永久停用平板電腦"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"永久停用電視"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"永久停用電話"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"直接啟動 CDMA 電視設定程序"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"直接起始 CDMA 手機設定程序"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"允許應用程式啟動 CDMA 服務。請注意,惡意應用程式可能利用此功能啟動非必要的 CDMA 服務。"</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"控制位置更新通知"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"允許應用程式啟用/停用來自無線電的位置更新通知 (不建議一般應用程式使用)。"</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"存取登機選項"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"允許應用程式呼叫方法來新增及移除可用的指紋範本"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"使用指紋硬體"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"允許應用程式使用指紋硬體進行驗證"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"僅偵測到部分指紋,請再試一次。"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"無法處理指紋,請再試一次。"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"指紋感應器有髒汙。請清潔感應器,然後再試一次。"</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"手指移動速度過快,請再試一次。"</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"手指移動速度過慢,請再試一次。"</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"供應商自訂的指紋擷取錯誤訊息 0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"無法辨識指紋,請再試一次。"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"硬體無法使用。"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"無法儲存指紋,請先移除現有指紋。"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋處理作業逾時,請再試一次。"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"指紋處理作業逾時,請再試一次。"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"供應商自訂的錯誤訊息。"</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"讀取同步處理設定"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"允許應用程式讀取帳戶的同步處理設定,例如判斷「使用者」應用程式是否和某個帳戶進行同步處理。"</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"開啟及關閉同步功能"</string>
@@ -822,6 +854,10 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"允許應用程式移除 DRM 憑證 (一般應用程式並不需要)。"</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"與行動通訊業者簡訊服務繫結"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允許應用程式與行動通訊業者簡訊服務的頂層介面繫結 (一般應用程式並不需要)。"</string>
+    <!-- no translation found for permlab_accessVoiceInteractionService (4183835260471435605) -->
+    <skip />
+    <!-- no translation found for permdesc_accessVoiceInteractionService (836587728238433459) -->
+    <skip />
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"管理螢幕鎖定密碼和 PIN 碼支援的字元和長度上限。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
@@ -1119,6 +1155,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"允許應用程式驗證是否可安裝特定套件。"</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"繫結至套件驗證程序"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"允許應用程式要求驗證套件 (一般應用程式不需使用)。"</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"驗證用途篩選器"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"允許應用程式檢查用途篩選器是否已通過驗證。"</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"與用途篩選器驗證程式繫結"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"允許應用程式要求用途篩選器驗證程式 (一般應用程式不需使用)。"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"存取序列埠"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"允許應用程式使用 SerialManager API 存取序列埠。"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"從外部存取內容供應端"</string>
@@ -1544,6 +1584,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"減少日數"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"增加年數"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"減少年數"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"上個月"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"下個月"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt 鍵"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"取消"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete 鍵"</string>
@@ -1794,11 +1836,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"分鐘數環狀滑桿"</string>
     <string name="select_hours" msgid="6043079511766008245">"選取小時數"</string>
     <string name="select_minutes" msgid="3974345615920336087">"選取分鐘數"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"日期網格 (按月顯示)"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"年份清單"</string>
     <string name="select_day" msgid="7774759604701773332">"選取月份和日期"</string>
     <string name="select_year" msgid="7952052866994196170">"選取年份"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"已選取 <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"已刪除 <xliff:g id="KEY">%1$s</xliff:g>"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"如要取消固定這個畫面,請同時輕觸並按住返回按鈕和總覽按鈕。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 4c3a400..df11e16 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -124,8 +124,19 @@
     <string name="roamingText12" msgid="1189071119992726320">"Ibhena yokuzulazula ivaliwe"</string>
     <string name="roamingTextSearching" msgid="8360141885972279963">"Iseshela Isevisi"</string>
     <string name="wfcRegErrorTitle" msgid="2301376280632110664">"Ukushaya kwe-Wi-Fi"</string>
-  <string-array name="wfcOperatorErrorMessages">
+  <string-array name="wfcOperatorErrorAlertMessages">
   </string-array>
+  <string-array name="wfcOperatorErrorNotificationMessages">
+  </string-array>
+    <string name="wfcSpnFormat" msgid="8211621332478306568">"%s"</string>
+    <!-- no translation found for wifi_calling_off_summary (8720659586041656098) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_preferred_summary (1994113411286935263) -->
+    <skip />
+    <!-- no translation found for wfc_mode_cellular_preferred_summary (5920549484600758786) -->
+    <skip />
+    <!-- no translation found for wfc_mode_wifi_only_summary (2379919155237869320) -->
+    <skip />
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Akudlulisiwe"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> emuva kwamasekhondi angu-<xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
@@ -584,6 +595,7 @@
     <string name="permdesc_camera" msgid="8497216524735535009">"Ivumela uhlelo lokusebenza ukuthatha izithombe namavidiyo ngekhamera. Le mvume ivumela uhlelo lokusebenza ukusebenzisa ikhamera nganoma isiphi isikhathi ngaphandle kwemvume yakho."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"khubaza i-LED yesikhombi sokudlulisa uma ikhamera isebenza"</string>
     <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Ivumela isistimu efakwe ngaphambili yohlelo lokusebenza ukuze ikhubaze i-LED yesikhombi sokusetshenziswa kwekhamera."</string>
+    <string name="permdesc_cameraSendSystemEvent" msgid="8642231538552298107">"Ivumela uhlelo lokusebenza lesistimu olufakwe ngaphambilini ukuthumela imicimbi yesistimu yesevisi yekhamera."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"vimbela ngokuphelele ithebhulethi"</string>
     <string name="permlab_brick" product="tv" msgid="4912674222121249410">"khubaza unaphakade i-TV"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ngokwaphakade vimbela ifoni"</string>
@@ -632,6 +644,10 @@
     <string name="permlab_performCdmaProvisioning" product="tv" msgid="3485391974208100809">"qala ngokuqondile ukusethwa kwe-CDMA TV"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"ngokuqondile qalisa ukumisa ifoni nge-CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Ivumela uhlelo lokusebenza ukuqalisa amalungiselelo e-CDMA. Izuhlelo lokusebenza ezinobungozi ingaqalisa amalungiselelo e-CDMA ngokungenasidingo."</string>
+    <!-- no translation found for permlab_performSimActivation (1651116521896665009) -->
+    <skip />
+    <!-- no translation found for permdesc_performSimActivation (1778214876348917401) -->
+    <skip />
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"lawula izaziso zokubuyekeza indawo"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Ivumela ukuthi uhlelo lokusebenza yenze izaziso zendawo zisebenze noma zingasebenzi emsakazweni. Ayenzelwe ukuthi isetshenziswe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"finyelela kwizakhiwo zokuhlola"</string>
@@ -746,6 +762,22 @@
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Ivumela uhlelo lokusebenza ukuthi libuyisele izindlela zokungeza nokususa izifanekiso zezigxivizo zeminwe ngokusetshenziswa."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"sebenzisa izingxenyekazi zekhompyutha zezigxivizo zeminwe"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Ivumela uhlelo lokusebenza ukuthi lusebenzise izingxenyekazi zekhompyutha zezigxivizo zeminwe ukuze kuqinisekiswe"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Izigxivizo zeminwe ezincane zitholiwe. Sicela uzame futhi."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Ayikwazanga ukucubungula izigxivizo zeminwe. Sicela uzame futhi."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Inzwa yezigxivizo zeminwe ingcolile. Sicela uyihlanze uphinde uzame futhi."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="5303368850245663580">"Umunwe uhanjiswe ngokushesha kakhulu. Sicela uzame futhi."</string>
+    <string name="fingerprint_acquired_too_slow" msgid="7381891107120721078">"Umunwe uhanjiswe kancane kakhulu. Sicela uzame futhi."</string>
+  <string-array name="fingerprint_acquired_vendor">
+    <item msgid="2892952818207766996">"Umlayezo wephutha wokutholwa okucacisiwe komthengisi ongu-0"</item>
+  </string-array>
+    <string name="fingerprint_error_unable_to_process" msgid="4232401562838100026">"Ayikwazi ukucubungula. Zama futhi."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="6162709753784993771">"Izingxenyekazi zekhompuyutha azitholakali."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Izigxivizo zeminwe azikwazi ukugcinwa. Sicela ususe izigxivizo zeminwe ezikhona."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string>
+    <string name="fingerprint_error_vendor" msgid="3175724710791609491">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string>
+  <string-array name="fingerprint_error_vendor">
+    <item msgid="5804600450373644614">"Umlayezo wephutha ocacile womthengisi."</item>
+  </string-array>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"funda izilungiselelo zokuvumelanisa"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Ivumela uhlelo lokusebenza ukufunda izilungiselelo zokuvumelanisa ze-akhawunti. Isibonelo, lokhu kungacacisa ukuthi noma ngabe uhlelo lokusebenza le-People livumelanisiwe ne-akhawunti."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"shintsha phakathi kokuvula kanye nokucisha ukuvumelanisa"</string>
@@ -822,6 +854,8 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Ivumela uhlelo lokusebenza ukususa izitifiketi ze-DRM. Akufanele idingeke ngezinhlelo zokusebenza ezivamile."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"bophezela kusevisi yomlayezo yenkampani yenethiwekhi"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Ivumela isibambi ukuhlanganisa isixhumanisi sokubona esiphezulu sesevisi yomlayezo yenkampani yenethiwekhi. Akufanele idingeke kuzinhlelo zokusebenza ezivamile."</string>
+    <string name="permlab_accessVoiceInteractionService" msgid="4183835260471435605">"hlanganyela nesevisi ebandakanyayo yezwi"</string>
+    <string name="permdesc_accessVoiceInteractionService" msgid="836587728238433459">"Vumela umbambi ukuthi ahlanganyele nesevisi yamanje esebenzayo yezwi. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi wokukhiya isikrini nama-PIN."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Gaka imizamo yokuvula isikrini"</string>
@@ -1119,6 +1153,10 @@
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Ivumela ukuthi isisetshenziswa siqinisekise ukuthi ngabe iphakheji iyafakeka."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bopha okokuqinisekisa iphakheji"</string>
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Ivumela umnikazi ukuthi enze izicelo zezinsiza eziqinisekisa iphakheji. Akumele kudingeke ekusetshenzisweni okujwayelekile."</string>
+    <string name="permlab_intentFilterVerificationAgent" msgid="1135788294400437497">"qinisekisa isihlungi esihlosiwe"</string>
+    <string name="permdesc_intentFilterVerificationAgent" msgid="5853902808424716312">"Ivumela uhlelo lokusebenza ukuthi lihlole uma ngabe isihlungi esihlosiwe siqinisekisiwe noma asiqinisekisiwe."</string>
+    <string name="permlab_bindIntentFilterVerifier" msgid="8567268159430779210">"hlanganisa kusiqinisekisi esihlosiwe sesihlungi"</string>
+    <string name="permdesc_bindIntentFilterVerifier" msgid="681128728719578778">"Ivumela umbambi ukuthi enze izicelo zeziqinisekisi ezihlosiwe zesihlungi. Akumele kudingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"finyelela kuma- serial port"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Ivumela umnikai ukuthi athole inombolo ye-serial ukue angene kwiindawo ze-serial esebenzisa i-SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"finyelela abahlinzeki bokuqukethwe ngaphandle"</string>
@@ -1544,6 +1582,8 @@
     <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Yehlisa usuku"</string>
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Khulisa unyaka"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Yehlisa unyaka"</string>
+    <string name="date_picker_prev_month_button" msgid="2858244643992056505">"Inyanga edlule"</string>
+    <string name="date_picker_next_month_button" msgid="5559507736887605055">"Inyanga ezayo"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"i-ALT"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Khansela"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Susa"</string>
@@ -1794,11 +1834,8 @@
     <string name="minute_picker_description" msgid="8606010966873791190">"Amaminithi weslayidi esiyindingilizi"</string>
     <string name="select_hours" msgid="6043079511766008245">"Khetha amahora"</string>
     <string name="select_minutes" msgid="3974345615920336087">"Khetha amaminithi"</string>
-    <string name="day_picker_description" msgid="8990847925961297968">"Igridi yenyanga yezinsuku"</string>
-    <string name="year_picker_description" msgid="5524331207436052403">"Uhlu lonyaka"</string>
     <string name="select_day" msgid="7774759604701773332">"Khetha inyanga nosuku"</string>
     <string name="select_year" msgid="7952052866994196170">"Khetha unyaka"</string>
-    <string name="item_is_selected" msgid="949687401682476608">"I-<xliff:g id="ITEM">%1$s</xliff:g> ekhethiwe"</string>
     <string name="deleted_key" msgid="7659477886625566590">"I-<xliff:g id="KEY">%1$s</xliff:g> isusiwe"</string>
     <string name="managed_profile_label_badge" msgid="2355652472854327647">"Umsebenzi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="lock_to_app_toast" msgid="7570091317001980053">"Ukuze ususe ukuphina kulesi sikrini, thinta uphinde ubambe i-Emuva ne-Buka konke ngesikhathi esisodwa."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b5576c5..eb37619 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2633,6 +2633,70 @@
             <enum name="paddedBounds" value="3" />
         </attr>
 
+        <!-- Defines the drawable to draw over the content. This can be used as an overlay.
+             The foreground drawable participates in the padding of the content if the gravity
+             is set to fill. -->
+        <attr name="foreground" format="reference|color" />
+        <!-- Defines the gravity to apply to the foreground drawable. The gravity defaults
+             to fill. -->
+        <attr name="foregroundGravity">
+            <!-- Push object to the top of its container, not changing its size. -->
+            <flag name="top" value="0x30" />
+            <!-- Push object to the bottom of its container, not changing its size. -->
+            <flag name="bottom" value="0x50" />
+            <!-- Push object to the left of its container, not changing its size. -->
+            <flag name="left" value="0x03" />
+            <!-- Push object to the right of its container, not changing its size. -->
+            <flag name="right" value="0x05" />
+            <!-- Place object in the vertical center of its container, not changing its size. -->
+            <flag name="center_vertical" value="0x10" />
+            <!-- Grow the vertical size of the object if needed so it completely fills its container. -->
+            <flag name="fill_vertical" value="0x70" />
+            <!-- Place object in the horizontal center of its container, not changing its size. -->
+            <flag name="center_horizontal" value="0x01" />
+            <!-- Grow the horizontal size of the object if needed so it completely fills its container. -->
+            <flag name="fill_horizontal" value="0x07" />
+            <!-- Place the object in the center of its container in both the vertical and horizontal axis, not changing its size. -->
+            <flag name="center" value="0x11" />
+            <!-- Grow the horizontal and vertical size of the object if needed so it completely fills its container. -->
+            <flag name="fill" value="0x77" />
+            <!-- Additional option that can be set to have the top and/or bottom edges of
+                 the child clipped to its container's bounds.
+                 The clip will be based on the vertical gravity: a top gravity will clip the bottom
+                 edge, a bottom gravity will clip the top edge, and neither will clip both edges. -->
+            <flag name="clip_vertical" value="0x80" />
+            <!-- Additional option that can be set to have the left and/or right edges of
+                 the child clipped to its container's bounds.
+                 The clip will be based on the horizontal gravity: a left gravity will clip the right
+                 edge, a right gravity will clip the left edge, and neither will clip both edges. -->
+            <flag name="clip_horizontal" value="0x08" />
+        </attr>
+        <!-- Defines whether the foreground drawable should be drawn inside the padding.
+             This property is turned on by default. -->
+        <attr name="foregroundInsidePadding" format="boolean" />
+        <!-- Tint to apply to the foreground. -->
+        <attr name="foregroundTint" format="color" />
+        <!-- Blending mode used to apply the foreground tint. -->
+        <attr name="foregroundTintMode">
+            <!-- The tint is drawn on top of the drawable.
+                 [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
+            <enum name="src_over" value="3" />
+            <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
+                 color channels are thrown out. [Sa * Da, Sc * Da] -->
+            <enum name="src_in" value="5" />
+            <!-- The tint is drawn above the drawable, but with the drawable’s alpha
+                 channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
+            <enum name="src_atop" value="9" />
+            <!-- Multiplies the color and alpha channels of the drawable with those of
+                 the tint. [Sa * Da, Sc * Dc] -->
+            <enum name="multiply" value="14" />
+            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+            <enum name="screen" value="15" />
+            <!-- Combines the tint and drawable color and alpha channels, clamping the
+                 result to valid color values. Saturate(S + D) -->
+            <enum name="add" value="16" />
+        </attr>
+
     </declare-styleable>
 
     <!-- Attributes that can be assigned to a tag for a particular View. -->
@@ -3366,72 +3430,9 @@
         <attr name="padding" />
     </declare-styleable>
     <declare-styleable name="FrameLayout">
-        <!-- Defines the drawable to draw over the content. This can be used as an overlay.
-             The foreground drawable participates in the padding of the content if the gravity
-             is set to fill. -->
-        <attr name="foreground" format="reference|color" />
-        <!-- Defines the gravity to apply to the foreground drawable. The gravity defaults
-             to fill. -->
-        <attr name="foregroundGravity">
-            <!-- Push object to the top of its container, not changing its size. -->
-            <flag name="top" value="0x30" />
-            <!-- Push object to the bottom of its container, not changing its size. -->
-            <flag name="bottom" value="0x50" />
-            <!-- Push object to the left of its container, not changing its size. -->
-            <flag name="left" value="0x03" />
-            <!-- Push object to the right of its container, not changing its size. -->
-            <flag name="right" value="0x05" />
-            <!-- Place object in the vertical center of its container, not changing its size. -->
-            <flag name="center_vertical" value="0x10" />
-            <!-- Grow the vertical size of the object if needed so it completely fills its container. -->
-            <flag name="fill_vertical" value="0x70" />
-            <!-- Place object in the horizontal center of its container, not changing its size. -->
-            <flag name="center_horizontal" value="0x01" />
-            <!-- Grow the horizontal size of the object if needed so it completely fills its container. -->
-            <flag name="fill_horizontal" value="0x07" />
-            <!-- Place the object in the center of its container in both the vertical and horizontal axis, not changing its size. -->
-            <flag name="center" value="0x11" />
-            <!-- Grow the horizontal and vertical size of the object if needed so it completely fills its container. -->
-            <flag name="fill" value="0x77" />
-            <!-- Additional option that can be set to have the top and/or bottom edges of
-                 the child clipped to its container's bounds.
-                 The clip will be based on the vertical gravity: a top gravity will clip the bottom
-                 edge, a bottom gravity will clip the top edge, and neither will clip both edges. -->
-            <flag name="clip_vertical" value="0x80" />
-            <!-- Additional option that can be set to have the left and/or right edges of
-                 the child clipped to its container's bounds.
-                 The clip will be based on the horizontal gravity: a left gravity will clip the right
-                 edge, a right gravity will clip the left edge, and neither will clip both edges. -->
-            <flag name="clip_horizontal" value="0x08" />
-        </attr>
-        <!-- Defines whether the foreground drawable should be drawn inside the padding.
-             This property is turned on by default. -->
-        <attr name="foregroundInsidePadding" format="boolean" />
         <!-- Determines whether to measure all children or just those in
              the VISIBLE or INVISIBLE state when measuring. Defaults to false. -->
         <attr name="measureAllChildren" format="boolean" />
-        <!-- Tint to apply to the foreground. -->
-        <attr name="foregroundTint" format="color" />
-        <!-- Blending mode used to apply the foreground tint. -->
-        <attr name="foregroundTintMode">
-            <!-- The tint is drawn on top of the drawable.
-                 [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
-            <enum name="src_over" value="3" />
-            <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
-                 color channels are thrown out. [Sa * Da, Sc * Da] -->
-            <enum name="src_in" value="5" />
-            <!-- The tint is drawn above the drawable, but with the drawable’s alpha
-                 channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
-            <enum name="src_atop" value="9" />
-            <!-- Multiplies the color and alpha channels of the drawable with those of
-                 the tint. [Sa * Da, Sc * Dc] -->
-            <enum name="multiply" value="14" />
-            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
-            <enum name="screen" value="15" />
-            <!-- Combines the tint and drawable color and alpha channels, clamping the
-                 result to valid color values. Saturate(S + D) -->
-            <enum name="add" value="16" />
-        </attr>
     </declare-styleable>
     <declare-styleable name="ExpandableListView">
         <!-- Indicator shown beside the group View. This can be a stateful Drawable. -->
@@ -3504,15 +3505,29 @@
         <!-- Sets a drawable as the content of this ImageView. -->
         <attr name="src" format="reference|color" />
         <!-- Controls how the image should be resized or moved to match the size
-             of this ImageView. -->
+             of this ImageView.  See {@link android.widget.ImageView.ScaleType} -->
         <attr name="scaleType">
+            <!-- Scale using the image matrix when drawing. See  
+                 {@link android.widget.ImageView#setImageMatrix(Matrix)}. -->
             <enum name="matrix" value="0" />
+            <!-- Scale the image using {@link android.graphics.Matrix.ScaleToFit#FILL}. -->
             <enum name="fitXY" value="1" />
+            <!-- Scale the image using {@link android.graphics.Matrix.ScaleToFit#START}. -->
             <enum name="fitStart" value="2" />
+            <!-- Scale the image using {@link android.graphics.Matrix.ScaleToFit#CENTER}. -->
             <enum name="fitCenter" value="3" />
+            <!-- Scale the image using {@link android.graphics.Matrix.ScaleToFit#END}. -->
             <enum name="fitEnd" value="4" />
+            <!-- Center the image in the view, but perform no scaling. -->
             <enum name="center" value="5" />
+            <!-- Scale the image uniformly (maintain the image's aspect ratio) so both dimensions 
+                 (width and height) of the image will be equal to or larger than the corresponding
+                 dimension of the view (minus padding). The image is then centered in the view. -->
             <enum name="centerCrop" value="6" />
+            <!-- Scale the image uniformly (maintain the image's aspect ratio) so that both
+                 dimensions (width and height) of the image will be equal to or less than the
+                 corresponding dimension of the view (minus padding). The image is then centered in
+                 the view. -->
             <enum name="centerInside" value="7" />
         </attr>
         <!-- Set this to true if you want the ImageView to adjust its bounds
@@ -4282,6 +4297,15 @@
         <attr name="letterSpacing" />
         <!-- Font feature settings. -->
         <attr name="fontFeatureSettings" />
+        <!-- Break strategy (control over paragraph layout). -->
+        <attr name="breakStrategy">
+            <!-- Line breaking uses simple strategy. -->
+            <enum name="simple" value="0" />
+            <!-- Line breaking uses high-quality strategy, including hyphenation. -->
+            <enum name="high_quality" value="1" />
+            <!-- Line breaking stratgegy balances line lengths. -->
+            <enum name="balanced" value="2" />
+        </attr>
     </declare-styleable>
     <declare-styleable name="TextViewAppearance">
         <!-- Base text color, typeface, size, and style. -->
@@ -4443,11 +4467,6 @@
     </declare-styleable>
 
     <declare-styleable name="DatePicker">
-        <!-- The first year (inclusive), for example "1940". {@deprecated Use minDate instead.} -->
-        <attr name="startYear" format="integer" />
-        <!-- The last year (inclusive), for example "2010". {@deprecated Use maxDate instead.} -->
-        <attr name="endYear" format="integer" />
-
         <!-- The first day of week according to {@link java.util.Calendar}. -->
         <attr name="firstDayOfWeek" />
         <!-- The minimal date shown by this calendar view in mm/dd/yyyy format. -->
@@ -4473,12 +4492,14 @@
         <!-- The background for the selected date header. -->
         <attr name="headerBackground" />
 
-        <!-- The list year's text appearance in the list. -->
+        <!-- The list year's text appearance in the list.
+             {@deprecated Use yearListTextColor. }-->
         <attr name="yearListItemTextAppearance" format="reference" />
         <!-- @hide The list year's text appearance in the list when activated. -->
         <attr name="yearListItemActivatedTextAppearance" format="reference" />
         <!-- The text color list of the calendar. -->
         <attr name="calendarTextColor" format="color" />
+
         <!-- Defines the look of the widget. Prior to the L release, the only choice was
              spinner. As of L, with the Material theme selected, the default layout is calendar,
              but this attribute can be used to force spinner to be used instead. -->
@@ -4489,17 +4510,29 @@
             <enum name="calendar" value="2" />
         </attr>
 
-        <!-- @deprecated The text appearance for the month (ex. May) in the selected date header. -->
+        <!-- The first year (inclusive), for example "1940".
+             {@deprecated Use minDate instead.} -->
+        <attr name="startYear" format="integer" />
+        <!-- The last year (inclusive), for example "2010".
+             {@deprecated Use maxDate instead.} -->
+        <attr name="endYear" format="integer" />
+        <!-- The text appearance for the month (ex. May) in the selected date header.
+             {@deprecated Use headerTextColor instead.} -->
         <attr name="headerMonthTextAppearance" format="reference" />
-        <!-- @deprecated The text appearance for the day of month (ex. 28) in the selected date header. -->
+        <!-- The text appearance for the day of month (ex. 28) in the selected date header.
+             {@deprecated Use headerTextColor instead.} -->
         <attr name="headerDayOfMonthTextAppearance" format="reference" />
-        <!-- The text appearance for the year (ex. 2014) in the selected date header. -->
+        <!-- The text appearance for the year (ex. 2014) in the selected date header.
+             {@deprecated Use headerTextColor instead.} -->
         <attr name="headerYearTextAppearance" format="reference" />
-        <!-- @deprecated The background color for the header's day of week. -->
+        <!-- The background color for the header's day of week.
+             {@deprecated No longer displayed.} -->
         <attr name="dayOfWeekBackground" format="color" />
-        <!-- @deprecated The text color for the header's day of week. -->
+        <!-- The text color for the header's day of week.
+             {@deprecated No longer displayed.} -->
         <attr name="dayOfWeekTextAppearance" format="reference" />
-        <!-- @deprecated The list year's selected circle color in the list. -->
+        <!-- The list year's selected circle color in the list.
+             {@deprecated No longer displayed.} -->
         <attr name="yearListSelectorColor" format="color" />
     </declare-styleable>
 
@@ -4786,24 +4819,27 @@
         <attr name="legacyLayout" format="reference" />
         <!-- @hide The layout of the time picker. -->
         <attr name="internalLayout" />
-        <!-- The text appearance for the AM/PM header. -->
-        <attr name="headerAmPmTextAppearance" format="reference" />
-        <!-- The text appearance for the time header. -->
-        <attr name="headerTimeTextAppearance" format="reference" />
+
+        <!-- The text color for the selected time header text, ex. "12" or
+             "PM". This should be a color state list where the activated state
+             will be used when the minute picker or hour picker is active.-->
+        <attr name="headerTextColor" />
         <!-- The background for the header containing the currently selected time. -->
         <attr name="headerBackground" />
-        <!-- The color for the hours/minutes numbers. -->
+
+        <!-- The color for the hours/minutes numbers. This should be a color
+             state list where the activated state will be used when the number
+             is active.-->
         <attr name="numbersTextColor" format="color" />
-        <!-- The color for the inner hours numbers used in 24-hour mode. -->
+        <!-- The color for the inner hours numbers used in 24-hour mode. This
+             should be a color state list where the activated state will be
+             used when the number is active.-->
         <attr name="numbersInnerTextColor" format="color" />
         <!-- The background color for the hours/minutes numbers. -->
         <attr name="numbersBackgroundColor" format="color" />
-        <!-- The color for the AM/PM selectors. -->
-        <attr name="amPmTextColor" format="color" />
-        <!-- The background color state list for the AM/PM selectors. -->
-        <attr name="amPmBackgroundColor" format="color" />
         <!-- The color for the hours/minutes selector. -->
         <attr name="numbersSelectorColor" format="color" />
+
         <!-- Defines the look of the widget. Prior to the L release, the only choice was
              spinner. As of L, with the Material theme selected, the default layout is clock,
              but this attribute can be used to force spinner to be used instead. -->
@@ -4813,6 +4849,19 @@
             <!-- Time picker with clock face to select the time. -->
             <enum name="clock" value="2" />
         </attr>
+
+        <!-- The text appearance for the AM/PM header.
+             @deprecated Use headerTextColor instead. -->
+        <attr name="headerAmPmTextAppearance" format="reference" />
+        <!-- The text appearance for the time header.
+             @deprecated Use headerTextColor instead. -->
+        <attr name="headerTimeTextAppearance" format="reference" />
+        <!-- The color for the AM/PM selectors.
+             {@deprecated Use headerTextColor instead.}-->
+        <attr name="amPmTextColor" format="color" />
+        <!-- The background color state list for the AM/PM selectors.
+             {@deprecated Use headerBackground instead.}-->
+        <attr name="amPmBackgroundColor" format="color" />
     </declare-styleable>
 
     <!-- ========================= -->
@@ -5935,6 +5984,9 @@
         <attr name="valueType" />
         <attr name="value" />
         <attr name="fraction" format="float" />
+        <!-- Defines a per-interval interpolator for this keyframe. This interpolator will be used
+             to interpolate between this keyframe and the previous keyframe.-->
+        <attr name="interpolator" />
     </declare-styleable>
 
     <!-- ========================== -->
@@ -7178,6 +7230,9 @@
              the component here for their recognition service. -->
         <attr name="recognitionService" format="string" />
         <attr name="settingsActivity" />
+        <!-- Flag indicating whether this voice interaction service is capable of handling the
+             assist gesture. -->
+        <attr name="supportsAssistGesture" format="boolean" />
     </declare-styleable>
 
     <!-- Use <code>voice-enrollment-application</code>
@@ -7733,6 +7788,8 @@
             <enum name="multi-select" value="4" />
             <enum name="integer" value="5" />
             <enum name="string" value="6" />
+            <enum name="bundle" value="7" />
+            <enum name="bundle_array" value="8" />
         </attr>
         <attr name="title" />
         <attr name="description" />
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index aefb67c..b0b4e3a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -389,13 +389,12 @@
          with the same {@link android.R.attr#taskAffinity} as it has. -->
     <attr name="allowTaskReparenting" format="boolean" />
 
-    <!-- Declare that this application may use cleartext traffic (e.g., HTTP rather than HTTPS;
-         WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP without STARTTLS or TLS).
-         Defaults to true. If set to false {@code false}, the app declares that it does not
-         intend to use cleartext network traffic, in which case platform components (e.g.,
-         HTTP stacks, {@code WebView}, {@code MediaPlayer}) will refuse app's requests to use
-         cleartext traffic. Third-party libraries are encouraged to honor this flag as well.
-         @hide -->
+    <!-- Declare that this application may use cleartext traffic, such as HTTP rather than HTTPS;
+         WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP without STARTTLS or TLS.
+         Defaults to true. If set to false {@code false}, the application declares that it does not
+         intend to use cleartext network traffic, in which case platform components (e.g. HTTP
+         stacks, {@code WebView}, {@code MediaPlayer}) will refuse applications's requests to use
+         cleartext traffic. Third-party libraries are encouraged to honor this flag as well. -->
     <attr name="usesCleartextTraffic" format="boolean" />
 
     <!-- Declare that code from this application will need to be loaded into other
@@ -1043,6 +1042,18 @@
          libraries in the apk must be stored and page-aligned.  -->
     <attr name="extractNativeLibs" format="boolean"/>
 
+    <!-- Specify whether an activity intent filter will need to be verified thru its set
+         of data URIs. This will only be used when the Intent's action is set to
+         {@link android.content.Intent#ACTION_VIEW Intent.ACTION_VIEW} and the Intent's category is
+         set to {@link android.content.Intent#CATEGORY_BROWSABLE Intent.CATEGORY_BROWSABLE} and the
+         intern filter data scheme is set to "http" or "https". When set to true, the intent filter
+         will need to use its data tag for getting the URIs to verify with.
+
+         For each URI, an HTTPS network request will be done to <code>/.well-known/associations.json</code>
+         host to verify that the web site is okay with the app intercepting the URI.
+         -->
+    <attr name="autoVerify" format="boolean" />
+
     <!-- The <code>manifest</code> tag is the root of an
          <code>AndroidManifest.xml</code> file,
          describing the contents of an Android package (.apk) file.  One
@@ -1164,13 +1175,13 @@
              "com.google". -->
         <attr name="requiredAccountType" format="string"/>
         <attr name="isGame" />
-        <!-- Declare that this application may use cleartext traffic (e.g., HTTP rather than HTTPS;
-             WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP without STARTTLS or TLS).
-             Defaults to true. If set to false {@code false}, the app declares that it does not
-             intend to use cleartext network traffic, in which case platform components (e.g.,
-             HTTP stacks, {@code WebView}, {@code MediaPlayer}) will refuse app's requests to use
-             cleartext traffic. Third-party libraries are encouraged to honor this flag as well.
-             @hide -->
+        <!-- Declare that this application may use cleartext traffic, such as HTTP rather than
+             HTTPS; WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP without STARTTLS or
+             TLS). Defaults to true. If set to false {@code false}, the application declares that it
+             does not intend to use cleartext network traffic, in which case platform components
+             (e.g. HTTP stacks, {@code WebView}, {@code MediaPlayer}) will refuse applications's
+             requests to use cleartext traffic. Third-party libraries are encouraged to honor this
+             flag as well. -->
         <attr name="usesCleartextTraffic" />
         <attr name="multiArch" />
         <attr name="extractNativeLibs" />
@@ -1841,6 +1852,7 @@
         <attr name="banner" />
         <attr name="logo" />
         <attr name="priority" />
+        <attr name="autoVerify" />
     </declare-styleable>
     
     <!-- Attributes that can be supplied in an AndroidManifest.xml
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 37c9598..e879244 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -471,6 +471,18 @@
     <!-- Wifi driver supports batched scan -->
     <bool translatable="false" name="config_wifi_batched_scan_supported">false</bool>
 
+    <!-- Idle Receive current for wifi radio. 0 by default-->
+    <integer translatable="false" name="config_wifi_idle_receive_cur_ma">1</integer>
+
+    <!-- Rx current for wifi radio. 0 by default-->
+    <integer translatable="false" name="config_wifi_active_rx_cur_ma">2</integer>
+
+    <!-- Tx current for wifi radio. 0 by default-->
+    <integer translatable="false" name="config_wifi_tx_cur_ma">3</integer>
+
+    <!-- Operating volatage for wifi radio. 0 by default-->
+    <integer translatable="false" name="config_wifi_operating_voltage_mv">4</integer>
+
     <!-- Flag indicating whether the we should enable the automatic brightness in Settings.
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
@@ -1112,6 +1124,18 @@
          device does not support multiple advertisement-->
     <integer translatable="false" name="config_bluetooth_max_advertisers">0</integer>
 
+    <!-- Idle current for bluetooth controller. 0 by default-->
+    <integer translatable="false" name="config_bluetooth_idle_cur_ma">1</integer>
+
+    <!-- Rx current for bluetooth controller. 0 by default-->
+    <integer translatable="false" name="config_bluetooth_rx_cur_ma">2</integer>
+
+    <!-- Tx current for bluetooth controller. 0 by default-->
+    <integer translatable="false" name="config_bluetooth_tx_cur_ma">3</integer>
+
+    <!-- Operating volatage for bluetooth controller. 0 by default-->
+    <integer translatable="false" name="config_bluetooth_operating_voltage_mv">4</integer>
+
     <!-- The default data-use polling period. -->
     <integer name="config_datause_polling_period_sec">600</integer>
 
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 6c6d2cc..7d08e7f 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -364,26 +364,32 @@
 
     <dimen name="resolver_max_width">480dp</dimen>
 
-     <!-- Size of the offset applied to the position of the circular mask. This is only
-     used on circular displays. In the case where there is no "chin", this will default
-     to 0 -->
-     <dimen name="circular_display_mask_offset">0px</dimen>
+    <!-- Size of the offset applied to the position of the circular mask. This
+         is only used on circular displays. In the case where there is no
+         "chin", this will default to 0 -->
+    <dimen name="circular_display_mask_offset">0px</dimen>
+    <!-- Amount to reduce the size of the circular mask by (to compensate for
+         aliasing effects). This is only used on circular displays. -->
+    <dimen name="circular_display_mask_thickness">1px</dimen>
 
-     <!-- Amount to reduce the size of the circular mask by (to compensate for aliasing
-     effects). This is only used on circular displays. -->
-     <dimen name="circular_display_mask_thickness">1px</dimen>
+    <dimen name="lock_pattern_dot_line_width">3dp</dimen>
+    <dimen name="lock_pattern_dot_size">12dp</dimen>
+    <dimen name="lock_pattern_dot_size_activated">28dp</dimen>
 
-     <dimen name="lock_pattern_dot_line_width">3dp</dimen>
-     <dimen name="lock_pattern_dot_size">12dp</dimen>
-     <dimen name="lock_pattern_dot_size_activated">28dp</dimen>
+    <dimen name="text_handle_min_size">40dp</dimen>
 
-     <dimen name="text_handle_min_size">40dp</dimen>
+    <!-- Lighting and shadow properties -->
+    <dimen name="light_y">-200dp</dimen>
+    <dimen name="light_z">800dp</dimen>
+    <dimen name="light_radius">600dp</dimen>
+    <item type="dimen" format="float" name="ambient_shadow_alpha">0.075</item>
+    <item type="dimen" format="float" name="spot_shadow_alpha">0.15</item>
 
-     <!-- Lighting and shadow properties -->
-     <dimen name="light_y">-200dp</dimen>
-     <dimen name="light_z">800dp</dimen>
-     <dimen name="light_radius">600dp</dimen>
-     <item type="dimen" format="float" name="ambient_shadow_alpha">0.075</item>
-     <item type="dimen" format="float" name="spot_shadow_alpha">0.15</item>
-
+     <!-- Floating toolbar dimensions -->
+     <dimen name="floating_toolbar_height">48dp</dimen>
+     <dimen name="floating_toolbar_menu_button_side_padding">8dp</dimen>
+     <dimen name="floating_toolbar_text_size">14sp</dimen>
+     <dimen name="floating_toolbar_menu_button_minimum_width">48dp</dimen>
+     <dimen name="floating_toolbar_default_width">250dp</dimen>
+     <dimen name="floating_toolbar_minimum_overflow_height">192dp</dimen>
 </resources>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 6108b27..aaf252a 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -93,4 +93,10 @@
   <item type="id" name="undo" />
   <item type="id" name="redo" />
   <item type="id" name="replaceText" />
+
+  <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SHOW_ON_SCREEN}. -->
+  <item type="id" name="accessibilityActionShowOnScreen" />
+
+  <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_TO_POSITION}. -->
+  <item type="id" name="accessibilityActionScrollToPosition" />
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5e4b039..24d17a4 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2646,10 +2646,17 @@
   <public type="id" name="undo" />
   <public type="id" name="redo" />
   <public type="id" name="replaceText" />
+  <public type="id" name="accessibilityActionShowOnScreen" />
+  <public type="id" name="accessibilityActionScrollToPosition" />
 
   <public type="attr" name="allowUndo" />
-
   <public type="attr" name="colorBackgroundFloating" />
-
   <public type="attr" name="extractNativeLibs" />
+  <public type="attr" name="usesCleartextTraffic" />
+
+  <!--IntentFilter auto verification -->
+  <public type="attr" name="autoVerify" />
+  <public type="attr" name="breakStrategy" />
+
+  <public type="attr" name="supportsAssistGesture" />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7672e93..7dc3ff7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -249,8 +249,20 @@
     <string name="wfcRegErrorTitle">Wi-Fi Calling</string>
     <!-- WFC Operator Error Codes -->
     <string-array name="wfcOperatorErrorCodes" translatable="false" />
-    <!-- WFC Operator Error Messages -->
-    <string-array name="wfcOperatorErrorMessages" />
+    <!-- WFC Operator Error Messages showed as alerts -->
+    <string-array name="wfcOperatorErrorAlertMessages" />
+    <!-- WFC Operator Error Messages showed as notifications -->
+    <string-array name="wfcOperatorErrorNotificationMessages" />
+    <!-- Template for showing cellular network operator name while WFC is active -->
+    <string name="wfcSpnFormat">%s</string>
+    <!-- WFC, summary for Disabled -->
+    <string name="wifi_calling_off_summary">Off</string>
+    <!-- WFC, summary for Wi-Fi Preferred -->
+    <string name="wfc_mode_wifi_preferred_summary">Wi-Fi preferred</string>
+    <!-- WFC, summary for Cellular Preferred -->
+    <string name="wfc_mode_cellular_preferred_summary">Cellular preferred</string>
+    <!-- WFC, summary for Wi-Fi Only -->
+    <string name="wfc_mode_wifi_only_summary">Wi-Fi only</string>
 
     <!--
         {0} is one of "bearerServiceCode*"
@@ -1756,6 +1768,8 @@
     <string name="permlab_cameraDisableTransmitLed">disable transmit indicator LED when camera is in use</string>
     <!-- Description of a camera app permission, listed so the user can choose whether or not they want to allow it to disable the may-transmit light indicator. -->
     <string name="permdesc_cameraDisableTransmitLed">Allows a pre-installed system application to disable the camera use indicator LED.</string>
+    <!-- Description of a camera app permission, listed so that the user can send the camera service notifications about system-wide events. -->
+    <string name="permdesc_cameraSendSystemEvent">Allows a pre-installed system application to send the camera service system events.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_brick" product="tablet">permanently disable tablet</string>
@@ -1885,6 +1899,10 @@
     <string name="permdesc_performCdmaProvisioning">Allows the app to start CDMA provisioning.
         Malicious apps may unnecessarily start CDMA provisioning.</string>
 
+    <string name="permlab_performSimActivation">start SIM card setup</string>
+    <string name="permdesc_performSimActivation">Allows the app to handle SIM activation requests.
+        The app may directly perform activation or may delegate to another app.</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_locationUpdates">control location update notifications</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -2226,6 +2244,36 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_useFingerprint">Allows the app to use fingerprint hardware for authentication</string>
 
+    <!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
+    <string name="fingerprint_acquired_partial">Partial fingerprint detected. Please try again.</string>
+    <!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
+    <string name="fingerprint_acquired_insufficient">Couldn\'t process fingerprint. Please try again.</string>
+    <!-- Message shown during fingerprint acquisision when the fingerprint sensor needs cleaning -->
+    <string name="fingerprint_acquired_imager_dirty">Fingerprint sensor is dirty. Please clean and try again.</string>
+    <!-- Message shown during fingerprint acquisision when the user removes their finger from the sensor too quickly -->
+    <string name="fingerprint_acquired_too_fast">Finger moved to fast. Please try again.</string>
+    <!-- Message shown during fingerprint acquisision when the user moves their finger too slowly -->
+    <string name="fingerprint_acquired_too_slow">Finger moved to slow. Please try again.</string>
+    <!-- Array containing custom messages shown during fingerprint acquisision from vendor.  Vendor is expected to add and translate these strings -->
+    <string-array name="fingerprint_acquired_vendor">
+        <item>Vendor-specific acquisition error message 0</item>
+    </string-array>
+
+    <!-- Generic error message shown when the fingerprint hardware can't recognize the fingerprint -->
+    <string name="fingerprint_error_unable_to_process">Unable to process. Try again.</string>
+    <!-- Error message shown when the fingerprint hardware can't be accessed -->
+    <string name="fingerprint_error_hw_not_available">Hardware not available.</string>
+    <!-- Error message shown when the fingerprint hardware has run out of room for storing fingerprints -->
+    <string name="fingerprint_error_no_space">Fingerprint can\'t be stored. Please remove an existing fingerprint.</string>
+    <!-- Error message shown when the fingerprint hardware timer has expired and the user needs to restart the operation. -->
+    <string name="fingerprint_error_timeout">Fingerprint time out reached. Try again.</string>
+    <!-- Error message shown when the fingerprint hardware timer has expired and the user needs to restart the operation. -->
+    <string name="fingerprint_error_vendor">Fingerprint time out reached. Try again.</string>
+    <!-- Array containing custom error messages from vendor.  Vendor is expected to add and translate these strings -->
+    <string-array name="fingerprint_error_vendor">
+        <item>Vendor-specifc error message.</item>
+    </string-array>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_readSyncSettings">read sync settings</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -2414,6 +2462,11 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_bindCarrierMessagingService">Allows the holder to bind to the top-level interface of a carrier messaging service. Should never be needed for normal apps.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_accessVoiceInteractionService">interact with voice interaction service</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_accessVoiceInteractionService">Allows the holder to interact with the currently active voice interaction service. Should never be needed for normal apps.</string>
+
     <!-- Policy administration -->
 
     <!-- Title of policy access to limiting the user's password choices -->
@@ -3335,6 +3388,22 @@
     <string name="permdesc_bindPackageVerifier">Allows the holder to make requests of
         package verifiers. Should never be needed for normal apps.</string>
 
+    <!-- Title of an application permission which allows the application to verify whether
+         a different intent filter is able to be verified by some internal logic. [CHAR LIMIT=40] -->
+    <string name="permlab_intentFilterVerificationAgent">verify intent filter</string>
+    <!-- Description of an application permission which allows the application to verify whether
+         a different intent filter is able to be verified by some internal heuristic. [CHAR LIMIT=NONE] -->
+    <string name="permdesc_intentFilterVerificationAgent">Allows the app to check if an intent filter
+        is verified or not.</string>
+
+    <!-- Title of an application permission which allows the application to verify whether
+         a different intent filter is able to be verified by some internal logic. [CHAR LIMIT=40] -->
+    <string name="permlab_bindIntentFilterVerifier">bind to an intent filter verifier</string>
+    <!-- Description of an application permission which allows the application to verify whether
+         a different intent filter is able to be verified by some internal logic. [CHAR LIMIT=NONE] -->
+    <string name="permdesc_bindIntentFilterVerifier">Allows the holder to make requests of
+        intent filter verifiers. Should never be needed for normal apps.</string>
+
     <!-- Title of an application permission which allows the application to access serial ports via the SerialManager. [CHAR LIMIT=40] -->
     <string name="permlab_serialPort">access serial ports</string>
     <!-- Description of an application permission which allows the application access serial ports via the SerialManager. [CHAR LIMIT=NONE] -->
@@ -4383,6 +4452,10 @@
     <string name="date_picker_increment_year_button">Increase year</string>
     <!-- Description of the button to decrease the DatePicker's year value. [CHAR LIMIT=NONE] -->
     <string name="date_picker_decrement_year_button">Decrease year</string>
+    <!-- Description of the button to move to the previous month. [CHAR LIMIT=NONE] -->
+    <string name="date_picker_prev_month_button">Previous month</string>
+    <!-- Description of the button to move to the next month. [CHAR LIMIT=NONE] -->
+    <string name="date_picker_next_month_button">Next month</string>
 
     <!-- KeyboardView - accessibility support -->
     <!-- Description of the Alt button in a KeyboardView. [CHAR LIMIT=NONE] -->
@@ -5046,8 +5119,6 @@
     <string name="select_day">Select month and day</string>
     <!-- Accessibility announcement for the year picker [CHAR LIMIT=NONE] -->
     <string name="select_year">Select year</string>
-    <!-- Accessibility description for the item that is currently selected. -->
-    <string name="item_is_selected"><xliff:g id="item" example="2013">%1$s</xliff:g> selected</string>
     <!-- Accessibility announcement when a number that had been typed in is deleted [CHAR_LIMIT=NONE] -->
     <string name="deleted_key"><xliff:g id="key" example="4">%1$s</xliff:g> deleted</string>
 
@@ -5091,6 +5162,11 @@
     <!-- Lock-to-app unlock password string -->
     <string name="lock_to_app_unlock_password">Ask for password before unpinning</string>
 
+    <!-- Notification shown when device owner silently installs a package -->
+    <string name="package_installed_device_owner">Installed by your administrator</string>
+    <!-- Notification shown when device owner silently deletes a package -->
+    <string name="package_deleted_device_owner">Deleted by your administrator</string>
+
     <!-- [CHAR_LIMIT=NONE] Battery saver: Feature description -->
     <string name="battery_saver_description">To help improve battery life, battery saver reduces your device’s performance and limits vibration, location services, and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging.</string>
 
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index cc64b43..3c3d286 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -497,6 +497,7 @@
         <item name="textEditSideNoPasteWindowLayout">?attr/textEditSideNoPasteWindowLayout</item>
         <item name="textEditSuggestionItemLayout">?attr/textEditSuggestionItemLayout</item>
         <item name="textCursorDrawable">?attr/textCursorDrawable</item>
+        <item name="breakStrategy">high_quality</item>
     </style>
 
     <style name="Widget.CheckedTextView">
@@ -527,6 +528,7 @@
         <item name="textAppearance">?attr/textAppearanceMediumInverse</item>
         <item name="textColor">?attr/editTextColor</item>
         <item name="gravity">center_vertical</item>
+        <item name="breakStrategy">simple</item>
     </style>
 
     <style name="Widget.ExpandableListView" parent="Widget.ListView">
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 223578d..23ac221 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -240,10 +240,6 @@
     <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
     <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse"/>
     <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Menu" parent="TextAppearance.Material.Widget.ActionBar.Menu"/>
-    <style name="TextAppearance.DeviceDefault.DatePicker.DayOfWeekLabel" parent="TextAppearance.Material.DatePicker.DayOfWeekLabel"/>
-    <style name="TextAppearance.DeviceDefault.DatePicker.MonthLabel" parent="TextAppearance.Material.DatePicker.MonthLabel"/>
-    <style name="TextAppearance.DeviceDefault.DatePicker.DayOfMonthLabel" parent="TextAppearance.Material.DatePicker.DayOfMonthLabel"/>
-    <style name="TextAppearance.DeviceDefault.DatePicker.YearLabel" parent="TextAppearance.Material.DatePicker.YearLabel"/>
 
     <!-- Preference Styles -->
     <style name="Preference.DeviceDefault" parent="Preference.Material"/>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index f1f7462..9cf7884 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -381,40 +381,22 @@
 
     <style name="TextAppearance.Material.TimePicker.TimeLabel" parent="TextAppearance.Material">
         <item name="textSize">@dimen/timepicker_time_label_size</item>
-        <item name="textColor">@color/time_picker_header_text_material</item>
+        <item name="textColor">@color/primary_text_secondary_when_activated_material_inverse</item>
     </style>
 
     <style name="TextAppearance.Material.TimePicker.AmPmLabel" parent="TextAppearance.Material.Button">
         <item name="textSize">@dimen/timepicker_ampm_label_size</item>
-        <item name="textColor">@color/time_picker_header_text_material</item>
-    </style>
-
-    <style name="TextAppearance.Material.DatePicker.DayOfWeekLabel" parent="TextAppearance.Material">
-        <item name="includeFontPadding">false</item>
-        <item name="textColor">?attr/textColorPrimaryInverse</item>
-        <item name="textSize">@dimen/datepicker_header_text_size</item>
-    </style>
-
-    <style name="TextAppearance.Material.DatePicker.MonthLabel" parent="TextAppearance.Material">
-        <item name="includeFontPadding">false</item>
-        <item name="textColor">@color/date_picker_header_text_material</item>
-        <item name="textSize">@dimen/datepicker_selected_date_month_size</item>
-    </style>
-
-    <style name="TextAppearance.Material.DatePicker.DayOfMonthLabel" parent="TextAppearance.Material">
-        <item name="includeFontPadding">false</item>
-        <item name="textColor">@color/date_picker_header_text_material</item>
-        <item name="textSize">@dimen/datepicker_selected_date_day_size</item>
+        <item name="textColor">@color/primary_text_secondary_when_activated_material_inverse</item>
     </style>
 
     <style name="TextAppearance.Material.DatePicker.YearLabel" parent="TextAppearance.Material">
-        <item name="textColor">@color/date_picker_header_text_material</item>
+        <item name="textColor">@color/primary_text_secondary_when_activated_material_inverse</item>
         <item name="textSize">@dimen/date_picker_year_label_size</item>
         <item name="fontFamily">sans-serif-medium</item>
     </style>
 
     <style name="TextAppearance.Material.DatePicker.DateLabel" parent="TextAppearance.Material">
-        <item name="textColor">@color/date_picker_header_text_material</item>
+        <item name="textColor">@color/primary_text_secondary_when_activated_material_inverse</item>
         <item name="textSize">@dimen/date_picker_date_label_size</item>
         <item name="fontFamily">sans-serif-medium</item>
     </style>
@@ -660,8 +642,7 @@
         <item name="legacyLayout">@layout/time_picker_legacy_material</item>
         <!-- Attributes for new-style TimePicker. -->
         <item name="internalLayout">@layout/time_picker_material</item>
-        <item name="headerTimeTextAppearance">@style/TextAppearance.Material.TimePicker.TimeLabel</item>
-        <item name="headerAmPmTextAppearance">@style/TextAppearance.Material.TimePicker.AmPmLabel</item>
+        <item name="headerTextColor">@color/primary_text_secondary_when_activated_material</item>
         <item name="headerBackground">#ff555555</item>
         <item name="numbersTextColor">?attr/textColorPrimaryActivated</item>
         <item name="numbersInnerTextColor">?attr/textColorSecondaryActivated</item>
@@ -676,8 +657,7 @@
         <item name="calendarViewShown">true</item>
         <!-- Attributes for new-style DatePicker. -->
         <item name="internalLayout">@layout/date_picker_material</item>
-        <item name="yearListItemTextAppearance">@style/TextAppearance.Material.DatePicker.List.YearLabel</item>
-        <item name="yearListItemActivatedTextAppearance">@style/TextAppearance.Material.DatePicker.List.YearLabel.Activated</item>
+        <item name="headerTextColor">@color/primary_text_secondary_when_activated_material</item>
         <item name="headerBackground">#ff555555</item>
     </style>
 
@@ -1033,11 +1013,13 @@
     <style name="Widget.Material.Light.NumberPicker" parent="Widget.Material.NumberPicker"/>
 
     <style name="Widget.Material.Light.TimePicker" parent="Widget.Material.TimePicker">
+        <item name="headerTextColor">@color/primary_text_secondary_when_activated_material_inverse</item>
         <item name="headerBackground">?attr/colorAccent</item>
         <item name="numbersBackgroundColor">#ffeeeeee</item>
     </style>
 
     <style name="Widget.Material.Light.DatePicker" parent="Widget.Material.DatePicker">
+        <item name="headerTextColor">@color/primary_text_secondary_when_activated_material_inverse</item>
         <item name="headerBackground">?attr/colorAccent</item>
     </style>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c4e9e8e..b4ba316 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -328,6 +328,10 @@
   <java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
   <java-symbol type="string"  name="config_wifi_random_mac_oui" />
   <java-symbol type="integer"  name="config_wifi_network_switching_blacklist_time" />
+  <java-symbol type="integer"  name="config_wifi_idle_receive_cur_ma" />
+  <java-symbol type="integer"  name="config_wifi_active_rx_cur_ma" />
+  <java-symbol type="integer"  name="config_wifi_tx_cur_ma" />
+  <java-symbol type="integer"  name="config_wifi_operating_voltage_mv" />
 
   <java-symbol type="bool" name="editable_voicemailnumber" />
 
@@ -349,6 +353,10 @@
   <java-symbol type="integer" name="config_burnInProtectionMinVerticalOffset" />
   <java-symbol type="integer" name="config_burnInProtectionMaxVerticalOffset" />
   <java-symbol type="integer" name="config_burnInProtectionMaxRadius" />
+  <java-symbol type="integer" name="config_bluetooth_idle_cur_ma" />
+  <java-symbol type="integer" name="config_bluetooth_rx_cur_ma" />
+  <java-symbol type="integer" name="config_bluetooth_tx_cur_ma" />
+  <java-symbol type="integer" name="config_bluetooth_operating_voltage_mv" />
   <java-symbol type="integer" name="config_cursorWindowSize" />
   <java-symbol type="integer" name="config_drawLockTimeoutMillis" />
   <java-symbol type="integer" name="config_doublePressOnPowerBehavior" />
@@ -686,6 +694,8 @@
   <java-symbol type="string" name="lock_to_app_unlock_pin" />
   <java-symbol type="string" name="lock_to_app_unlock_pattern" />
   <java-symbol type="string" name="lock_to_app_unlock_password" />
+  <java-symbol type="string" name="package_installed_device_owner" />
+  <java-symbol type="string" name="package_deleted_device_owner" />
   <java-symbol type="string" name="lockscreen_access_pattern_cell_added" />
   <java-symbol type="string" name="lockscreen_access_pattern_cleared" />
   <java-symbol type="string" name="lockscreen_access_pattern_detected" />
@@ -755,7 +765,13 @@
   <java-symbol type="string" name="phoneTypeWorkPager" />
   <java-symbol type="string" name="wfcRegErrorTitle" />
   <java-symbol type="array" name="wfcOperatorErrorCodes" />
-  <java-symbol type="array" name="wfcOperatorErrorMessages" />
+  <java-symbol type="array" name="wfcOperatorErrorAlertMessages" />
+  <java-symbol type="array" name="wfcOperatorErrorNotificationMessages" />
+  <java-symbol type="string" name="wfcSpnFormat" />
+  <java-symbol type="string" name="wifi_calling_off_summary" />
+  <java-symbol type="string" name="wfc_mode_wifi_preferred_summary" />
+  <java-symbol type="string" name="wfc_mode_cellular_preferred_summary" />
+  <java-symbol type="string" name="wfc_mode_wifi_only_summary" />
   <java-symbol type="string" name="policydesc_disableCamera" />
   <java-symbol type="string" name="policydesc_encryptedStorage" />
   <java-symbol type="string" name="policydesc_expirePassword" />
@@ -1158,6 +1174,7 @@
   <java-symbol type="drawable" name="ic_audio_vol" />
   <java-symbol type="drawable" name="ic_audio_vol_mute" />
   <java-symbol type="drawable" name="ic_bullet_key_permission" />
+  <java-symbol type="drawable" name="ic_check_circle_24px" />
   <java-symbol type="drawable" name="ic_contact_picture" />
   <java-symbol type="drawable" name="ic_dialog_usb" />
   <java-symbol type="drawable" name="ic_emergency" />
@@ -2035,7 +2052,6 @@
   <java-symbol type="integer" name="config_downtime_condition_lookahead_threshold_hrs" />
   <java-symbol type="string" name="muted_by" />
 
-  <java-symbol type="string" name="item_is_selected" />
   <java-symbol type="string" name="select_day" />
   <java-symbol type="string" name="select_year" />
 
@@ -2061,6 +2077,19 @@
   <!-- From KeyguardServiceDelegate -->
   <java-symbol type="string" name="config_keyguardComponent" />
 
+  <!-- Fingerprint messages -->
+  <java-symbol type="string" name="fingerprint_error_unable_to_process" />
+  <java-symbol type="string" name="fingerprint_error_hw_not_available" />
+  <java-symbol type="string" name="fingerprint_error_no_space" />
+  <java-symbol type="string" name="fingerprint_error_timeout" />
+  <java-symbol type="array" name="fingerprint_error_vendor" />
+  <java-symbol type="string" name="fingerprint_acquired_partial" />
+  <java-symbol type="string" name="fingerprint_acquired_insufficient" />
+  <java-symbol type="string" name="fingerprint_acquired_imager_dirty" />
+  <java-symbol type="string" name="fingerprint_acquired_too_slow" />
+  <java-symbol type="string" name="fingerprint_acquired_too_fast" />
+  <java-symbol type="array" name="fingerprint_acquired_vendor" />
+
   <!-- From various Material changes -->
   <java-symbol type="attr" name="titleTextAppearance" />
   <java-symbol type="attr" name="subtitleTextAppearance" />
@@ -2172,6 +2201,30 @@
   <java-symbol type="style" name="TextAppearance.Material.Widget.Calendar.Month" />
   <java-symbol type="style" name="TextAppearance.Material.Widget.Calendar.DayOfWeek" />
   <java-symbol type="style" name="TextAppearance.Material.Widget.Calendar.Day" />
+  <java-symbol type="style" name="TextAppearance.Material.DatePicker.List.YearLabel" />
+  <java-symbol type="style" name="TextAppearance.Material.DatePicker.List.YearLabel.Activated" />
   <java-symbol type="dimen" name="day_picker_padding_top"/>
   <java-symbol type="dimen" name="date_picker_day_of_week_height"/>
+
+  <java-symbol type="string" name="storage_internal" />
+  <java-symbol type="string" name="storage_sd_card" />
+  <java-symbol type="string" name="storage_usb" />
+
+  <!-- Floating toolbar -->
+  <java-symbol type="layout" name="floating_popup_container" />
+  <java-symbol type="layout" name="floating_popup_menu_button" />
+  <java-symbol type="layout" name="floating_popup_open_overflow_button" />
+  <java-symbol type="dimen" name="floating_toolbar_height" />
+  <java-symbol type="dimen" name="floating_toolbar_menu_button_side_padding" />
+  <java-symbol type="dimen" name="floating_toolbar_text_size" />
+  <java-symbol type="dimen" name="floating_toolbar_menu_button_minimum_width" />
+  <java-symbol type="dimen" name="floating_toolbar_default_width" />
+  <java-symbol type="dimen" name="floating_toolbar_minimum_overflow_height" />
+
+  <java-symbol type="drawable" name="ic_chevron_left" />
+  <java-symbol type="drawable" name="ic_chevron_right" />
+  <java-symbol type="string" name="date_picker_prev_month_button" />
+  <java-symbol type="string" name="date_picker_next_month_button" />
+  <java-symbol type="layout" name="date_picker_month_item_material" />
+  <java-symbol type="id" name="month_view" />
 </resources>
diff --git a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
new file mode 100644
index 0000000..1a50432
--- /dev/null
+++ b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
@@ -0,0 +1,82 @@
+/*
+ * 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.net;
+
+import com.google.caliper.Param;
+import com.google.caliper.SimpleBenchmark;
+
+public class NetworkStatsBenchmark extends SimpleBenchmark {
+    private static final String UNDERLYING_IFACE = "wlan0";
+    private static final String TUN_IFACE = "tun0";
+    private static final int TUN_UID = 999999999;
+
+    @Param({"100", "1000"})
+    private int mSize;
+    private NetworkStats mNetworkStats;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mNetworkStats = new NetworkStats(0, mSize + 2);
+        int uid = 0;
+        NetworkStats.Entry recycle = new NetworkStats.Entry();
+        for (int i = 0; i < mSize; i++) {
+            recycle.iface = (i < mSize / 2) ? TUN_IFACE : UNDERLYING_IFACE;
+            recycle.uid = uid;
+            recycle.set = i % 2;
+            recycle.tag = NetworkStats.TAG_NONE;
+            recycle.rxBytes = 60000;
+            recycle.rxPackets = 60;
+            recycle.txBytes = 150000;
+            recycle.txPackets = 1500;
+            recycle.operations = 0;
+            mNetworkStats.addValues(recycle);
+            if (recycle.set == 1) {
+                uid++;
+            }
+        }
+        recycle.iface = UNDERLYING_IFACE;
+        recycle.uid = TUN_UID;
+        recycle.set = NetworkStats.SET_FOREGROUND;
+        recycle.tag = NetworkStats.TAG_NONE;
+        recycle.rxBytes = 90000 * mSize;
+        recycle.rxPackets = 40 * mSize;
+        recycle.txBytes = 180000 * mSize;
+        recycle.txPackets = 1200 * mSize;
+        recycle.operations = 0;
+        mNetworkStats.addValues(recycle);
+    }
+
+    public void timeMigrateTun(int reps) {
+        for (int i = 0; i < reps; i++) {
+            NetworkStats stats = mNetworkStats.clone();
+            stats.migrateTun(TUN_UID, TUN_IFACE, UNDERLYING_IFACE);
+        }
+    }
+
+    /**
+     * Since timeMigrateTun() includes a clone() call on the NetworkStats object,
+     * we need to measure the cost of the clone() call itself in order to get more
+     * accurate measurement on the migrateTun() method.
+     */
+    public void timeClone(int reps) {
+        for (int i = 0; i < reps; i++) {
+            NetworkStats stats = mNetworkStats.clone();
+        }
+    }
+}
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index bfaea8f..b07d338 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -113,6 +113,9 @@
     <application android:theme="@style/Theme">
         <uses-library android:name="android.test.runner" />
         <uses-library android:name="org.apache.http.legacy" android:required="false" />
+        <meta-data
+            android:name="android.content.APP_RESTRICTIONS"
+            android:resource="@xml/app_restrictions" />
         <activity android:name="android.view.ViewAttachTestActivity" android:label="View Attach Test">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/core/tests/coretests/res/values/strings.xml b/core/tests/coretests/res/values/strings.xml
index ce0d9a2..04b0478 100644
--- a/core/tests/coretests/res/values/strings.xml
+++ b/core/tests/coretests/res/values/strings.xml
@@ -135,4 +135,8 @@
     <string name="first">Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.</string>
     <string name="actor">Abe Lincoln</string>
     <string name="caption">Lincoln adressing the crowd at Gettysburgh</string>
+
+    <!-- RestrictionsManagerTest -->
+    <string name="restrictionManager_title">Title</string>
+    <string name="restrictionManager_desc">Description</string>
 </resources>
diff --git a/core/tests/coretests/res/xml/app_restrictions.xml b/core/tests/coretests/res/xml/app_restrictions.xml
new file mode 100644
index 0000000..c84cabcc
--- /dev/null
+++ b/core/tests/coretests/res/xml/app_restrictions.xml
@@ -0,0 +1,55 @@
+<?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.
+-->
+
+<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
+    <restriction android:key="hidden_key"
+                 android:restrictionType="hidden"/>
+    <restriction
+            android:defaultValue="true"
+            android:description="@string/restrictionManager_desc"
+            android:key="bool_key"
+            android:restrictionType="bool"
+            android:title="@string/restrictionManager_title"/>
+    <restriction
+            android:defaultValue="test"
+            android:key="string_key"
+            android:restrictionType="string"/>
+
+    <restriction android:key="int_key"
+                 android:restrictionType="integer"
+                 android:defaultValue="15"/>
+    <restriction android:key="bundle_key"
+                 android:restrictionType="bundle">
+        <restriction
+                android:key="bundle_string_key"
+                android:restrictionType="string"/>
+        <restriction
+                android:defaultValue="true"
+                android:key="bundle_bool_key"
+                android:restrictionType="bool"/>
+
+    </restriction>
+    <restriction android:key="bundle_array_key"
+                 android:restrictionType="bundle_array">
+        <restriction android:key="bundle_array_int"
+                     android:restrictionType="integer"/>
+        <restriction android:key="bundle_array_bundle_key"
+                     android:restrictionType="bundle">
+            <restriction android:key="bundle_array_bundle_int_key"
+                         android:restrictionType="integer"/>
+        </restriction>
+    </restriction>
+</restrictions>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/content/RestrictionsManagerTest.java b/core/tests/coretests/src/android/content/RestrictionsManagerTest.java
new file mode 100644
index 0000000..8921924
--- /dev/null
+++ b/core/tests/coretests/src/android/content/RestrictionsManagerTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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;
+
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.test.AndroidTestCase;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class RestrictionsManagerTest extends AndroidTestCase {
+    private RestrictionsManager mRm;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mRm = (RestrictionsManager) mContext.getSystemService(Context.RESTRICTIONS_SERVICE);
+    }
+
+    public void testGetManifestRestrictions() {
+        String packageName = getContext().getPackageName();
+        List<RestrictionEntry> manifestRestrictions = mRm.getManifestRestrictions(packageName);
+        assertEquals(6, manifestRestrictions.size());
+        Set<String> verifiedKeys = new HashSet<>(Arrays.asList("bundle_key", "bundle_array_key",
+                "bundle_array_bundle_key"));
+        for (RestrictionEntry entry : manifestRestrictions) {
+            if ("bundle_key".equals(entry.getKey())) {
+                assertEquals("bundle_key entry should have 2 children entries",
+                        2, entry.getRestrictions().length);
+                verifiedKeys.remove(entry.getKey());
+            } else if ("bundle_array_key".equals(entry.getKey())) {
+                assertEquals("bundle_array_key should have 2 children entries",
+                        2, entry.getRestrictions().length);
+                assertNotNull(entry.getRestrictions());
+                for (RestrictionEntry childEntry : entry.getRestrictions()) {
+                    if ("bundle_array_bundle_key".equals(childEntry.getKey())) {
+                        assertNotNull(childEntry.getRestrictions());
+                        assertEquals("bundle_array_bundle_key should have 1 child entry",
+                                1, childEntry.getRestrictions().length);
+                        verifiedKeys.remove(childEntry.getKey());
+                    }
+                }
+                verifiedKeys.remove(entry.getKey());
+            }
+        }
+        assertTrue("Entries" + verifiedKeys + " were not found", verifiedKeys.isEmpty());
+    }
+
+    public void testConvertRestrictionsToBundle() {
+        String packageName = getContext().getPackageName();
+        List<RestrictionEntry> manifestRestrictions = mRm.getManifestRestrictions(packageName);
+        Bundle bundle = RestrictionsManager.convertRestrictionsToBundle(manifestRestrictions);
+        assertEquals(6, bundle.size());
+        Bundle childBundle = bundle.getBundle("bundle_key");
+        assertNotNull(childBundle);
+        assertEquals(2, childBundle.size());
+        Parcelable[] childBundleArray = bundle.getParcelableArray("bundle_array_key");
+        assertEquals(2, childBundleArray.length);
+    }
+
+}
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index fd922a2..a470de1 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -18,6 +18,8 @@
 
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.SET_FOREGROUND;
+import static android.net.NetworkStats.SET_DBG_VPN_IN;
+import static android.net.NetworkStats.SET_DBG_VPN_OUT;
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.TAG_NONE;
@@ -346,7 +348,7 @@
             .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
 
         assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface));
-        assertEquals(17, delta.size());
+        assertEquals(21, delta.size());
 
         // tunIface and TEST_IFACE entries are not changed.
         assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE,
@@ -377,14 +379,33 @@
                 0L, 0L, 0L, 0L, 0L);
 
         // New entries are added for new application's underlying Iface traffic
-        assertValues(delta, 13, underlyingIface, 10120, SET_DEFAULT, TAG_NONE,
+        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE,
                 72667L, 197L, 41872l, 219L, 0L);
-        assertValues(delta, 14, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE,
+        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE,
                 9297L, 17L, 3936, 19L, 0L);
-        assertValues(delta, 15, underlyingIface, 10120, SET_DEFAULT, testTag1,
+        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1,
                 21691L, 41L, 13179L, 46L, 0L);
-        assertValues(delta, 16, underlyingIface, 10120, SET_FOREGROUND, testTag1,
+        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1,
                 1281L, 2L, 634L, 1L, 0L);
+
+        // New entries are added for debug purpose
+        assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE,
+                39605L, 46L, 11690, 49, 0);
+        assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE,
+                81964, 214, 45808, 238, 0);
+        assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE,
+                4983, 10, 1717, 10, 0);
+        assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE,
+                126552, 270, 59215, 297, 0);
+
+    }
+
+    private static void assertContains(NetworkStats stats,  String iface, int uid, int set,
+            int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
+        int index = stats.findIndex(iface, uid, set, tag);
+        assertTrue(index != -1);
+        assertValues(stats, index, iface, uid, set, tag,
+                rxBytes, rxPackets, txBytes, txPackets, operations);
     }
 
     private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set,
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index cd45017..6fa28b1 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -804,4 +804,56 @@
         assertFalse(Uri.parse("content://com.example/path/path").isPathPrefixMatch(
                 Uri.parse("content://com.example/path%2Fpath")));
     }
+
+    public void testToSafeString() {
+        checkToSafeString("tel:xxxxxx", "tel:Google");
+        checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890");
+        checkToSafeString("tEl:xxx.xxx-xxxx", "tEl:123.456-7890");
+
+        checkToSafeString("sms:xxxxxx", "sms:123abc");
+        checkToSafeString("smS:xxx.xxx-xxxx", "smS:123.456-7890");
+
+        checkToSafeString("smsto:xxxxxx", "smsto:123abc");
+        checkToSafeString("SMSTo:xxx.xxx-xxxx", "SMSTo:123.456-7890");
+
+        checkToSafeString("mailto:xxxxxxx@xxxxxxx.xxx", "mailto:android@android.com");
+        checkToSafeString("Mailto:xxxxxxx@xxxxxxx.xxxxxxxxxx",
+                "Mailto:android@android.com/secret");
+
+        checkToSafeString("sip:xxxxxxx@xxxxxxx.xxxxxxxx", "sip:android@android.com:1234");
+        checkToSafeString("sIp:xxxxxxx@xxxxxxx.xxx", "sIp:android@android.com");
+
+        checkToSafeString("http://www.android.com/...", "http://www.android.com");
+        checkToSafeString("HTTP://www.android.com/...", "HTTP://www.android.com");
+        checkToSafeString("http://www.android.com/...", "http://www.android.com/");
+        checkToSafeString("http://www.android.com/...", "http://www.android.com/secretUrl?param");
+        checkToSafeString("http://www.android.com/...",
+                "http://user:pwd@www.android.com/secretUrl?param");
+        checkToSafeString("http://www.android.com/...",
+                "http://user@www.android.com/secretUrl?param");
+        checkToSafeString("http://www.android.com/...", "http://www.android.com/secretUrl?param");
+        checkToSafeString("http:///...", "http:///path?param");
+        checkToSafeString("http:///...", "http://");
+        checkToSafeString("http://:12345/...", "http://:12345/");
+
+        checkToSafeString("https://www.android.com/...", "https://www.android.com/secretUrl?param");
+        checkToSafeString("https://www.android.com:8443/...",
+                "https://user:pwd@www.android.com:8443/secretUrl?param");
+        checkToSafeString("https://www.android.com/...", "https://user:pwd@www.android.com");
+        checkToSafeString("Https://www.android.com/...", "Https://user:pwd@www.android.com");
+
+        checkToSafeString("ftp://ftp.android.com/...", "ftp://ftp.android.com/");
+        checkToSafeString("ftP://ftp.android.com/...", "ftP://anonymous@ftp.android.com/");
+        checkToSafeString("ftp://ftp.android.com:2121/...",
+                "ftp://root:love@ftp.android.com:2121/");
+
+        checkToSafeString("unsupported://ajkakjah/askdha/secret?secret",
+                "unsupported://ajkakjah/askdha/secret?secret");
+        checkToSafeString("unsupported:ajkakjah/askdha/secret?secret",
+                "unsupported:ajkakjah/askdha/secret?secret");
+    }
+
+    private void checkToSafeString(String expectedSafeString, String original) {
+        assertEquals(expectedSafeString, Uri.parse(original).toSafeString());
+    }
 }
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 38321a3..a0b26f3 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -49,6 +49,8 @@
 ################################
 # Do not include Motoya on space-constrained devices
 ifneq ($(SMALLER_FONT_FOOTPRINT),true)
+# Do not include Motoya if we are including full NotoSans
+ifneq ($(FONT_NOTOSANS_FULL),true)
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := MTLmr3m.ttf
@@ -59,6 +61,7 @@
 include $(BUILD_PREBUILT)
 extra_font_files += MTLmr3m.ttf
 
+endif  # !FONT_NOTOSANS_FULL
 endif  # !SMALLER_FONT_FOOTPRINT
 
 ################################
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 42b5d5d..5c3b90b 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -181,6 +181,18 @@
     </family>
     <family>
         <fileset>
+            <file variant="elegant">NotoSansOriya-Regular.ttf</file>
+            <file variant="elegant">NotoSansOriya-Bold.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
+            <file variant="compact">NotoSansOriyaUI-Regular.ttf</file>
+            <file variant="compact">NotoSansOriyaUI-Bold.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
             <file>NotoSansSinhala-Regular.ttf</file>
             <file>NotoSansSinhala-Bold.ttf</file>
         </fileset>
@@ -355,11 +367,6 @@
     </family>
     <family>
         <fileset>
-            <file>Lohit-Odia.ttf</file>
-        </fileset>
-    </family>
-    <family>
-        <fileset>
             <file lang="zh-Hans">NotoSansHans-Regular.otf</file>
         </fileset>
     </family>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 37527e9..f3a7647 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -191,6 +191,14 @@
         <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansKannadaUI-Bold.ttf</font>
     </family>
+    <family variant="elegant">
+        <font weight="400" style="normal">NotoSansOriya-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
+    </family>
+    <family variant="compact">
+        <font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font>
+        <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
+    </family>
     <family>
         <font weight="400" style="normal">NotoSansSinhala-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansSinhala-Bold.ttf</font>
@@ -299,9 +307,6 @@
     <family>
         <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
     </family>
-    <family>
-        <font weight="400" style="normal">Lohit-Odia.ttf</font>
-    </family>
     <family lang="zh-Hans">
         <font weight="400" style="normal">NotoSansHans-Regular.otf</font>
     </family>
diff --git a/docs/html/google/auth/http-auth.jd b/docs/html/google/auth/http-auth.jd
index 804ba12..7d34d89 100644
--- a/docs/html/google/auth/http-auth.jd
+++ b/docs/html/google/auth/http-auth.jd
@@ -95,7 +95,7 @@
 </pre>
 <p>For example, you're using a debug-key with Eclipse, then the command looks like this:</p>
 <pre class="no-pretty-print">
-keytool -exportcert -alias androiddebugkey-keystore ~/.android/debug.keystore -list -v
+keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v
 </pre>
 <p>Then the keystore password is "android".</p>
 </li>
diff --git a/docs/html/google/gcm/c2dm.jd b/docs/html/google/gcm/c2dm.jd
index 6ae7c1a..d0f8c71 100644
--- a/docs/html/google/gcm/c2dm.jd
+++ b/docs/html/google/gcm/c2dm.jd
@@ -33,7 +33,10 @@
 </div>
 </div>
 
-<p>Android Cloud to Device Messaging (C2DM) is deprecated. The C2DM service will continue to be maintained in the short term, but C2DM will accept no new users, and it will grant no new quotas. <strong>C2DM developers are strongly encouraged to move to Google Cloud Messaging (GCM)</strong>. GCM is the next generation of C2DM.</p>
+<p>Android Cloud to Device Messaging (C2DM) was officially deprecated on June 26, 2012, and has been
+ shut down completely as of April 1, 2015.  <strong>C2DM developers are strongly encouraged to move
+  to Google Cloud Messaging (GCM)</strong>. GCM is the next generation of C2DM.</p>
+
 <p>This document is addressed to  C2DM developers who are moving to GCM. It describes the differences between GCM and C2DM, and explains how to migrate existing C2DM apps to GCM.</p>
 
 
diff --git a/docs/html/guide/index.jd b/docs/html/guide/index.jd
index d78a1b1..cb4f65c 100644
--- a/docs/html/guide/index.jd
+++ b/docs/html/guide/index.jd
@@ -30,7 +30,7 @@
 work in the background.</p>
 
 <p>From one component you can start another component using an <em>intent</em>. You can even start
-a component in a different app, such an activity in a maps app to show an address. This model
+a component in a different app, such as an activity in a maps app to show an address. This model
 provides multiple entry points for a single app and allows any app to behave as a user's "default"
 for an action that other apps may invoke.</p>
 
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index c1256f9..99e64d9 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -13,10 +13,11 @@
           android:<a href="#clear">clearTaskOnLaunch</a>=["true" | "false"]
           android:<a href="#config">configChanges</a>=["mcc", "mnc", "locale",
                                  "touchscreen", "keyboard", "keyboardHidden",
-                                 "navigation", "screenLayout", "fontScale", "uiMode",
-                                 "orientation", "screenSize", "smallestScreenSize"]
-          android:<a href="#dlmode">documentLaunchMode</a>=["intoExisting", "always",
-                                  "none", "never"]
+                                 "navigation", "screenLayout", "fontScale",
+                                 "uiMode", "orientation", "screenSize",
+                                 "smallestScreenSize"]
+          android:<a href="#dlmode">documentLaunchMode</a>=["intoExisting" | "always" |
+                                  "none" | "never"]
           android:<a href="#enabled">enabled</a>=["true" | "false"]
           android:<a href="#exclude">excludeFromRecents</a>=["true" | "false"]
           android:<a href="#exported">exported</a>=["true" | "false"]
diff --git a/docs/html/images/tv/channel-info.png b/docs/html/images/tv/channel-info.png
new file mode 100644
index 0000000..5a48078
--- /dev/null
+++ b/docs/html/images/tv/channel-info.png
Binary files differ
diff --git a/docs/html/images/tv/do-not-attempt.png b/docs/html/images/tv/do-not-attempt.png
new file mode 100644
index 0000000..18a8775
--- /dev/null
+++ b/docs/html/images/tv/do-not-attempt.png
Binary files differ
diff --git a/docs/html/images/tv/prog-guide.png b/docs/html/images/tv/prog-guide.png
new file mode 100644
index 0000000..caa2278
--- /dev/null
+++ b/docs/html/images/tv/prog-guide.png
Binary files differ
diff --git a/docs/html/images/tv/tvinput-life.png b/docs/html/images/tv/tvinput-life.png
new file mode 100644
index 0000000..fc53f89
--- /dev/null
+++ b/docs/html/images/tv/tvinput-life.png
Binary files differ
diff --git a/docs/html/tools/revisions/build-tools.jd b/docs/html/tools/revisions/build-tools.jd
index b08fbcf..e8706c1 100644
--- a/docs/html/tools/revisions/build-tools.jd
+++ b/docs/html/tools/revisions/build-tools.jd
@@ -78,6 +78,19 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>Build Tools, Revision 22.0.1</a> <em>(March 2015)</em>
+  </p>
+  <div class="toggle-content-toggleme">
+    <p>Fixed compatibility issues with
+    <a href="{@docRoot}guide/topics/renderscript/compute.html">RenderScript</a> kernels on
+    Android 4.4 (API level 19) to Android 4.1 (API level 16) devices.</p>
+  </div>
+</div>
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>Build Tools, Revision 22.0.0</a> <em>(March 2015)</em>
   </p>
   <div class="toggle-content-toggleme">
diff --git a/docs/html/tools/testing-support-library/index.jd b/docs/html/tools/testing-support-library/index.jd
index aeace8e..c8c9ef5 100644
--- a/docs/html/tools/testing-support-library/index.jd
+++ b/docs/html/tools/testing-support-library/index.jd
@@ -391,7 +391,9 @@
 
   <p>
     To learn more about using Espresso, see the
-    <a href="{@docRoot}reference/android/support/test/package-summary.html">API reference</a>.
+    <a href="{@docRoot}reference/android/support/test/package-summary.html">API reference</a> and
+    <a href="{@docRoot}training/testing/ui-testing/espresso-testing.html">
+      Testing UI for a Single App</a> training.
   </p>
 
   <h3 id="UIAutomator">
@@ -531,7 +533,9 @@
 
   <p>
     To learn more about using UI Automator, see the
-    <a href="{@docRoot}reference/android/support/test/package-summary.html">API reference</a>.
+    <a href="{@docRoot}reference/android/support/test/package-summary.html">API reference</a> and
+    <a href="{@docRoot}training/testing/ui-testing/uiautomator-testing.html">
+      Testing UI for Multiple Apps</a> training.
   </p>
 
   <h2 id="setup">
diff --git a/docs/html/training/auto/start/index.jd b/docs/html/training/auto/start/index.jd
index 54500ac..22e7521 100644
--- a/docs/html/training/auto/start/index.jd
+++ b/docs/html/training/auto/start/index.jd
@@ -55,14 +55,6 @@
 setting up your development environment and meeting the the minimum requirements
 to enable an app to communicate with Auto.</p>
 
-<p class="note"><strong>Important:</strong> If you are planning to develop
-apps for Auto, you are encouraged to begin enabling and testing your
-apps now. However, Auto-enabled apps cannot be published at this time.
-Join the
-<a href="http://g.co/AndroidAutoDev" class="external-link">Auto
-Developers Google+ community</a> for updates on when you will be able to submit
-your Auto-enabled apps.</p>
-
 <h2 id="dev-project">Set Up an Auto Project</h2>
 <p>This section describes how to create a new app or modify an existing app to
 communicate with Auto.</p>
diff --git a/docs/html/training/custom-views/optimizing-view.jd b/docs/html/training/custom-views/optimizing-view.jd
index 7f2e762..022618b 100644
--- a/docs/html/training/custom-views/optimizing-view.jd
+++ b/docs/html/training/custom-views/optimizing-view.jd
@@ -12,33 +12,21 @@
     <div id="tb">
 
         <h2>This lesson teaches you to</h2>
-        <ol>
-            <li><a href="#less">Do Less, Less Frequently</a></li>
-            <li><a href="#accelerate">Use Hardware Acceleration</a></li>
-        </ol>
-
-        <h2>You should also read</h2>
         <ul>
-            <li><a href="{@docRoot}guide/topics/graphics/hardware-accel.html">
-                Hardware Acceleration
-            </a>
-        </li>
-    </ul>
-<h2>Try it out</h2>
-<div class="download-box">
-<a href="{@docRoot}shareables/training/CustomView.zip"
-class="button">Download the sample</a>
-<p class="filename">CustomView.zip</p>
-</div>
-</div>
+            <li><a href="#less">Do Less, Less Frequently</a></li>
+        </ul>
+        <h2>Try it out</h2>
+        <div class="download-box">
+            <a href="{@docRoot}shareables/training/CustomView.zip"
+                class="button">Download the sample</a>
+            <p class="filename">CustomView.zip</p>
         </div>
-
+    </div>
+</div>
 
 <p>Now that you have a well-designed view that responds to gestures and transitions between states,
-you need to ensure
-that the view runs fast. To avoid a UI that feels sluggish or stutters during playback, you must
-ensure that your
-animations consistently run at 60 frames per second.</p>
+ensure that the view runs fast. To avoid a UI that feels sluggish or stutters during playback,
+ensure that animations consistently run at 60 frames per second.</p>
 
 <h2 id="less">Do Less, Less Frequently</h2>
 
@@ -52,19 +40,13 @@
 allocation while an
 animation is running.</p>
 
-<p>In addition to making {@link android.view.View#onDraw onDraw()} leaner, you should also make sure
+<p>In addition to making {@link android.view.View#onDraw onDraw()} leaner, also make sure
 it's called as
 infrequently as possible. Most calls to {@link android.view.View#onDraw onDraw()} are the result of
 a call to {@link
 android.view.View#invalidate() invalidate()}, so eliminate unnecessary calls to {@link
 android.view.View#invalidate()
-invalidate()}. When possible, call the four-parameter variant of {@link
-android.view.View#invalidate() invalidate()}
-rather than the version that takes no parameters. The no-parameter variant invalidates the entire
-view, while the
-four-parameter variant invalidates only a specified portion of the view. This approach allows draw calls to
-be more efficient and
-can eliminate unnecessary invalidation of views that fall outside the invalid rectangle.</p>
+invalidate()}.</p>
 
 <p>Another very expensive operation is traversing layouts. Any time a view calls {@link
 android.view.View#requestLayout()
@@ -78,7 +60,7 @@
 as shallow as
 possible.</p>
 
-<p>If you have a complex UI, you should consider writing a custom {@link android.view.ViewGroup
+<p>If you have a complex UI, consider writing a custom {@link android.view.ViewGroup
 ViewGroup} to perform
 its layout. Unlike the built-in views, your custom view can make application-specific assumptions
 about the size and
@@ -88,89 +70,3 @@
 views, but it never
 measures them. Instead, it sets their sizes directly according to its own custom layout
 algorithm.</p>
-
-<h2 id="accelerate">Use Hardware Acceleration</h2>
-
-<p>As of Android 3.0, the Android 2D graphics system can be accelerated by the GPU (Graphics
-Processing Unit) hardware
-found in most newer Android devices. GPU hardware acceleration can result in a tremendous
-performance increase for many
-applications, but it isn't the right choice for every application. The Android framework
-gives you the ability to finely control which parts of your application are or are not
-hardware accelerated.</p>
-
-<p>See <a href="{@docRoot}guide/topics/graphics/hardware-accel.html">Hardware Acceleration</a>
-        in the Android Developers Guide for directions on how to enable acceleration at the
-        application, activity, or window level. Notice  that in addition to the directions in
-        the developer guide, you must also set your application's target API to 11 or higher by
-        specifying {@code &lt;uses-sdk
-        android:targetSdkVersion="11"/&gt;} in your {@code AndroidManifest.xml} file.</p>
-
-<p>Once you've enabled hardware acceleration, you may or may not see a performance increase.
-Mobile GPUs are very good at certain tasks, such as scaling, rotating, and translating
-bitmapped images. They are not particularly good at other tasks, such as drawing lines or curves. To
-get the most out of GPU acceleration, you should maximize the number of operations that the GPU is
-good at, and minimize the number of operations that the GPU isn't good at.</p>
-
-<p>In the PieChart example, for instance, drawing the pie is relatively expensive. Redrawing the pie
-each time it's
-rotated causes the UI to feel sluggish. The solution is to place the pie chart into a child
-{@link android.view.View} and set that
-{@link android.view.View}'s
-<a href="{@docRoot}reference/android/view/View.html#setLayerType(int, android.graphics.Paint)">
-    layer type</a> to {@link android.view.View#LAYER_TYPE_HARDWARE}, so that the GPU can cache it as
-a static
-image. The sample
-defines the child view as an inner class of {@code PieChart}, which minimizes the amount of code
-changes that are needed
-to implement this solution.</p>
-
-<pre>
-   private class PieView extends View {
-
-       public PieView(Context context) {
-           super(context);
-           if (!isInEditMode()) {
-               setLayerType(View.LAYER_TYPE_HARDWARE, null);
-           }
-       }
-       
-       &#64;Override
-       protected void onDraw(Canvas canvas) {
-           super.onDraw(canvas);
-
-           for (Item it : mData) {
-               mPiePaint.setShader(it.mShader);
-               canvas.drawArc(mBounds,
-                       360 - it.mEndAngle,
-                       it.mEndAngle - it.mStartAngle,
-                       true, mPiePaint);
-           }
-       }
-
-       &#64;Override
-       protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-           mBounds = new RectF(0, 0, w, h);
-       }
-
-       RectF mBounds;
-   }
-</pre>
-
-<p>After this code change, {@code PieChart.PieView.onDraw()} is called only when the view is first
-shown. During the rest
-of the application's lifetime, the pie chart is cached as an image, and redrawn at different
-rotation angles by the GPU.
-GPU hardware is particularly good at this sort of thing, and the performance difference is
-immediately noticeable.</p>
-
-<p>There is a tradeoff, though. Caching images as hardware layers consumes video memory, which is a
-limited resource.
-For this reason, the final version of {@code PieChart.PieView} only sets its layer type to
-{@link android.view.View#LAYER_TYPE_HARDWARE}
-while the user is actively scrolling. At all other times, it sets its layer type to
-{@link android.view.View#LAYER_TYPE_NONE}, which
-allows the GPU to stop caching the image.</p>
-
-<p>Finally, don't forget to profile your code. Techniques that improve performance on one view
-might negatively affect performance on another.</p>
diff --git a/docs/html/training/testing/ui-testing/espresso-testing.jd b/docs/html/training/testing/ui-testing/espresso-testing.jd
new file mode 100644
index 0000000..85f4ba4
--- /dev/null
+++ b/docs/html/training/testing/ui-testing/espresso-testing.jd
@@ -0,0 +1,579 @@
+page.title=Testing UI for a Single App
+page.tags=testing,espresso
+trainingnavtop=true
+
+@jd:body
+
+<!-- This is the training bar -->
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dependencies and Prerequisites</h2>
+
+        <ul>
+          <li>Android 2.2 (API level 8) or higher
+          </li>
+
+          <li>
+            <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support
+            Library</a>
+          </li>
+        </ul>
+
+        <h2>
+          This lesson teaches you to
+        </h2>
+
+        <ol>
+          <li>
+            <a href="#setup">Set Up Espresso</a>
+          </li>
+
+          <li>
+            <a href="#build">Create an Espresso Test Class</a>
+          </li>
+
+          <li>
+            <a href="#run">Run Espresso Tests on a Device or Emulator</a>
+          </li>
+        </ol>
+
+        <h2>
+          You should also read
+        </h2>
+
+        <ul>
+           <li><a href="{@docRoot}reference/android/support/test/package-summary.html">
+              Espresso API Reference</a></li>
+        </ul>
+
+        <h2>
+          Try it out
+        </h2>
+
+        <ul>
+          <li>
+            <a href="https://github.com/googlesamples/android-testing"
+            class="external-link">Espresso Code Samples</a>
+          </li>
+        </ul>
+      </div>
+    </div>
+
+    <p>
+      Testing user interactions
+      within a single app helps to ensure that users do not
+      encounter unexpected results or have a poor experience when interacting with your app.
+      You should get into the habit of creating user interface (UI) tests if you need to verify
+      that the UI of your app is functioning correctly.
+    </p>
+
+    <p>
+      The Espresso testing framework, provided by the
+      <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>,
+      provides APIs for writing UI tests to simulate user interactions within a
+      single target app. Espresso tests can run on devices running Android 2.2 (API level 8) and
+      higher. A key benefit of using Espresso is that it provides automatic synchronization of test
+      actions with the UI of the app you are testing. Espresso detects when the main thread is idle,
+      so it is able to run your test commands at the appropriate time, improving the reliability of
+      your tests. This capability also relieves you from having to adding any timing workarounds,
+      such as a sleep period, in your test code.
+    </p>
+
+    <p>
+      The Espresso testing framework is an instrumentation-based API and works
+      with the
+      <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code
+      AndroidJUnitRunner}</a> test runner.
+    </p>
+
+    <h2 id="setup">
+      Set Up Espresso
+    </h2>
+
+    <p>
+      Before you begin using Espresso, you must:
+    </p>
+
+    <ul>
+      <li>
+        <strong>Install the Android Testing Support Library</strong>. The Espresso API is
+        located under the {@code com.android.support.test.espresso} package. These classes allow
+        you to create tests that use the Espresso testing framework. To learn how to install the
+        library, see <a href="{@docRoot}tools/testing-support-library/index.html#setup">
+        Testing Support Library Setup</a>.
+      </li>
+
+      <li>
+        <strong>Set up your project structure.</strong> In your Gradle project, the source code for
+        the target app that you want to test is typically placed under the {@code app/src/main}
+        folder. The source code for instrumentation tests, including
+        your Espresso tests, must be placed under the <code>app/src/androidTest</code> folder. To
+        learn more about setting up your project directory, see
+        <a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.
+      </li>
+
+      <li>
+        <strong>Specify your Android testing dependencies</strong>. In order for the
+        <a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for Gradle</a> to
+        correctly build and run your Espresso tests, you must specify the following libraries in
+        the {@code build.gradle} file of your Android app module:
+
+        <pre>
+dependencies {
+    androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
+    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
+}
+</pre>
+      </li>
+
+      <li>
+        <strong>Turn off animations on your test device.</strong> Leaving system animations turned
+        on in the test device might cause unexpected results or may lead your test to fail. Turn
+        off animations from <em>Settings</em> by opening <em>Developing Options</em> and
+        turning all the following options off:
+        <ul>
+          <li>
+            <em>Window animation scale</em>
+          </li>
+
+          <li>
+            <em>Transition animation scale</em>
+          </li>
+
+          <li>
+            <em>Animator duration scale</em>
+          </li>
+        </ul>
+      </li>
+    </ul>
+
+    <h2 id="build">
+      Create an Espresso Test Class
+    </h2>
+
+    <p>
+      To create an Espresso test, create a Java class or an
+      {@link android.test.ActivityInstrumentationTestCase2}
+      subclass that follows this programming model:
+    </p>
+
+    <ol>
+      <li>Find the UI component you want to test in an {@link android.app.Activity} (for example, a
+      sign-in button in the app) by calling the
+      <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
+        {@code onView()}</a> method, or the
+      <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">
+      {@code onData()}</a> method for {@link android.widget.AdapterView} controls.
+      </li>
+
+      <li>Simulate a specific user interaction to perform on that UI component, by calling the
+      <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code ViewInteraction.perform()}</a>
+      or
+      <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code DataInteraction.perform()}</a>
+      method and passing in the user action (for example, click on the sign-in button). To sequence
+      multiple actions on the same UI component, chain them using a comma-separated list in your
+      method argument.
+      </li>
+
+      <li>Repeat the steps above as necessary, to simulate a user flow across multiple
+      activities in the target app.
+      </li>
+
+      <li>Use the
+    <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html">{@code ViewAssertions}</a>
+        methods to check that the UI reflects the expected
+      state or behavior, after these user interactions are performed.
+      </li>
+    </ol>
+
+    <p>
+      These steps are covered in more detail in the sections below.
+    </p>
+
+    <p>
+      The following code snippet shows how your test class might invoke this basic workflow:
+    </p>
+
+<pre>
+onView(withId(R.id.my_view))            // withId(R.id.my_view) is a ViewMatcher
+        .perform(click())               // click() is a ViewAction
+        .check(matches(isDisplayed())); // matches(isDisplayed()) is a ViewAssertion
+</pre>
+
+    <h3 id="espresso-aitc2">
+      Using Espresso with ActivityInstrumentationTestCase2
+    </h3>
+
+    <p>
+      If you are subclassing {@link android.test.ActivityInstrumentationTestCase2}
+      to create your Espresso test class, you must inject an
+      {@link android.app.Instrumentation} instance into your test class. This step is required in
+      order for your Espresso test to run with the
+      <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
+      test runner.
+    </p>
+
+    <p>
+      To do this, call the
+      {@link android.test.InstrumentationTestCase#injectInstrumentation(android.app.Instrumentation) injectInstrumentation()}
+      method and pass in the result of
+      <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html#getInstrumentation()">
+      {@code InstrumentationRegistry.getInstrumentation()}</a>, as shown in the following code
+      example:
+    </p>
+
+<pre>
+import android.support.test.InstrumentationRegistry;
+
+public class MyEspressoTest
+        extends ActivityInstrumentationTestCase2&lt;MyActivity&gt; {
+
+    private MyActivity mActivity;
+
+    public MyEspressoTest() {
+        super(MyActivity.class);
+    }
+
+    &#64;Before
+    public void setUp() throws Exception {
+        super.setUp();
+        injectInstrumentation(InstrumentationRegistry.getInstrumentation());
+        mActivity = getActivity();
+    }
+
+   ...
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> Previously, {@link android.test.InstrumentationTestRunner}
+would inject the {@link android.app.Instrumentation} instance, but this test runner is being
+deprecated.</p>
+
+    <h3 id="accessing-ui-components">
+      Accessing UI Components
+    </h3>
+
+    <p>
+      Before Espresso can interact with the app under test, you must first specify the UI component
+      or <em>view</em>. Espresso supports the use of
+<a href="http://hamcrest.org/" class="external-link">Hamcrest matchers</a>
+      for specifying views and adapters in your app.
+    </p>
+
+    <p>
+      To find the view, call the <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
+      {@code onView()}</a>
+      method and pass in a view matcher that specifies the view that you are targeting. This is
+      described in more detail in <a href="#specifying-view-matcher">Specifying a View Matcher</a>.
+      The <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
+      {@code onView()}</a> method returns a
+      <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html">
+      {@code ViewInteraction}</a>
+      object that allows your test to interact with the view.
+      However, calling  the <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
+      {@code onView()}</a> method may not work if you want to locate a view in
+      an {@link android.widget.AdapterView} layout. In this case, follow the instructions in
+      <a href="#locating-adpeterview-view">Locating a view in an AdapterView</a> instead.
+    </p>
+
+    <p class="note">
+      <strong>Note</strong>: The <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
+      {@code onView()}</a> method does not check if the view you specified is
+      valid. Instead, Espresso searches only the current view hierarchy, using the matcher provided.
+      If no match is found, the method throws a
+      <a href="{@docRoot}reference/android/support/test/espresso/NoMatchingViewException.html">
+      {@code NoMatchingViewException}</a>.
+    </p>
+
+    <p>
+      The following code snippet shows how you might write a test that accesses an
+      {@link android.widget.EditText} field, enters a string of text, closes the virtual keyboard,
+      and then performs a button click.
+    </p>
+
+<pre>
+public void testChangeText_sameActivity() {
+    // Type text and then press the button.
+    onView(withId(R.id.editTextUserInput))
+            .perform(typeText(STRING_TO_BE_TYPED), closeSoftKeyboard());
+    onView(withId(R.id.changeTextButton)).perform(click());
+
+    // Check that the text was changed.
+    ...
+}
+</pre>
+
+    <h4 id="specifying-view-matcher">
+      Specifying a View Matcher
+    </h4>
+
+    <p>
+      You can specify a view matcher by using these approaches:
+    </p>
+
+    <ul>
+      <li>Calling methods in the
+        <a href="{@docRoot}reference/android/support/test/espresso/matcher/ViewMatchers.html">
+        {@code ViewMatchers}</a> class. For example, to find a view by looking for a text string it
+        displays, you can call a method like this:
+        <pre>
+onView(withText("Sign-in"));
+</pre>
+
+<p>Similarly you can call
+<a href="{@docRoot}reference/android/support/test/espresso/matcher/ViewMatchers.html#withId(int)">
+{@code withId()}</a> and providing the resource ID ({@code R.id}) of the view, as shown in the
+following example:</p>
+
+<pre>
+onView(withId(R.id.button_signin));
+</pre>
+
+    <p>
+      Android resource IDs are not guaranteed to be unique. If your test attempts to match to a
+      resource ID used by more than one view, Espresso throws an
+<a href="{@docRoot}reference/android/support/test/espresso/AmbiguousViewMatcherException.html">
+  {@code AmbiguousViewMatcherException}</a>.
+    </p>
+      </li>
+      <li>Using the Hamcrest
+      <a href="http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html"
+         class="external-link">{@code Matchers}</a> class. You can use the
+      {@code allOf()} methods to combine multiple matchers, such as
+      {@code containsString()} and {@code instanceOf()}. This approach allows you to
+      filter the match results more narrowly, as shown in the following example:
+<pre>
+onView(allOf(withId(R.id.button_signin), withText("Sign-in")));
+</pre>
+<p>You can use the {@code not} keyword to filter for views that don't correspond to the matcher, as
+shown in the following example:</p>
+<pre>
+onView(allOf(withId(R.id.button_signin), not(withText("Sign-out"))));
+</pre>
+<p>To use these methods in your test, import the {@code org.hamcrest.Matchers} package. To
+learn more about Hamcrest matching, see the
+<a href="http://hamcrest.org/" class="external-link">Hamcrest site</a>.
+</p>
+      </li>
+    </ul>
+
+    <p>
+      To improve the performance of your Espresso tests, specify the minimum matching information
+      needed to find your target view. For example, if a view is uniquely identifiable by its
+      descriptive text, you do not need to specify that it is also assignable from the
+      {@link android.widget.TextView} instance.
+    </p>
+
+    <h4 id="#locating-adpeterview-view">
+      Locating a view in an AdapterView
+    </h4>
+
+    <p>
+      In an {@link android.widget.AdapterView} widget, the view is dynamically populated with child
+      views at runtime. If the target view you want to test is inside an
+      {@link android.widget.AdapterView}
+      (such as a {@link android.widget.ListView}, {@link android.widget.GridView}, or
+      {@link android.widget.Spinner}), the
+<a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onView(org.hamcrest.Matcher<android.view.View>)">
+  {@code onView()}</a> method might not work because only a
+      subset of the views may be loaded in the current view hierarchy.
+    </p>
+
+    <p>
+      Instead, call the <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
+      method to obtain a
+      <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html">
+      {@code DataInteraction}</a>
+      object to access the target view element. Espresso handles loading the target view element
+      into the current view hierarchy. Espresso also takes care of scrolling to the target element,
+      and putting the element into focus.
+    </p>
+
+    <p class="note">
+      <strong>Note</strong>: The
+  <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
+      method does not check if if the item you specified corresponds with a view. Espresso searches
+      only the current view hierarchy. If no match is found, the method throws a
+      <a href="{@docRoot}reference/android/support/test/espresso/NoMatchingViewException.html">
+        {@code NoMatchingViewException}</a>.
+    </p>
+
+    <p>
+      The following code snippet shows how you can use the
+      <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
+      method together
+      with Hamcrest matching to search for a specific row in a list that contains a given string.
+      In this example, the {@code LongListActivity} class contains a list of strings exposed
+      through a {@link android.widget.SimpleAdapter}.
+    </p>
+
+<pre>
+onData(allOf(is(instanceOf(Map.class)),
+        hasEntry(equalTo(LongListActivity.ROW_TEXT), is(str))));
+</pre>
+
+    <h3 id="perform-actions">
+      Performing Actions
+    </h3>
+
+    <p>
+      Call the <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code ViewInteraction.perform()}</a>
+      or
+      <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#perform(android.support.test.espresso.ViewAction...)">{@code DataInteraction.perform()}</a>
+      methods to
+      simulate user interactions on the UI component. You must pass in one or more
+      <a href="{@docRoot}reference/android/support/test/espresso/ViewAction.html">{@code ViewAction}</a>
+      objects as arguments. Espresso fires each action in sequence according to
+      the given order, and executes them in the main thread.
+    </p>
+
+    <p>
+      The
+      <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html">{@code ViewActions}</a>
+      class provides a list of helper methods for specifying common actions.
+      You can use these methods as convenient shortcuts instead of creating and configuring
+      individual <a href="{@docRoot}reference/android/support/test/espresso/ViewAction.html">{@code ViewAction}</a>
+      objects. You can specify such actions as:
+    </p>
+
+    <ul>
+      <li>
+       <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#click()">{@code ViewActions.click()}</a>:
+       Clicks on the view.
+      </li>
+
+      <li>
+       <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#typeText(java.lang.String)">{@code ViewActions.typeText()}</a>:
+       Clicks on a view and enters a specified string.
+      </li>
+
+      <li>
+       <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>:
+       Scrolls to the view. The
+        target view must be subclassed from {@link android.widget.ScrollView}
+        and the value of its
+        <a href="http://developer.android.com/reference/android/view/View.html#attr_android:visibility">{@code android:visibility}</a>
+        property must be {@link android.view.View#VISIBLE}. For views that extend
+        {@link android.widget.AdapterView} (for example,
+        {@link android.widget.ListView}),
+        the
+        <a href="{@docRoot}reference/android/support/test/espresso/Espresso.html#onData(org.hamcrest.Matcher<java.lang.Object>)">{@code onData()}</a>
+        method takes care of scrolling for you.
+      </li>
+
+      <li>
+       <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#pressKey(int)">{@code ViewActions.pressKey()}</a>:
+       Performs a key press using a specified keycode.
+      </li>
+
+      <li>
+      <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#clearText()">{@code ViewActions.clearText()}</a>:
+      Clears the text in the target view.
+      </li>
+    </ul>
+
+    <p>
+      If the target view is inside a {@link android.widget.ScrollView}, perform the
+      <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>
+      action first to display the view in the screen before other proceeding
+      with other actions. The
+      <a href="{@docRoot}reference/android/support/test/espresso/action/ViewActions.html#scrollTo()">{@code ViewActions.scrollTo()}</a>
+      action will have no effect if the view is already displayed.
+    </p>
+
+    <h3 id="verify-results">
+      Verifying Results
+    </h3>
+
+    <p>
+      Call the
+      <a href="{@docRoot}reference/android/support/test/espresso/ViewInteraction.html#check(android.support.test.espresso.ViewAssertion)">{@code ViewInteraction.check()}</a>
+      or
+      <a href="{@docRoot}reference/android/support/test/espresso/DataInteraction.html#check(android.support.test.espresso.ViewAssertion)">{@code DataInteraction.check()}</a>
+      method to assert
+      that the view in the UI matches some expected state. You must pass in a
+      <a href="{@docRoot}reference/android/support/test/espresso/ViewAssertion.html">
+      {@code ViewAssertion}</a> object as the argument. If the assertion fails, Espresso throws
+      an {@link junit.framework.AssertionFailedError}.
+    </p>
+
+    <p>
+      The
+  <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html">{@code ViewAssertions}</a>
+      class provides a list of helper methods for specifying common
+      assertions. The assertions you can use include:
+    </p>
+
+    <ul>
+      <li>
+        <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#doesNotExist()">{@code doesNotExist}</a>:
+Asserts that there is no view matching the specified criteria in the current view hierarchy.
+      </li>
+
+      <li>
+        <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#matches(org.hamcrest.Matcher&lt;? super android.view.View&gt;)">{@code matches}</a>:
+        Asserts that the specified view exists in the current view hierarchy
+        and its state matches some given Hamcrest matcher.
+      </li>
+
+      <li>
+       <a href="{@docRoot}reference/android/support/test/espresso/assertion/ViewAssertions.html#selectedDescendantsMatch(org.hamcrest.Matcher&lt;android.view.View&gt;, org.hamcrest.Matcher&lt;android.view.View&gt;)">{@code selectedDescendentsMatch}</a>
+       : Asserts that the specified children views for a
+        parent view exist, and their state matches some given Hamcrest matcher.
+      </li>
+    </ul>
+
+    <p>
+      The following code snippet shows how you might check that the text displayed in the UI has
+      the same value as the text previously entered in the
+      {@link android.widget.EditText} field.
+    </p>
+<pre>
+public void testChangeText_sameActivity() {
+    // Type text and then press the button.
+    ...
+
+    // Check that the text was changed.
+    onView(withId(R.id.textToBeChanged))
+            .check(matches(withText(STRING_TO_BE_TYPED)));
+}
+</pre>
+
+<h2 id="run">Run Espresso Tests on a Device or Emulator</h2>
+
+    <p>
+      To run Espresso tests, you must use the
+      <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
+      class provided in the
+      <a href="{@docRoot}tools/testing-support-library/index.html">
+      Android Testing Support Library</a> as your default test runner. The
+      <a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for
+      Gradle</a> provides a default directory ({@code src/androidTest/java}) for you to store the
+      instrumented test classes and test suites that you want to run on a device. The
+      plug-in compiles the test code in that directory and then executes the test app using
+      the configured test runner class.
+    </p>
+
+    <p>
+      To run Espresso tests in your Gradle project:
+    </p>
+
+    <ol>
+      <li>Specify
+        <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
+        as the default test instrumentation runner in
+      your {@code build.gradle} file:
+
+  <pre>
+android {
+    defaultConfig {
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+}</pre>
+      </li>
+      <li>Run your tests from the command-line by calling the the {@code connectedCheck}
+        (or {@code cC}) task:
+  <pre>
+./gradlew cC</pre>
+      </li>
+    </ol>
\ No newline at end of file
diff --git a/docs/html/training/testing/ui-testing/index.jd b/docs/html/training/testing/ui-testing/index.jd
new file mode 100644
index 0000000..20422f7
--- /dev/null
+++ b/docs/html/training/testing/ui-testing/index.jd
@@ -0,0 +1,76 @@
+page.title=Automating User Interface Tests
+page.tags=testing
+
+trainingnavtop=true
+startpage=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+        <h2>
+          You should also read
+        </h2>
+
+        <ul>
+          <li>
+            <a href="{@docRoot}tools/testing-support-library/index.html">Testing Support Library</a>
+          </li>
+        </ul>
+</div>
+</div>
+
+<p>User interface (UI) testing lets you ensure that your app meets its functional requirements
+and achieves a high standard of quality such that it is more likely to be successfully adopted by
+users.</p>
+
+<p>One approach to UI testing is to simply have a human tester perform a set of user operations on
+the target app and verify that it is behaving correctly. However, this manual approach can be
+time-consuming, tedious, and error-prone. A more efficient approach is to write your UI
+tests such that user actions are performed in an automated way. The automated approach allows
+you to run your tests quickly and reliably in a repeatable manner.</p>
+
+<p class="note"><strong>Note: </strong>It is strongly encouraged that you use
+<a href="{@docRoot}sdk/installing/studio.html">Android Studio</a> for
+building your test apps, because it provides project setup, library inclusion, and packaging
+conveniences. This class assumes you are using Android Studio.</p>
+
+<p>To automate UI tests with Android Studio, you implement your test code in a separate
+Android test folder ({@code src/androidTest/java}). The
+<a href="{@docRoot}tools/building/plugin-for-gradle.html">Android
+Plug-in for Gradle</a> builds a test app based on your test code, then loads the test app on the
+same device as the target app. In your test code, you can use UI testing frameworks to
+simulate user interactions on the target app, in order to perform testing tasks that cover specific
+usage scenarios.</p>
+
+<p>For testing Android apps, you typically create these types of automated UI tests:</p>
+
+<ul>
+<li><em>UI tests that span a single app:</em> This type of test verifies that the target app behaves
+as expected when a user performs a specific action or enters a specific input in its activities.
+It allows you to check that the target app returns the correct UI output in response
+to user interactions in the app’s activities. UI testing frameworks like Espresso allow you to
+programmatically simulate user actions and test complex intra-app user interactions.</li>
+<li><em>UI tests that span multiple apps:</em> This type of test verifies the correct behavior of
+interactions between different user apps or between user apps and system apps. For example, you
+might want to test that your camera app shares images correctly with a 3rd-party social media app,
+or with the default Android Photos app. UI testing frameworks that support cross-app interactions,
+such as UI Automator, allow you to create tests for such scenarios.</li>
+</ul>
+
+<p>The lessons in this class teach you how to use the tools and APIs in the
+<a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>
+to build these types of automated tests. Before you begin building tests using these
+APIs, you must install the Android Testing Support Library, as described in
+<a href="{@docRoot}tools/testing-support-library/index.html#setup">Downloading the Android
+Testing Support Library</a>.</p>
+
+<h2>Lessons</h2>
+<dl>
+  <dt><strong><a href="espresso-testing.html">
+Testing UI for a Single App</a></strong></dt>
+    <dd>Learn how to test UI in a single app by using the Espresso testing framework.</dd>
+  <dt><strong><a href="uiautomator-testing.html">
+Testing UI for Multiple Apps</a></strong></dt>
+    <dd>Learn how to test UI in multiple apps by using the UI Automator testing framework</dd>
+</dl>
\ No newline at end of file
diff --git a/docs/html/training/testing/ui-testing/uiautomator-testing.jd b/docs/html/training/testing/ui-testing/uiautomator-testing.jd
new file mode 100644
index 0000000..e314b70
--- /dev/null
+++ b/docs/html/training/testing/ui-testing/uiautomator-testing.jd
@@ -0,0 +1,520 @@
+page.title=Testing UI for Multiple Apps
+page.tags=testing,ui automator
+trainingnavtop=true
+
+@jd:body
+
+<!-- This is the training bar -->
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dependencies and Prerequisites</h2>
+
+  <ul>
+    <li>Android 4.3 (API level 18) or higher</li>
+    <li><a href="{@docRoot}tools/testing-support-library/index.html">
+      Android Testing Support Library</a></li>
+  </ul>
+
+  <h2>This lesson teaches you to</h2>
+
+  <ol>
+    <li><a href="#setup">Set Up UI Automator</a></li>
+    <li><a href="#build">Create a UI Automator Test Class</a></li>
+    <li><a href="#run">Run UI Automator Tests on a Device or Emulator</a></li>
+  </ol>
+
+  <h2>You should also read</h2>
+
+  <ul>
+    <li><a href="{@docRoot}reference/android/support/test/package-summary.html">
+UI Automator API Reference</a></li>
+  </ul>
+
+  <h2>Try it out</h2>
+
+  <ul>
+    <li><a href="https://github.com/googlesamples/android-testing"
+class="external-link">UI Automator Code Samples</a></li>
+  </ul>
+</div>
+</div>
+
+<p>A user interface (UI) test that involves user interactions across multiple apps lets you
+verify that your app behaves correctly when the user flow crosses into other apps or into the
+system UI. An example of such a user flow is a messaging app that lets the user enter a text
+message, launches the Android contact picker so that the users can select recipients to send the
+message to, and then returns control to the original app for the user to submit the message.</p>
+
+<p>This lesson covers how to write such UI tests using the
+UI Automator testing framework provided by the
+<a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+The UI Automator APIs let you interact with visible elements on a device, regardless of
+which {@link android.app.Activity} is in focus. Your test can look up a UI component by using
+convenient descriptors such as the text displayed in that component or its content description. UI
+Automator tests can run on devices running Android 4.3 (API level 18) or higher.</p>
+
+<p>The UI Automator testing framework is an instrumentation-based API and works
+with the
+<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
+  {@code AndroidJUnitRunner}</a>
+test runner.
+</p>
+
+<h2 id="setup">Set Up UI Automator</h2>
+<p>Before you begin using UI Automator, you must:</p>
+
+  <ul>
+      <li>
+        <strong>Install the Android Testing Support Library</strong>. The UI Automator API is
+        located under the {@code com.android.support.test.uiautomator} package. These classes allow
+        you to create tests that use the Espresso testing framework. To learn how to install the
+        library, see <a href="{@docRoot}tools/testing-support-library/index.html#setup">
+        Testing Support Library Setup</a>.
+      </li>
+
+      <li>
+        <strong>Set up your project structure.</strong> In your Gradle project, the source code for
+        the target app that you want to test is typically placed under the {@code app/src/main}
+        folder. The source code for instrumentation tests, including
+        your UI Automator tests, must be placed under the <code>app/src/androidTest</code> folder.
+        To learn more about setting up your project directory, see
+        <a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.
+      </li>
+
+      <li>
+        <strong>Specify your Android testing dependencies</strong>. In order for the
+        <a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for Gradle</a> to
+        correctly build and run your UI Automator tests, you must specify the following libraries in
+        the {@code build.gradle} file of your Android app module:
+
+        <pre>
+dependencies {
+    androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
+    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.0.0'
+}
+</pre>
+      </li>
+  </ul>
+
+<p>To optimize your UI Automator testing, you should first inspect the target app’s UI components
+and ensure that they are accessible. These optimization tips are described in the next two
+sections.</p>
+
+<h3 id="inspecting-ui">Inspecting the UI on a device</h3>
+<p>Before designing your test, inspect the UI components that are visible on the device. To
+ensure that your UI Automator tests can access these components, check that these components
+have visible text labels,
+<a href="http://developer.android.com/reference/android/view/View.html#attr_android:contentDescription">
+{@code android:contentDescription}</a>
+values, or both.</p>
+
+<p>The {@code uiautomatorviewer} tool provides a convenient visual interface to inspect the layout
+hierarchy and view the properties of UI components that are visible on the foreground of the device.
+This information lets you create more fine-grained tests using UI Automator. For example, you can
+create a UI selector that matches a specific visible property. </p>
+
+<p>To launch the {@code uiautomatorviewer} tool:</p>
+
+<ol>
+  <li>Launch the target app on a physical device.</li>
+  <li>Connect the device to your development machine.</li>
+  <li>Open a terminal window and navigate to the {@code &lt;android-sdk&gt;/tools/} directory.</li>
+  <li>Run the tool with this command:
+<pre>$ uiautomatorviewer</pre>
+  </li>
+</ol>
+
+<p>To view the UI properties for your application:</p>
+
+<ol>
+  <li>In the {@code uiautomatorviewer} interface, click the <strong>Device Screenshot</strong>
+button.</li>
+  <li>Hover over the snapshot in the left-hand panel to see the UI components identified by the
+{@code uiautomatorviewertool}. The properties are listed in the lower right-hand panel and the
+layout hierarchy in the upper right-hand panel.</li>
+  <li>Optionally, click on the <strong>Toggle NAF Nodes</strong> button to see UI components that
+are non-accessible to UI Automator. Only limited information may be available for these
+components.</li>
+</ol>
+
+<p>To learn about the common types of UI components provided by Android, see
+<a href="{@docRoot}guide/topics/ui/index.html">User Interface</a>.</p>
+
+<h3>Ensuring your Activity is accessible</h3>
+<p>The UI Automator test framework depends on the accessibility features of the Android framework
+to look up individual UI elements. As a developer, you should implement these minimum
+optimizations in your {@link android.app.Activity} to support UI Automator:</p>
+
+<ul>
+<li>Use the
+<a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
+  {@code android:contentDescription}</a>
+attribute to label the {@link android.widget.ImageButton}, {@link android.widget.ImageView},
+{@link android.widget.CheckBox} and other user interface controls.</li>
+<li>Provide an <a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">{@code android:hint}</a>
+attribute instead of a content description for {@link android.widget.EditText} fields.</li>
+<li>Associate an <a href="http://developer.android.com/reference/android/widget/TextView.html#attr_android:hint">
+  {@code android:hint}</a>
+attribute with any graphical icons used by controls that provide feedback to the user
+(for example, status or state information).</li>
+<li>Use the {@code uiautomatorviewer} tool to ensure that the UI component is accessible to the
+testing framework. You can also test the application by turning on accessibility services like
+TalkBack and Explore by Touch, and try using your application using only directional controls.</li>
+</ul>
+
+<p>Generally, app developers get accessibility support for free, courtesy of
+the {@link android.view.View} and {@link android.view.ViewGroup}
+classes. However, some apps use custom view elements to provide a richer user experience. Such
+custom elements won't get the accessibility support that is provided by the standard Android UI
+elements. If this applies to your app, make sure that it exposes the custom-drawn UI element to
+Android accessibility services by implementing the
+{@link android.view.accessibility.AccessibilityNodeProvider} class.</p>
+
+<p>If the custom view element contains a single element, make it accessible by
+<a href="{@docRoot}guide/topics/ui/accessibility/apps.html#accessibility-methods">implementing
+accessibility API methods</a>.
+If the custom view contains elements that are not views themselves (for example, a
+{@link android.webkit.WebView}, make sure it implements the
+{@link android.view.accessibility.AccessibilityNodeProvider} class. For container views that
+extend an existing container implementation
+(for example, a {@link android.widget.ListView}), implementing
+{@link android.view.accessibility.AccessibilityNodeProvider} is not necessary.</p>
+
+<p>For more information about implementing and testing accessibility, see
+<a href="{@docRoot}guide/topics/ui/accessibility/apps.html">Making Applications Accessible</a>.</p>
+
+<h2 id="build">Create a UI Automator Test Class</h2>
+
+<p>To build a UI Automator test, create a class that extends
+{@link android.test.InstrumentationTestCase}. Implement the following programming model in your
+UI Automator test class:</p>
+
+<ol>
+<li>Get a
+  <a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a>
+  object to access the device you want to test, by calling the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html#getInstance(android.app.Instrumentation)">
+{@code getInstance()}</a>
+method and passing it an {@link android.app.Instrumentation} object as the argument.</li>
+<li>Get a
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
+object to access a UI component that is displayed on the device
+	(for example, the current view in the foreground), by calling the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html#findObject(android.support.test.uiautomator.UiSelector)">
+  {@code findObject()}</a>
+method.
+</li>
+<li>Simulate a specific user interaction to perform on that UI component, by calling a
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
+method; for example, call
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#performMultiPointerGesture(android.view.MotionEvent.PointerCoords[]...)">
+  {@code performMultiPointerGesture()}</a>
+to simulate a multi-touch gesture, and
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#setText(java.lang.String)">{@code setText()}</a>
+to edit a text field. You can call on the APIs in steps 2 and 3 repeatedly as necessary to test
+more complex user interactions that involve multiple UI components or sequences of user actions.</li>
+<li>Check that the UI reflects the expected state or behavior, after these user interactions are
+	performed. </li>
+</ol>
+
+<p>These steps are covered in more detail in the sections below.</p>
+
+<h3 id="accessing-ui-components">Accessing UI Components</h3>
+<p>The
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a>
+  object is the primary way you access and manipulate the state of the
+device. In your tests, you can call
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a>
+methods to check for the state of various properties, such as current orientation or display size.
+Your test can use the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a>
+object to perform device-level actions, such as forcing the device into a specific rotation,
+pressing D-pad hardware buttons, and pressing the Home and Menu buttons.</p>
+
+<p>It’s good practice to start your test from the Home screen of the device. From the Home screen
+(or some other starting location you’ve chosen in the device), you can call the methods provided by
+the UI Automator API to select and interact with specific UI elements. </p>
+
+<p>The following code snippet shows how your test might get an instance of
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html">{@code UiDevice}</a>
+and simulate a Home button press:</p>
+
+<pre>
+import android.test.InstrumentationTestCase;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.By;
+
+public class CalculatorUiTest extends InstrumentationTestCase {
+
+    private UiDevice mDevice;
+
+    public void setUp() {
+        // Initialize UiDevice instance
+        mDevice = UiDevice.getInstance(getInstrumentation());
+
+        // Start from the home screen
+        mDevice.pressHome();
+        mDevice.wait(Until.hasObject(By.pkg(getHomeScreenPackage()).depth(0)),
+    }
+}
+</pre>
+
+<p>Use the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiDevice.html#findObject(android.support.test.uiautomator.UiSelector)">{@code findObject()}</a>
+method to retrieve a
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
+which represents a view that matches a given selector criteria. You can reuse the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
+instances that you have created in other parts of your app testing, as needed. Note that the
+UI Automator test framework searches the current display for a match every time your test uses a
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
+instance to click on a UI element or query a property.</p>
+
+<p>The following snippet shows how your test might construct
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
+instances that represent a Cancel button and a OK button in an app.</p>
+
+<pre>
+UiObject cancelButton = mDevice.findObject(new UiSelector()
+        .text("Cancel"))
+        .className("android.widget.Button"));
+UiObject okButton = mDevice.findObject(new UiSelector()
+        .text("OK"))
+        .className("android.widget.Button"));
+
+// Simulate a user-click on the OK button, if found.
+if(okButton.exists() &#38;&#38; okButton.isEnabled()) {
+    okButton.click();
+}
+</pre>
+
+<h4 id="specifying-selector">Specifying a selector</h4>
+<p>If you want to access a specific UI component in an app, use the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a>
+class. This class represents a query for specific elements in the
+currently displayed UI. </p>
+
+<p>If more than one matching element is found, the first matching element in the layout hierarchy
+is returned as the target
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>.
+When constructing a
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a>,
+you can chain together multiple properties to refine your search. If no matching UI element is
+found, a
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObjectNotFoundException.html">
+{@code UiAutomatorObjectNotFoundException}</a> is thrown. </p>
+
+<p>You can use the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html#childSelector(android.support.test.uiautomator.UiSelector)">{@code childSelector()}</a>
+method to nest multiple
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a>
+instances. For example, the following code example shows how your test might specify a search to
+find the first {@link android.widget.ListView} in the currently displayed UI, then search within that
+{@link android.widget.ListView} to find a UI element with the text property Apps.</p>
+
+<pre>
+UiObject appItem = new UiObject(new UiSelector()
+        .className("android.widget.ListView")
+        .instance(1)
+        .childSelector(new UiSelector()
+        .text("Apps")));
+</pre>
+
+<p>As a best practice, when specifying a selector, you should use a Resource ID (if one is assigned
+to a UI element) instead of a text element or content-descriptor. Not all elements have a text
+element (for example, icons in a toolbar). Text selectors are brittle and can lead to test failures
+if there are minor changes to the UI. They may also not scale across different languages; your text
+selectors may not match translated strings.</p>
+
+<p>It can be useful to specify the object state in your selector criteria. For example, if you want
+to select a list of all checked elements so that you can uncheck them, call the
+<a href="{@docRoot}reference/android/support/test/uiautomator/By.html#checked(boolean)">
+{@code checked()}</a>
+method with the argument set to {@code true}.</p>
+
+<h3 id="performing-actions">Performing Actions</h3>
+
+<p>Once your test has obtained a
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
+object, you can call the methods in the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>
+class to perform user interactions on the UI component represented by that
+object. You can specify such actions as:</p>
+
+<ul>
+<li>
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#click()">
+  {@code click()}</a>
+: Clicks the center of the visible bounds of the UI element.</li>
+<li>
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#dragTo(int, int, int)">
+  {@code dragTo()}</a>
+: Drags this object to arbitrary coordinates.</li>
+<li>
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#setText(java.lang.String)">
+  {@code setText()}</a>
+: Sets the text in an editable field, after clearing the field's content.
+Conversely, the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#clearTextField()">
+  {@code clearTextField()}</a>
+method clears the existing text in an editable field.</li>
+<li>
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeUp(int)">
+  {@code swipeUp()}</a>
+: Performs the swipe up action on the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html">{@code UiObject}</a>.
+Similarly, the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeDown(int)">
+  {@code swipeDown()}</a>,
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeLeft(int)">
+  {@code swipeLeft()}</a>, and
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiObject.html#swipeRight(int)">
+  {@code swipeRight()}</a>
+methods perform corresponding actions.</li>
+</ul>
+
+<p>The UI Automator testing framework allows you to send an
+{@link android.content.Intent}
+or launch an {@link android.app.Activity}
+without using shell commands, by getting a
+{@link android.content.Context}
+object through
+{@link android.app.Instrumentation#getContext() getContext()}.</p>
+
+<p>The following snippet shows how your test can use an
+{@link android.content.Intent} to launch the app under test. This approach is useful when you are
+only interested in testing the calculator app, and don't care about the launcher.</p>
+
+<pre>
+public void setUp() {
+    ...
+
+    // Launch a simple calculator app
+    Context context = getInstrumentation().getContext();
+    Intent intent = context.getPackageManager()
+            .getLaunchIntentForPackage(CALC_PACKAGE);
+    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+            // Clear out any previous instances
+    context.startActivity(intent);
+    mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT);
+}
+</pre>
+
+<h4 id="actions-on-collections">Performing actions on collections</h4>
+
+<p>Use the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiCollection.html">
+  {@code UiCollection}</a>
+class if you want to simulate user interactions on a
+collection of items (for example, songs in a music album or a list of emails in an Inbox). To
+create a
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiCollection.html">
+  {@code UiCollection}</a>
+object, specify a
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiSelector.html">{@code UiSelector}</a>
+that searches for a
+UI container or a wrapper of other child UI elements, such as a layout view that contains child UI
+elements.</p>
+
+<p>The following code snippet shows how your test might construct a
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiCollection.html">
+  {@code UiCollection}</a>
+to represent a video album that is displayed within a {@link android.widget.FrameLayout}:</p>
+
+<pre>
+UiCollection videos = new UiCollection(new UiSelector()
+        .className("android.widget.FrameLayout"));
+
+// Retrieve the number of videos in this collection:
+int count = videos.getChildCount(new UiSelector()
+        .className("android.widget.LinearLayout"));
+
+// Find a specific video and simulate a user-click on it
+UiObject video = videos.getChildByText(new UiSelector()
+        .className("android.widget.LinearLayout"), "Cute Baby Laughing");
+video.click();
+
+// Simulate selecting a checkbox that is associated with the video
+UiObject checkBox = video.getChild(new UiSelector()
+        .className("android.widget.Checkbox"));
+if(!checkBox.isSelected()) checkbox.click();
+</pre>
+
+<h4 id="actions-on-scrollable-views">Performing actions on scrollable views</h4>
+<p>Use the
+<a href="{@docRoot}reference/android/support/test/uiautomator/UiScrollable.html">
+  {@code UiScrollable}</a>
+class to simulate vertical or horizontal scrolling across a display. This technique is helpful when
+a UI element is positioned off-screen and you need to scroll to bring it into view.</p>
+
+<p>The following code snippet shows how to simulate scrolling down the Settings menu and clicking
+on an About tablet option:</p>
+
+<pre>
+UiScrollable settingsItem = new UiScrollable(new UiSelector()
+        .className("android.widget.ListView"));
+UiObject about = settingsItem.getChildByText(new UiSelector()
+        .className("android.widget.LinearLayout"), "About tablet");
+about.click();
+</pre>
+
+<h3 id="verifying-results">Verifying Results</h3>
+<p>The {@link android.test.InstrumentationTestCase} extends {@link junit.framework.TestCase}, so
+you can use standard JUnit <a href="http://junit.org/javadoc/latest/org/junit/Assert.html"
+class="external-link">{@code Assert}</a> methods to test
+that UI components in the app return the expected results. </p>
+
+<p>The following snippet shows how your test can locate several buttons in a calculator app, click
+on them in order, then verify that the correct result is displayed.</p>
+
+<pre>
+private static final String CALC_PACKAGE = "com.myexample.calc";
+
+public void testTwoPlusThreeEqualsFive() {
+    // Enter an equation: 2 + 3 = ?
+    mDevice.findObject(new UiSelector()
+            .packageName(CALC_PACKAGE).resourceId("two")).click();
+    mDevice.findObject(new UiSelector()
+            .packageName(CALC_PACKAGE).resourceId("plus")).click();
+    mDevice.findObject(new UiSelector()
+            .packageName(CALC_PACKAGE).resourceId("three")).click();
+    mDevice.findObject(new UiSelector()
+            .packageName(CALC_PACKAGE).resourceId("equals")).click();
+
+    // Verify the result = 5
+    UiObject result = mDevice.findObject(By.res(CALC_PACKAGE, "result"));
+    assertEquals("5", result.getText());
+}
+</pre>
+
+<h2 id="run">Run UI Automator Tests on a Device or Emulator</h2>
+<p>UI Automator tests are based on the {@link android.app.Instrumentation} class. The
+<a href="https://developer.android.com/tools/building/plugin-for-gradle.html">
+  Android Plug-in for Gradle</a>
+provides a default directory ({@code src/androidTest/java}) for you to store the instrumented test
+classes and test suites that you want to run on a device. The plug-in compiles the test
+code in that directory and then executes the test app using a test runner class. You are
+strongly encouraged to use the
+<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
+class provided in the
+<a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>
+as your default test runner. </p>
+
+<p>To run UI Automator tests in your Gradle project:</p>
+
+<ol>
+<li>Specify
+<a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code AndroidJUnitRunner}</a>
+as the default test instrumentation runner in your {@code build.gradle} file:
+<pre>
+android {
+    defaultConfig {
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+}</pre>
+</li>
+<li>Run your tests from the command-line by calling the {@code connectedCheck}
+  (or {@code cC}) task:
+<pre>./gradlew cC</pre>
+</li>
+</ol>
\ No newline at end of file
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 11ae1a6..3ee7ab7 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -998,10 +998,25 @@
            Building TV Games</a>
       </li>
 
-      <li>
-        <a href="<?cs var:toroot ?>training/tv/tif/index.html"
+      <li class="nav-section">
+        <div class="nav-section-header">
+          <a href="<?cs var:toroot ?>training/tv/tif/index.html"
            description="How to build Live TV apps.">
            Building Live TV Apps</a>
+        </div>
+        <ul>
+          <li>
+            <a href="<?cs var:toroot ?>training/tv/tif/tvinput.html">
+              Developing a TV Input Service</a>
+          <li>
+            <a href="<?cs var:toroot ?>training/tv/tif/channel.html">
+              Working with Channel Data</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>training/tv/tif/ui.html">
+              Managing User Interaction</a>
+          </li>
+        </ul>
       </li>
 
       <li>
@@ -1825,6 +1840,24 @@
         </ul>
       </li>
     </ul>
+    <ul>
+      <li class="nav-section">
+      <div class="nav-section-header"><a href="<?cs var:toroot ?>training/testing/ui-testing/index.html"
+         description="How to automate your user interface tests for Android apps.">
+            Automating UI Tests
+          </a></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>training/testing/ui-testing/espresso-testing.html">
+            <span class="en">Testing UI for a Single App</span>
+          </a>
+          </li>
+          <li><a href="<?cs var:toroot ?>training/testing/ui-testing/uiautomator-testing.html">
+            <span class="en">Testing UI for Multiple Apps</span>
+          </a>
+          </li>
+        </ul>
+      </li>
+    </ul>
   </li>
   <!-- End best Testing -->
 
diff --git a/docs/html/training/tv/tif/channel.jd b/docs/html/training/tv/tif/channel.jd
new file mode 100644
index 0000000..999f1ca
--- /dev/null
+++ b/docs/html/training/tv/tif/channel.jd
@@ -0,0 +1,239 @@
+page.title=Working with Channel Data
+page.tags=tv, tif
+helpoutsWidget=true
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>This lesson teaches you to</h2>
+  <ol>
+    <li><a href="#permission">Get Permission</a></li>
+    <li><a href="#register">Register Channels in the Database</a></li>
+    <li><a href="#update">Update Channel Data</a></li>
+  </ol>
+  <h2>Try It Out</h2>
+  <ul>
+    <li><a class="external-link" href="https://github.com/googlesamples/androidtv-sample-inputs">
+      TV Input Service sample app</a></li>
+  </ul>
+</div>
+</div>
+
+<p>Your TV input must provide Electronic Program Guide (EPG) data for at least one channel in its
+setup activity. You should also periodically update that data, with consideration for the size of
+the update and the processing thread that handles it. This lesson discusses creating and updating
+channel and program data on the system database with these considerations in mind.</p>
+
+<p>&nbsp;</p>
+
+<h2 id="permission">Get Permission</h2>
+
+<p>In order for your TV input to work with EPG data, it must declare the
+read and write permissions in its Android manifest file as follows:</p>
+
+<pre>
+&lt;uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" /&gt;
+&lt;uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" /&gt;
+</pre>
+
+<h2 id="register">Register Channels in the Database</h2>
+
+<p>The Android TV system database maintains records of channel data for TV inputs. In your setup
+activity, for each of your channels, you must map your channel data to the following fields of the
+{@link android.media.tv.TvContract.Channels} class:</p>
+
+<ul>
+  <li>{@link android.media.tv.TvContract.Channels#COLUMN_DISPLAY_NAME} - the displayed name of the
+  channel</li>
+  <li>{@link android.media.tv.TvContract.Channels#COLUMN_DISPLAY_NUMBER} - the displayed channel
+  number</li>
+  <li>{@link android.media.tv.TvContract.Channels#COLUMN_INPUT_ID} - the ID of the TV input service</li>
+  <li>{@link android.media.tv.TvContract.Channels#COLUMN_SERVICE_TYPE} - the channel's service type</li>
+  <li>{@link android.media.tv.TvContract.Channels#COLUMN_TYPE} - the channel's broadcast standard
+  type</li>
+  <li>{@link android.media.tv.TvContract.Channels#COLUMN_VIDEO_FORMAT} - the default video format
+  for the channel</li>
+</ul>
+
+<p>Although the TV input framework is generic enough to handle both traditional broadcast and
+over-the-top (OTT) content without any distinction, you may want to define the following columns in
+addition to those above to better identify traditional broadcast channels:</p>
+
+<ul>
+  <li>{@link android.media.tv.TvContract.Channels#COLUMN_ORIGINAL_NETWORK_ID} - the television
+  network ID</li>
+  <li>{@link android.media.tv.TvContract.Channels#COLUMN_SERVICE_ID} - the service ID</li>
+  <li>{@link android.media.tv.TvContract.Channels#COLUMN_TRANSPORT_STREAM_ID} - the transport stream
+  ID</li>
+</ul>
+
+<p>For internet streaming based TV inputs, assign your own values to the above accordingly so that
+each channel can be identified uniquely.</p>
+
+<p>Pull your channel metadata (in XML, JSON, or whatever) from your backend server, and in your setup
+activity map the values to the system database as follows:</p>
+
+<pre>
+ContentValues values = new ContentValues();
+
+values.put(Channels.COLUMN_DISPLAY_NUMBER, channel.mNumber);
+values.put(Channels.COLUMN_DISPLAY_NAME, channel.mName);
+values.put(Channels.COLUMN_ORIGINAL_NETWORK_ID, channel.mOriginalNetworkId);
+values.put(Channels.COLUMN_TRANSPORT_STREAM_ID, channel.mTransportStreamId);
+values.put(Channels.COLUMN_SERVICE_ID, channel.mServiceId);
+values.put(Channels.COLUMN_VIDEO_FORMAT, channel.mVideoFormat);
+
+Uri uri = context.getContentResolver().insert(TvContract.Channels.CONTENT_URI, values);
+</pre>
+
+<p>In the example above, <code>channel</code> is an object which holds channel metadata from the
+backend server.</p>
+
+<h3 id="art">Present Channel and Program Information</h2>
+
+<p>The system TV app presents channel and program information to users as they flip through channels,
+as shown in figure 1. To make sure the channel and program information works with the system TV app's
+channel and program information presenter, follow the guidelines below.</p>
+
+<ol>
+<li><strong>Channel number</strong> ({@link android.media.tv.TvContract.Channels#COLUMN_DISPLAY_NUMBER})
+<li><strong>Icon</strong>
+(<a href="guide/topics/manifest/application-element.html#icon"><code>android:icon</code></a> in the
+TV input's manifest)</li>
+<li><strong>Program description</strong> ({@link android.media.tv.TvContract.Programs#COLUMN_SHORT_DESCRIPTION})
+<li><strong>Program title</strong> ({@link android.media.tv.TvContract.Programs#COLUMN_TITLE})</li>
+<li><strong>Channel logo</strong> ({@link android.media.tv.TvContract.Channels.Logo})
+  <ul>
+    <li>Use the color #EEEEEE to match the surrounding text</li>
+    <li>Don't include padding
+  </ul></li>
+<li><strong>Poster art</strong> ({@link android.media.tv.TvContract.Programs#COLUMN_POSTER_ART_URI})
+  <ul>
+    <li>Aspect ratio between 16:9 and 4:3</li>
+  </ul>
+</ol>
+
+<img src="{@docRoot}images/tv/channel-info.png" id="figure1">
+<p class="img-caption">
+  <strong>Figure 1.</strong> The system TV app channel and program information presenter.
+</p>
+
+<p>The system TV app provides the same information through the program guide, including poster art,
+as shown in figure 2.</p>
+
+<img src="{@docRoot}images/tv/prog-guide.png" id="figure2">
+<p class="img-caption">
+  <strong>Figure 2.</strong> The system TV app program guide.
+</p>
+
+<h2 id="update">Update Channel Data</h2>
+
+<p>When updating existing channel data, use the
+{@link android.content.ContentProvider#update(android.net.Uri, android.content.ContentValues,
+java.lang.String, java.lang.String[]) update()}
+method instead of deleting and re-adding the data. You can identify the current version of the data
+by using {@link android.media.tv.TvContract.Channels#COLUMN_VERSION_NUMBER Channels.COLUMN_VERSION_NUMBER}
+and {@link android.media.tv.TvContract.Programs#COLUMN_VERSION_NUMBER Programs.COLUMN_VERSION_NUMBER}
+when choosing the records to update.</p>
+
+<p class="note"><strong>Note:</strong> Adding channel data to the {@link android.content.ContentProvider}
+can take time. Only add current programs (those within two hours of the current time) when you update,
+and use a <a href="{@docRoot}training/sync-adapters/creating-sync-adapter.html">Sync Adapter</a> to
+update the rest of the channel data in the background. See the <a class="external-link" href="https://github.com/googlesamples/androidtv-sample-inputs/blob/master/app/src/main/java/com/example/android/sampletvinput/syncadapter/SyncAdapter.java">
+Android TV Live TV Sample App</a> for an example.</p>
+
+<h3 id="batch">Batch Loading Channel Data</h3>
+
+<p>When updating the system database with a large amount of channel data, use the {@link android.content.ContentResolver}
+{@link android.content.ContentResolver#applyBatch applyBatch()}
+or
+{@link android.content.ContentResolver#bulkInsert(android.net.Uri, android.content.ContentValues[]) bulkInsert()}
+method. Here's an example using {@link android.content.ContentResolver#applyBatch applyBatch()}:<p>
+
+<pre>
+ArrayList&lt;ContentProviderOperation&gt; ops = new ArrayList&lt;&gt;();
+int programsCount = mChannelInfo.mPrograms.size();
+for (int j = 0; j &lt; programsCount; ++j) {
+    ProgramInfo program = mChannelInfo.mPrograms.get(j);
+    ops.add(ContentProviderOperation.newInsert(
+            TvContract.Programs.CONTENT_URI)
+            .withValues(programs.get(j))
+            .withValue(Programs.COLUMN_START_TIME_UTC_MILLIS,
+                    programStartSec * 1000)
+            .withValue(Programs.COLUMN_END_TIME_UTC_MILLIS,
+                    (programStartSec + program.mDurationSec) * 1000)
+            .build());
+    programStartSec = programStartSec + program.mDurationSec;
+    if (j % 100 == 99 || j == programsCount - 1) {
+        try {
+            <strong>getContentResolver().applyBatch(TvContract.AUTHORITY, ops);</strong>
+        } catch (RemoteException | OperationApplicationException e) {
+            Log.e(TAG, "Failed to insert programs.", e);
+            return;
+        }
+        ops.clear();
+    }
+}
+</pre>
+
+<h3 id="async">Processing Channel Data Asynchronously</h3>
+
+<p>Data manipulation, such as fetching a stream from the server or accessing the database, should
+not block the UI thread. Using an {@link android.os.AsyncTask} is one
+way to perform updates asynchronously.  For example, when loading channel info from a backend server,
+you can use {@link android.os.AsyncTask} as follows:</p>
+
+<pre>
+private static class LoadTvInputTask extends AsyncTask&lt;Uri, Void, Void>&gt; {
+
+    private Context mContext;
+
+    public LoadTvInputTask(Context context) {
+        mContext = context;
+    }
+
+    &#64;Override
+    protected Void doInBackground(Uri... uris) {
+        try {
+            fetchUri(uris[0]);
+        } catch (IOException e) {
+          Log.d(“LoadTvInputTask”, “fetchUri error”);
+        }
+        return null;
+    }
+
+    private void fetchUri(Uri videoUri) throws IOException {
+        InputStream inputStream = null;
+        try {
+            inputStream = mContext.getContentResolver().openInputStream(videoUri);
+            XmlPullParser parser = Xml.newPullParser();
+            try {
+                parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
+                parser.setInput(inputStream, null);
+                sTvInput = ChannelXMLParser.parseTvInput(parser);
+                sSampleChannels = ChannelXMLParser.parseChannelXML(parser);
+            } catch (XmlPullParserException e) {
+                e.printStackTrace();
+            }
+        } finally {
+            if (inputStream != null) {
+                inputStream.close();
+            }
+        }
+    }
+}
+</pre>
+
+<p>If you need to update EPG data on a regular basis, consider using
+a <a href="{@docRoot}training/sync-adapters/creating-sync-adapter.html">
+Sync Adapter</a> or {@link android.app.job.JobScheduler} to run the update process during idle time,
+such as every day at 3:00 a.m. See the <a class="external-link" href="https://github.com/googlesamples/androidtv-sample-inputs/blob/master/app/src/main/java/com/example/android/sampletvinput/syncadapter/SyncAdapter.java">
+Android TV live TV sample app</a> for an example.</p>
+
+<p>Other techniques to separate the data update tasks from the UI thread include using the
+{@link android.os.HandlerThread} class, or you may implement your own using {@link android.os.Looper}
+and {@link android.os.Handler} classes.  See <a href="{@docRoot}guide/components/processes-and-threads.html">
+Processes and Threads</a> for more information.</p>
\ No newline at end of file
diff --git a/docs/html/training/tv/tif/index.jd b/docs/html/training/tv/tif/index.jd
index 9c10850..5739294 100644
--- a/docs/html/training/tv/tif/index.jd
+++ b/docs/html/training/tv/tif/index.jd
@@ -1,17 +1,26 @@
 page.title=Building Live TV Apps
 page.tags=tv, tif
 helpoutsWidget=true
-page.article=true
+startpage=true
 
 @jd:body
 
 <div id="tb-wrapper">
 <div id="tb">
+  <h2>Dependencies and Prerequisites</h2>
+  <ul>
+    <li>Android 5.0 (API level 21) or higher</li>
+  </ul>
   <h2>You should also read</h2>
   <ul>
     <li><a href="{@docRoot}reference/android/media/tv/package-summary.html">
       android.media.tv</a></li>
   </ul>
+  <h2>Try It Out</h2>
+  <ul>
+    <li><a class="external-link" href="https://github.com/googlesamples/androidtv-sample-inputs">
+      TV Input Service sample app</a></li>
+  </ul>
 </div>
 </div>
 
@@ -44,6 +53,17 @@
   Building a TV input service for your content can help make it more accessible on TV devices.
 </p>
 
-<p>For more information about TV Input Framework, see the
-<a href="{@docRoot}reference/android/media/tv/package-summary.html">android.media.tv</a>
-reference.</p>
+<h2>Topics</h2>
+
+<dl>
+  <dt><b><a href="tvinput.html">Developing a TV Input Service</a></b></dt>
+    <dd>Learn how to develop a TV input service, which works with the system TV app.</dd>
+
+  <dt><b><a href="channel.html">Working with Channel Data</a></b></dt>
+    <dd>Learn how to describe channel and program data for the system.</dd>
+
+  <dt><b><a href="ui.html">Managing User Interaction</a></b></dt>
+    <dd>Learn how to present overlays, manage content availability, and handle content selection.</dd>
+</dl>
+
+
diff --git a/docs/html/training/tv/tif/tvinput.jd b/docs/html/training/tv/tif/tvinput.jd
new file mode 100644
index 0000000..91f8ded
--- /dev/null
+++ b/docs/html/training/tv/tif/tvinput.jd
@@ -0,0 +1,177 @@
+page.title=Developing a TV Input Service
+page.tags=tv, tif
+helpoutsWidget=true
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>This lesson teaches you to</h2>
+  <ol>
+    <li><a href="#manifest">Declare Your TV Input Service in the Manifest</a></li>
+    <li><a href="#tvinput">Define Your TV Input Service</a></li>
+    <li><a href="#setup">Define Setup and Settings Activities</a></li>
+  </ol>
+  <h2>You should also read</h2>
+  <ul>
+    <li><a href="{@docRoot}reference/android/media/tv/package-summary.html">
+      android.media.tv</a></li>
+    <li><a class="external-lin" href="http://source.android.com/devices/tv/index.html">
+      TV Input Framework</a></li>
+  </ul>
+  <h2>Try It Out</h2>
+  <ul>
+    <li><a class="external-link" href="https://github.com/googlesamples/androidtv-sample-inputs">
+      TV Input Service sample app</a></li>
+  </ul>
+</div>
+</div>
+
+<p>A TV input service represents a media stream source, and lets you present your media content in a
+linear, broadcast TV fashion as channels and programs. With the TV input service, you can provide
+parental controls, program guide information, and content ratings. The TV input service works
+with the Android system TV app, developed for the device and immutable by third-party apps, which
+ultimately controls and presents content on the TV. See
+<a class="external-link" href="http://source.android.com/devices/tv/index.html">
+TV Input Framework</a> for more information about the framework architecture and its components.</p>
+
+<p>To develop a TV input service, you implement the following components:</p>
+
+<ul>
+  <li>{@link android.media.tv.TvInputService} provides long-running and background availability for
+  the TV input</li>
+  <li>{@link android.media.tv.TvInputService.Session} maintains the TV input state and communicates
+  with the hosting app</li>
+  <li>{@link android.media.tv.TvContract} describes the channels and programs available to the TV
+  input</li>
+  <li>{@link android.media.tv.TvContract.Channels} represents information about a TV channel</li>
+  <li>{@link android.media.tv.TvContract.Programs} describes a TV program with data such as program
+  title and start time</li>
+  <li>{@link android.media.tv.TvTrackInfo} represents an audio, video, or subtitle track</li>
+  <li>{@link android.media.tv.TvContentRating} describes a content rating, allows for custom content
+  rating schemes</li>
+  <li>{@link android.media.tv.TvInputManager} provides an API to the system TV app and manages
+  the interaction with TV inputs and apps</li>
+</ul>
+
+<h2 id="manifest">Declare Your TV Input Service in the Manifest</h2>
+
+<p>Your app manifest must declare your {@link android.media.tv.TvInputService}. Within that
+declaration, specify the {@link android.Manifest.permission#BIND_TV_INPUT} permission to allow the
+service to connect the TV input to the system. A system service (<code>TvInputManagerService</code>)
+performs the binding and has that permission. The system TV app sends requests to TV input services
+via the {@link android.media.tv.TvInputManager} interface. The service declaration must also
+include an intent filter that specifies the {@link android.media.tv.TvInputService}
+as the action to perform with the intent. Also within the service declaration, declare the service
+meta data in a separate XML resource. The service declaration, the intent filter and the service
+meta data are described in the following example.</p>
+
+<pre>
+&lt;service android:name="com.example.sampletvinput.SampleTvInput"
+    android:label="@string/sample_tv_input_label"
+    android:permission="android.permission.BIND_TV_INPUT"&gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name="android.media.tv.TvInputService" /&gt;
+    &lt;/intent-filter&gt;
+    &lt;meta-data android:name="android.media.tv.input"
+      android:resource="@xml/sample_tv_input" /&gt;
+&lt;/service&gt;
+</pre>
+
+<p>Define the service meta data in separate XML file, as shown in the following example. The service
+meta data must include a setup interface that describes the TV input's initial configuration and
+channel scan. Also, the service meta data may (optionally) describe a settings activity for users to
+modify the TV input's behavior. The service meta data file is located in the XML resources directory
+for your application and must match the name of the resource in the manifest. Using the example
+manifest entries above, you would create an XML file in the location
+<code>res/xml/sample_tv_input.xml</code>, with the following contents:</p>
+
+<pre>
+&lt;tv-input xmlns:android="http://schemas.android.com/apk/res/android"
+  &lt;!-- Required: activity for setting up the input --&gt;
+  android:setupActivity="com.example.sampletvinput.SampleTvInputSetupActivity"
+  &lt;!-- Optional: activity for controlling the settings --&gt;
+  android:settingsActivity="com.example.sampletvinput.SampleTvInputSettingsActivity" /&gt;
+</pre>
+
+<h2 id="tvinput">Define Your TV Input Service</h2>
+
+<div class="figure">
+<img id="tvinputlife" src="{@docRoot}images/tv/tvinput-life.png" alt=""/>
+<p class="img-caption"><strong>Figure 1.</strong>TvInputService lifecycle.</p>
+</div>
+
+<p>For your service, you extend the {@link android.media.tv.TvInputService} class. A
+{@link android.media.tv.TvInputService} implementation is a
+<a href="{@docRoot}guide/components/bound-services.html">bound service</a> where the system service
+(<code>TvInputManagerService</code>) is the client that binds to it. The service life cycle methods
+you need to implement are illustrated in figure 1.</p>
+
+<p>The {@link android.app.Service#onCreate()} method initializes and starts the
+{@link android.os.HandlerThread} which provides a process thread separate from the UI thread to
+handle system-driven actions. In the following example, the {@link android.app.Service#onCreate()}
+method initializes the {@link android.view.accessibility.CaptioningManager} and prepares to handle
+the {@link android.media.tv.TvInputManager#ACTION_BLOCKED_RATINGS_CHANGED}
+and {@link android.media.tv.TvInputManager#ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED} actions. These
+actions describe system intents fired when the user changes the parental control settings, and when
+there is a change on the list of blocked ratings.</p>
+
+<pre>
+&#64;Override
+public void onCreate() {
+    super.onCreate();
+    mHandlerThread = new HandlerThread(getClass()
+      .getSimpleName());
+    mHandlerThread.start();
+    mDbHandler = new Handler(mHandlerThread.getLooper());
+    mHandler = new Handler();
+    mCaptioningManager = (CaptioningManager)
+      getSystemService(Context.CAPTIONING_SERVICE);
+
+    setTheme(android.R.style.Theme_Holo_Light_NoActionBar);
+
+    mSessions = new ArrayList&lt;BaseTvInputSessionImpl&gt;();
+    IntentFilter intentFilter = new IntentFilter();
+    intentFilter.addAction(TvInputManager
+      .ACTION_BLOCKED_RATINGS_CHANGED);
+    intentFilter.addAction(TvInputManager
+      .ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
+    registerReceiver(mBroadcastReceiver, intentFilter);
+}
+</pre>
+
+<p> See <a href="{@docRoot}training/tv/tif/ui.html#control">
+Control Content</a> for more information about working with blocked content and providing
+parental control. See {@link android.media.tv.TvInputManager} for more system-driven actions that
+you may want to handle in your TV input service.</p>
+
+<p>The {@link android.media.tv.TvInputService} creates a
+{@link android.media.tv.TvInputService.Session} that implements {@link android.os.Handler.Callback}
+to handle player state changes. With {@link android.media.tv.TvInputService.Session#onSetSurface(android.view.Surface) onSetSurface()},
+the {@link android.media.tv.TvInputService.Session} sets the {@link android.view.Surface} with the
+video content. See <a href="{@docRoot}training/tv/tif/ui.html#surface">Integrate Player with Surface</a>
+for more information about working with {@link android.view.Surface} to render video.</p>
+
+<p>The {@link android.media.tv.TvInputService.Session} handles the
+{@link android.media.tv.TvInputService.Session#onTune(android.net.Uri) onTune()}
+event when the user selects a channel, and notifies the system TV app for changes in the content and
+content meta data. These <code>notify()</code>code> methods are described in
+<a href="{@docRoot}training/tv/tif/ui.html#control">
+Control Content</a> and <a href="training/tv/tif/ui.html#track">Handle Track Selection</a> further
+in this training.</p>
+
+<h2 id="setup">Define Setup and Settings Activities</h2>
+
+<p>The system TV app works with the setup and settings activities you define for your TV input. The
+setup activity is required and must provide at least one channel record for the system database. The
+system TV app will invoke the setup activity when it cannot find a channel for the TV input.
+<p>The setup activity describes to the system TV app the channels made available through the TV
+input, as demonstrated in the next lesson, <a href="{@docRoot}training/tv/tif/channel.html">Creating
+and Updating Channel Data</a>.</p>
+
+<p>The settings activity is optional. You can define a settings activity to turn on parental
+controls, enable closed captions, set the display attributes, and so forth.</p>
+
+
diff --git a/docs/html/training/tv/tif/ui.jd b/docs/html/training/tv/tif/ui.jd
new file mode 100644
index 0000000..6ead3db
--- /dev/null
+++ b/docs/html/training/tv/tif/ui.jd
@@ -0,0 +1,304 @@
+page.title=Managing User Interaction
+page.tags=tv, tif
+helpoutsWidget=true
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>This lesson teaches you to</h2>
+  <ol>
+    <li><a href="#surface">Integrate Player with Surface</a></li>
+    <li><a href="#overlay">Use an Overlay</a></li>
+    <li><a href="#control">Control Content</a></li>
+    <li><a href="#track">Handle Track Selection</a></li>
+  </ol>
+  <h2>Try It Out</h2>
+  <ul>
+    <li><a class="external-link" href="https://github.com/googlesamples/androidtv-sample-inputs">
+      TV Input Service sample app</a></li>
+  </ul>
+</div>
+</div>
+
+<p>In the live TV experience the user changes channels and is presented with
+channel and program information briefly before the information disappears. Other types of information,
+such as messages ("DO NOT ATTEMPT AT HOME"), subtitles, or ads may need to persist. As with any TV
+app, such information should not interfere with the program content playing on the screen.</p>
+
+<img src="{@docRoot}images/tv/do-not-attempt.png" id="figure1">
+<p class="img-caption">
+  <strong>Figure 1.</strong> An overlay message in a live TV app.
+</p>
+
+<p>Also consider whether certain program content should be presented, given the
+content's rating and parental control settings, and how your app behaves and informs the user when
+content is blocked or unavailable. This lesson describes how to develop your TV input's user
+experience for these considerations.</p>
+
+<h2 id="surface">Integrate Player with Surface</h2>
+
+<p>Your TV input must render video onto a {@link android.view.Surface} object, which is passed by
+the {@link android.media.tv.TvInputService.Session#onSetSurface(android.view.Surface) TvInputService.Session.onSetSurface()}
+method. Here's an example of how to use a {@link android.media.MediaPlayer} instance for playing
+content in the {@link android.view.Surface} object:</p>
+
+<pre>
+&#64;Override
+public boolean onSetSurface(Surface surface) {
+    if (mPlayer != null) {
+        mPlayer.setSurface(surface);
+    }
+    mSurface = surface;
+    return true;
+}
+
+&#64;Override
+public void onSetStreamVolume(float volume) {
+    if (mPlayer != null) {
+        mPlayer.setVolume(volume, volume);
+    }
+    mVolume = volume;
+}
+</pre>
+
+<p>Similarly, here's how to do it using <a href="{@docRoot}guide/topics/media/exoplayer.html">
+ExoPlayer</a>:</p>
+
+<pre>
+&#64;Override
+public boolean onSetSurface(Surface surface) {
+    if (mPlayer != null) {
+        mPlayer.sendMessage(mVideoRenderer,
+                MediaCodecVideoTrackRenderer.MSG_SET_SURFACE,
+                surface);
+    }
+    mSurface = surface;
+    return true;
+}
+
+&#64;Override
+public void onSetStreamVolume(float volume) {
+    if (mPlayer != null) {
+        mPlayer.sendMessage(mAudioRenderer,
+                MediaCodecAudioTrackRenderer.MSG_SET_VOLUME,
+                volume);
+    }
+    mVolume = volume;
+}
+</pre>
+
+<h2 id="overlay">Use an Overlay</h2>
+
+<p>Use an overlay to display subtitles, messages, ads or MHEG-5 data broadcasts. By default, the
+overlay is disabled. You can enable it when you create the session by calling
+{@link android.media.tv.TvInputService.Session#setOverlayViewEnabled(boolean) TvInputService.Session.setOverlayViewEnabled(true)},
+as in the following example:</p>
+
+<pre>
+&#64;Override
+public final Session onCreateSession(String inputId) {
+    BaseTvInputSessionImpl session = onCreateSessionInternal(inputId);
+    session.setOverlayViewEnabled(true);
+    mSessions.add(session);
+    return session;
+}
+</pre>
+
+<p>Use a {@link android.view.View} object for the overlay, returned from {@link android.media.tv.TvInputService.Session#onCreateOverlayView() TvInputService.Session.onCreateOverlayView()}, as shown here:</p>
+
+<pre>
+&#64;Override
+public View onCreateOverlayView() {
+    LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
+    View view = inflater.inflate(R.layout.overlayview, null);
+    mSubtitleView = (SubtitleView) view.findViewById(R.id.subtitles);
+
+    // Configure the subtitle view.
+    CaptionStyleCompat captionStyle;
+    float captionTextSize = getCaptionFontSize();
+    captionStyle = CaptionStyleCompat.createFromCaptionStyle(
+            mCaptioningManager.getUserStyle());
+    captionTextSize *= mCaptioningManager.getFontScale();
+    mSubtitleView.setStyle(captionStyle);
+    mSubtitleView.setTextSize(captionTextSize);
+    return view;
+}
+</pre>
+
+<p>The layout definition for the overlay might look something like this:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"&gt;
+
+    &lt;com.google.android.exoplayer.text.SubtitleView
+        android:id="@+id/subtitles"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom|center_horizontal"
+        android:layout_marginLeft="16dp"
+        android:layout_marginRight="16dp"
+        android:layout_marginBottom="32dp"
+        android:visibility="invisible"/&gt;
+&lt;/FrameLayout&gt;
+</pre>
+
+<h2 id="control">Control Content</h2>
+
+<p>When the user selects a channel, your TV input handles the {@link android.media.tv.TvInputService.Session#onTune(android.net.Uri)
+onTune()} callback in the {@link android.media.tv.TvInputService.Session} object. The system TV
+app's parental controls determine what content displays, given the content rating.
+The following sections describe how to manage channel and program selection using the
+{@link android.media.tv.TvInputService.Session} <code>notify</code> methods that
+communicate with the system TV app.</p>
+
+<h3 id="unavailable">Make Video Unavailable</h3>
+
+<p>When the user changes the channel, you want to make sure the screen doesn't display any stray
+video artifacts before your TV input renders the content. When you call {@link android.media.tv.TvInputService.Session#onTune(android.net.Uri) TvInputService.Session.onTune()},
+you can prevent the video from being presented by calling {@link android.media.tv.TvInputService.Session#notifyVideoUnavailable(int) TvInputService.Session.notifyVideoUnavailable()}
+and passing the {@link android.media.tv.TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNING} constant, as
+shown in the following example.</p>
+
+<pre>
+&#64;Override
+public boolean onTune(Uri channelUri) {
+    if (mSubtitleView != null) {
+        mSubtitleView.setVisibility(View.INVISIBLE);
+    }
+    notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);
+    mUnblockedRatingSet.clear();
+
+    mDbHandler.removeCallbacks(mPlayCurrentProgramRunnable);
+    mPlayCurrentProgramRunnable = new PlayCurrentProgramRunnable(channelUri);
+    mDbHandler.post(mPlayCurrentProgramRunnable);
+    return true;
+}
+</pre>
+
+<p>Then, when the content is rendered to the {@link android.view.Surface}, you call
+{@link android.media.tv.TvInputService.Session#notifyVideoAvailable() TvInputService.Session.notifyVideoAvailable()}
+to allow the video to display, like so:</p>
+
+<pre>
+&#64;Override
+public void onDrawnToSurface(Surface surface) {
+    mFirstFrameDrawn = true;
+    notifyVideoAvailable();
+}
+</pre>
+
+<p>This transition lasts only for fractions of a second, but presenting a blank screen is
+visually better than allowing the picture to flash odd blips and jitters.</p>
+
+<p>See also, <a href="#surface">Integrate Player with Surface</a> for more information about working
+with {@link android.view.Surface} to render video.</p>
+
+<h3 id="parental">Provide Parental Control</h3>
+
+<p>To determine if a given content is blocked by parental controls and content rating, you check the
+{@link android.media.tv.TvInputManager} class methods, {@link android.media.tv.TvInputManager#isParentalControlsEnabled()}
+and {@link android.media.tv.TvInputManager#isRatingBlocked(android.media.tv.TvContentRating)}. You
+might also want to make sure the content's {@link android.media.tv.TvContentRating} is included in a
+set of currently allowed content ratings. These considerations are shown in the following sample.</p>
+
+<pre>
+private void checkContentBlockNeeded() {
+    if (mCurrentContentRating == null || !mTvInputManager.isParentalControlsEnabled()
+            || !mTvInputManager.isRatingBlocked(mCurrentContentRating)
+            || mUnblockedRatingSet.contains(mCurrentContentRating)) {
+        // Content rating is changed so we don't need to block anymore.
+        // Unblock content here explicitly to resume playback.
+        unblockContent(null);
+        return;
+    }
+
+    mLastBlockedRating = mCurrentContentRating;
+    if (mPlayer != null) {
+        // Children restricted content might be blocked by TV app as well,
+        // but TIF should do its best not to show any single frame of blocked content.
+        releasePlayer();
+    }
+
+    notifyContentBlocked(mCurrentContentRating);
+}
+</pre>
+
+<p>Once you have determined if the content should or should not be blocked, notify the system TV
+app by calling the
+{@link android.media.tv.TvInputService.Session} method {@link android.media.tv.TvInputService.Session#notifyContentAllowed() notifyContentAllowed()}
+or
+{@link android.media.tv.TvInputService.Session#notifyContentBlocked(android.media.tv.TvContentRating) notifyContentBlocked()}
+, as shown in the previous example.</p>
+
+<p>Use the {@link android.media.tv.TvContentRating} class to generate the system-defined string for
+the {@link android.media.tv.TvContract.Programs#COLUMN_CONTENT_RATING} with the
+<code><a href="{@docRoot}reference/android/media/tv/TvContentRating.html#createRating(java.lang.String, java.lang.String, java.lang.String, java.lang.String...)">TvContentRating.createRating()</a></code>
+method, as shown here:</p>
+
+<pre>
+TvContentRating rating = TvContentRating.createRating(
+    "com.android.tv",
+    "US_TV",
+    "US_TV_PG",
+    "US_TV_D", "US_TV_L");
+</pre>
+
+<h2 id="track">Handle Track Selection</h2>
+
+<p>The {@link android.media.tv.TvTrackInfo} class holds information about media tracks such
+as the track type (video, audio, or subtitle) and so forth. </p>
+
+<p>The first time your TV input session is able to get track information, it should call
+<code><a href="{@docRoot}reference/android/media/tv/TvInputService.Session.html#notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>)">TvInputService.Session.notifyTracksChanged()</a></code> with a list of all tracks to update the system TV app.  When there
+is a change in track information, call
+<code><a href="{@docRoot}reference/android/media/tv/TvInputService.Session.html#notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>)">notifyTracksChanged()</a></code>
+again to update the system.
+
+</p>
+
+<p>The system TV app provides an interface for the user to select a specific track if more than one
+track is available for a given track type; for example, subtitles in different languages. Your TV
+input responds to the
+{@link android.media.tv.TvInputService.Session#onSelectTrack(int, java.lang.String) onSelectTrack()}
+call from the system TV app by calling
+{@link android.media.tv.TvInputService.Session#notifyTrackSelected(int, java.lang.String) notifyTrackSelected()}
+, as shown in the following example. Note that when <code>null</code>
+is passed as the track ID, this <em>deselects</em> the track.</p>
+
+<pre>
+&#64;Override
+public boolean onSelectTrack(int type, String trackId) {
+    if (mPlayer != null) {
+        if (type == TvTrackInfo.TYPE_SUBTITLE) {
+            if (!mCaptionEnabled && trackId != null) {
+                return false;
+            }
+            mSelectedSubtitleTrackId = trackId;
+            if (trackId == null) {
+                mSubtitleView.setVisibility(View.INVISIBLE);
+            }
+        }
+        if (mPlayer.selectTrack(type, trackId)) {
+            notifyTrackSelected(type, trackId);
+            return true;
+        }
+    }
+    return false;
+}
+</pre>
+
+
+
+
+
+
+
diff --git a/docs/html/training/wearables/apps/voice.jd b/docs/html/training/wearables/apps/voice.jd
index 6d49319..3aef3c4 100644
--- a/docs/html/training/wearables/apps/voice.jd
+++ b/docs/html/training/wearables/apps/voice.jd
@@ -131,6 +131,17 @@
   </tr>
 
   <tr>
+    <td>Start stopwatch</td>
+    <td>"Ok Google, start stopwatch"</td>
+    <td>
+      <dl>
+        <dt>Action</dt>
+        <dd><code>com.google.android.wearable.action.STOPWATCH</code></dd>
+      </dl>
+   </td>
+  </tr>
+
+  <tr>
     <td>Start/Stop a bike ride</td>
     <td>"OK Google, start cycling"<br/><br/>"OK Google, start my bike ride"<br/><br/>"OK Google, stop cycling"</td>
     <td>
diff --git a/docs/html/training/wearables/watch-faces/drawing.jd b/docs/html/training/wearables/watch-faces/drawing.jd
index 3c5da34..60da5d5 100644
--- a/docs/html/training/wearables/watch-faces/drawing.jd
+++ b/docs/html/training/wearables/watch-faces/drawing.jd
@@ -377,7 +377,8 @@
 
 <ul>
 <li>For devices that use low-bit ambient mode, the screen supports fewer bits for each color
-in ambient mode, so you should disable anti-aliasing.</li>
+in ambient mode, so you should disable anti-aliasing and bitmap filtering when the device switches
+to ambient mode.</li>
 <li>For devices that require burn-in protection, avoid using large blocks of white pixels in
 ambient mode and do not place content within 10 pixels of the edge of the screen, since the
 system shifts the content periodically to avoid pixel burn-in.</li>
@@ -385,7 +386,9 @@
 
 <p>For more information about low-bit ambient mode and burn-in protection, see
 <a href="{@docRoot}design/wear/watchfaces.html#SpecialScreens">Optimize for Special
-Screens</a>.</p>
+Screens</a>. For more information on how to disable bitmap filtering, see
+<a href="{@docRoot}training/wearables/watch-faces/performance.html#BitmapFiltering">Bitmap
+Filtering</a>.</p>
 
 
 <h2 id="Modes">Respond to Changes Between Modes</h2>
diff --git a/docs/html/training/wearables/watch-faces/performance.jd b/docs/html/training/wearables/watch-faces/performance.jd
index 68438fe..118bc6a 100644
--- a/docs/html/training/wearables/watch-faces/performance.jd
+++ b/docs/html/training/wearables/watch-faces/performance.jd
@@ -99,7 +99,9 @@
 setFilterBitmap()} method. <a href="#fig2">Figure 2</a> shows a magnified view of a clock hand with
 and without bitmap filtering.</p>
 
-
+<p class="note"><strong>Note:</strong> In low-bit ambient mode, the system does not reliably
+render the colors in the image for bitmap filtering to process successfully. When ambient mode is
+active, disable bitmap filtering.</p>
 
 <h2 id="OutDrawing">Move Expensive Operations Outside the Drawing Method</h2>
 
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 150f195..48afcbf 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -45,6 +45,8 @@
  * Canvas and Drawables</a> developer guide.</p></div>
  */
 public class Canvas {
+    /** @hide */
+    public static boolean sCompatibilityRestore = false;
 
     /**
      * Should only be assigned in constructors (or setBitmap if software canvas),
@@ -557,7 +559,8 @@
      * an error to call restore() more times than save() was called.
      */
     public void restore() {
-        native_restore(mNativeCanvasWrapper);
+        boolean throwOnUnderflow = !sCompatibilityRestore || !isHardwareAccelerated();
+        native_restore(mNativeCanvasWrapper, throwOnUnderflow);
     }
 
     /**
@@ -582,7 +585,8 @@
      * @param saveCount The save level to restore to.
      */
     public void restoreToCount(int saveCount) {
-        native_restoreToCount(mNativeCanvasWrapper, saveCount);
+        boolean throwOnUnderflow = !sCompatibilityRestore || !isHardwareAccelerated();
+        native_restoreToCount(mNativeCanvasWrapper, saveCount, throwOnUnderflow);
     }
 
     /**
@@ -1988,9 +1992,10 @@
     private static native int native_saveLayerAlpha(long nativeCanvas, float l,
                                                     float t, float r, float b,
                                                     int alpha, int layerFlags);
-    private static native void native_restore(long canvasHandle);
+    private static native void native_restore(long canvasHandle, boolean tolerateUnderflow);
     private static native void native_restoreToCount(long canvasHandle,
-                                                     int saveCount);
+                                                     int saveCount,
+                                                     boolean tolerateUnderflow);
     private static native int native_getSaveCount(long canvasHandle);
 
     private static native void native_translate(long canvasHandle,
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 49c4247..c63c8ba 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -356,6 +356,108 @@
     public static final int RAW10 = 0x25;
 
     /**
+     * <p>
+     * Android 12-bit raw format
+     * </p>
+     * <p>
+     * This is a single-plane, 12-bit per pixel, densely packed (in each row),
+     * unprocessed format, usually representing raw Bayer-pattern images coming
+     * from an image sensor.
+     * </p>
+     * <p>
+     * In an image buffer with this format, starting from the first pixel of each
+     * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first
+     * and second byte contains the top 8 bits of first and second pixel. The third
+     * byte contains the 4 least significant bits of the two pixels, the exact layout
+     * data for each two consecutive pixels is illustrated below (Pi[j] stands for
+     * the jth bit of the ith pixel):
+     * </p>
+     * <table>
+     * <thead>
+     * <tr>
+     * <th align="center"></th>
+     * <th align="center">bit 7</th>
+     * <th align="center">bit 6</th>
+     * <th align="center">bit 5</th>
+     * <th align="center">bit 4</th>
+     * <th align="center">bit 3</th>
+     * <th align="center">bit 2</th>
+     * <th align="center">bit 1</th>
+     * <th align="center">bit 0</th>
+     * </tr>
+     * </thead> <tbody>
+     * <tr>
+     * <td align="center">Byte 0:</td>
+     * <td align="center">P0[11]</td>
+     * <td align="center">P0[10]</td>
+     * <td align="center">P0[ 9]</td>
+     * <td align="center">P0[ 8]</td>
+     * <td align="center">P0[ 7]</td>
+     * <td align="center">P0[ 6]</td>
+     * <td align="center">P0[ 5]</td>
+     * <td align="center">P0[ 4]</td>
+     * </tr>
+     * <tr>
+     * <td align="center">Byte 1:</td>
+     * <td align="center">P1[11]</td>
+     * <td align="center">P1[10]</td>
+     * <td align="center">P1[ 9]</td>
+     * <td align="center">P1[ 8]</td>
+     * <td align="center">P1[ 7]</td>
+     * <td align="center">P1[ 6]</td>
+     * <td align="center">P1[ 5]</td>
+     * <td align="center">P1[ 4]</td>
+     * </tr>
+     * <tr>
+     * <td align="center">Byte 2:</td>
+     * <td align="center">P1[ 3]</td>
+     * <td align="center">P1[ 2]</td>
+     * <td align="center">P1[ 1]</td>
+     * <td align="center">P1[ 0]</td>
+     * <td align="center">P0[ 3]</td>
+     * <td align="center">P0[ 2]</td>
+     * <td align="center">P0[ 1]</td>
+     * <td align="center">P0[ 0]</td>
+     * </tr>
+     * </tbody>
+     * </table>
+     * <p>
+     * This format assumes
+     * <ul>
+     * <li>a width multiple of 4 pixels</li>
+     * <li>an even height</li>
+     * </ul>
+     * </p>
+     *
+     * <pre>size = row stride * height</pre> where the row stride is in <em>bytes</em>,
+     * not pixels.
+     *
+     * <p>
+     * Since this is a densely packed format, the pixel stride is always 0. The
+     * application must use the pixel data layout defined in above table to
+     * access each row data. When row stride is equal to {@code width * (12 / 8)}, there
+     * will be no padding bytes at the end of each row, the entire image data is
+     * densely packed. When stride is larger than {@code width * (12 / 8)}, padding
+     * bytes will be present at the end of each row.
+     * </p>
+     * <p>
+     * For example, the {@link android.media.Image} object can provide data in
+     * this format from a {@link android.hardware.camera2.CameraDevice} (if
+     * supported) through a {@link android.media.ImageReader} object. The
+     * {@link android.media.Image#getPlanes() Image#getPlanes()} will return a
+     * single plane containing the pixel data. The pixel stride is always 0 in
+     * {@link android.media.Image.Plane#getPixelStride()}, and the
+     * {@link android.media.Image.Plane#getRowStride()} describes the vertical
+     * neighboring pixel distance (in bytes) between adjacent rows.
+     * </p>
+     *
+     * @see android.media.Image
+     * @see android.media.ImageReader
+     * @see android.hardware.camera2.CameraDevice
+     */
+    public static final int RAW12 = 0x26;
+
+    /**
      * Android dense depth image format.
      *
      * Each pixel is 16 bits, representing a depth ranging measurement from
@@ -388,6 +490,33 @@
     public static final int DEPTH_POINT_CLOUD = 0x101;
 
     /**
+     * Android private opaque image format.
+     * <p>
+     * The choices of the actual format and pixel data layout are entirely up to
+     * the device-specific and framework internal implementations, and may vary
+     * depending on use cases even for the same device. The buffers of this
+     * format can be produced by components like
+     * {@link android.media.ImageWriter ImageWriter} , and interpreted correctly
+     * by consumers like {@link android.hardware.camera2.CameraDevice
+     * CameraDevice} based on the device/framework private information. However,
+     * these buffers are not directly accessible to the application.
+     * </p>
+     * <p>
+     * When an {@link android.media.Image Image} of this format is obtained from
+     * an {@link android.media.ImageReader ImageReader} or
+     * {@link android.media.ImageWriter ImageWriter}, the
+     * {@link android.media.Image#getPlanes() getPlanes()} method will return an
+     * empty {@link android.media.Image.Plane Plane} array.
+     * </p>
+     * <p>
+     * If a buffer of this format is to be used as an OpenGL ES texture, the
+     * framework will assume that sampling the texture will always return an
+     * alpha value of 1.0 (i.e. the buffer contains only opaque pixel values).
+     * </p>
+     */
+    public static final int PRIVATE = 0x22;
+
+    /**
      * Use this function to retrieve the number of bits per pixel of an
      * ImageFormat.
      *
@@ -418,6 +547,8 @@
                 return 16;
             case RAW10:
                 return 10;
+            case RAW12:
+                return 12;
         }
         return -1;
     }
@@ -445,8 +576,10 @@
             case YUV_420_888:
             case RAW_SENSOR:
             case RAW10:
+            case RAW12:
             case DEPTH16:
             case DEPTH_POINT_CLOUD:
+            case PRIVATE:
                 return true;
         }
 
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 1da198c..cd5f59d 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -2120,9 +2120,9 @@
         int contextLen = contextEnd - contextStart;
         char[] buf = TemporaryBuffer.obtain(contextLen);
         TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
-        int result = getTextRunCursor(buf, 0, contextLen, dir, offset - contextStart, cursorOpt);
+        int relPos = getTextRunCursor(buf, 0, contextLen, dir, offset - contextStart, cursorOpt);
         TemporaryBuffer.recycle(buf);
-        return result;
+        return (relPos == -1) ? -1 : relPos + contextStart;
     }
 
     /**
@@ -2249,6 +2249,26 @@
             bounds);
     }
 
+    /**
+     * Determine whether the typeface set on the paint has a glyph supporting the string. The
+     * simplest case is when the string contains a single character, in which this method
+     * determines whether the font has the character. In the case of multiple characters, the
+     * method returns true if there is a single glyph representing the ligature. For example, if
+     * the input is a pair of regional indicator symbols, determine whether there is an emoji flag
+     * for the pair.
+     *
+     * Finally, if the string contains a variation selector, the method only returns true if
+     * the fonts contains a glyph specific to that variation.
+     *
+     * Checking is done on the entire fallback chain, not just the immediate font referenced.
+     *
+     * @param string the string to test whether there is glyph support
+     * @return true if the typeface has a glyph for the string
+     */
+    public boolean hasGlyph(String string) {
+        return native_hasGlyph(mNativePaint, mNativeTypeface, mBidiFlags, string);
+    }
+
     @Override
     protected void finalize() throws Throwable {
         try {
@@ -2334,4 +2354,6 @@
                                                              String settings);
     private static native int native_getHyphenEdit(long native_object);
     private static native void native_setHyphenEdit(long native_object, int hyphen);
+    private static native boolean native_hasGlyph(long native_object, long native_typeface,
+            int bidiFlags, String string);
 }
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 17e5b0b..28c26ff 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -16,6 +16,8 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorInflater;
+import android.animation.AnimatorSet;
+import android.animation.Animator.AnimatorListener;
 import android.annotation.NonNull;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -37,6 +39,7 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * This class uses {@link android.animation.ObjectAnimator} and
@@ -47,8 +50,8 @@
  * </p>
  * <p>
  * First is the XML file for {@link android.graphics.drawable.VectorDrawable}.
- * Note that we allow the animation happen on the group's attributes and path's
- * attributes, which requires they are uniquely named in this xml file. Groups
+ * Note that we allow the animation to happen on the group's attributes and path's
+ * attributes, which requires they are uniquely named in this XML file. Groups
  * and paths without animations do not need names.
  * </p>
  * <li>Here is a simple VectorDrawable in this vectordrawable.xml file.
@@ -71,7 +74,7 @@
  * &lt;/vector&gt;
  * </pre></li>
  * <p>
- * Second is the AnimatedVectorDrawable's xml file, which defines the target
+ * Second is the AnimatedVectorDrawable's XML file, which defines the target
  * VectorDrawable, the target paths and groups to animate, the properties of the
  * path and group to animate and the animations defined as the ObjectAnimators
  * or AnimatorSets.
@@ -90,7 +93,7 @@
  * &lt;/animated-vector&gt;
  * </pre></li>
  * <p>
- * Last is the Animator xml file, which is the same as a normal ObjectAnimator
+ * Last is the Animator XML file, which is the same as a normal ObjectAnimator
  * or AnimatorSet.
  * To complete this example, here are the 2 animator files used in avd.xml:
  * rotation.xml and path_morph.xml.
@@ -107,7 +110,7 @@
  * the other. Note that the paths must be compatible for morphing.
  * In more details, the paths should have exact same length of commands , and
  * exact same length of parameters for each commands.
- * Note that the path string are better stored in strings.xml for reusing.
+ * Note that the path strings are better stored in strings.xml for reusing.
  * <pre>
  * &lt;set xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
  *     &lt;objectAnimator
@@ -170,7 +173,7 @@
 
     @Override
     public int getChangingConfigurations() {
-        return super.getChangingConfigurations() | mAnimatedVectorState.mChangingConfigurations;
+        return super.getChangingConfigurations() | mAnimatedVectorState.getChangingConfigurations();
     }
 
     @Override
@@ -312,6 +315,15 @@
 
             eventType = parser.next();
         }
+        setupAnimatorSet();
+    }
+
+    private void setupAnimatorSet() {
+        if (mAnimatedVectorState.mTempAnimators != null) {
+            mAnimatedVectorState.mAnimatorSet.playTogether(mAnimatedVectorState.mTempAnimators);
+            mAnimatedVectorState.mTempAnimators.clear();
+            mAnimatedVectorState.mTempAnimators = null;
+        }
     }
 
     @Override
@@ -330,10 +342,44 @@
         }
     }
 
+    /**
+     * Adds a listener to the set of listeners that are sent events through the life of an
+     * animation.
+     *
+     * @param listener the listener to be added to the current set of listeners for this animation.
+     */
+    public void addListener(AnimatorListener listener) {
+        mAnimatedVectorState.mAnimatorSet.addListener(listener);
+    }
+
+    /**
+     * Removes a listener from the set listening to this animation.
+     *
+     * @param listener the listener to be removed from the current set of listeners for this
+     *                 animation.
+     */
+    public void removeListener(AnimatorListener listener) {
+        mAnimatedVectorState.mAnimatorSet.removeListener(listener);
+    }
+
+    /**
+     * Gets the set of {@link android.animation.Animator.AnimatorListener} objects that are currently
+     * listening for events on this <code>AnimatedVectorDrawable</code> object.
+     *
+     * @return List<AnimatorListener> The set of listeners.
+     */
+    public List<AnimatorListener> getListeners() {
+        return mAnimatedVectorState.mAnimatorSet.getListeners();
+    }
+
     private static class AnimatedVectorDrawableState extends ConstantState {
         int mChangingConfigurations;
         VectorDrawable mVectorDrawable;
-        ArrayList<Animator> mAnimators;
+        // Always have a valid animatorSet to handle all the listeners call.
+        AnimatorSet mAnimatorSet = new AnimatorSet();
+        // When parsing the XML, we build individual animator and store in this array. At the end,
+        // we add this array into the mAnimatorSet.
+        private ArrayList<Animator> mTempAnimators;
         ArrayMap<Animator, String> mTargetNameMap;
 
         public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy,
@@ -353,18 +399,23 @@
                     mVectorDrawable.setBounds(copy.mVectorDrawable.getBounds());
                     mVectorDrawable.setAllowCaching(false);
                 }
-                if (copy.mAnimators != null) {
-                    final int numAnimators = copy.mAnimators.size();
-                    mAnimators = new ArrayList<Animator>(numAnimators);
+                if (copy.mAnimatorSet != null) {
+                    final int numAnimators = copy.mTargetNameMap.size();
+                    // Deep copy a animator set, and then setup the target map again.
+                    mAnimatorSet = copy.mAnimatorSet.clone();
                     mTargetNameMap = new ArrayMap<Animator, String>(numAnimators);
+                    // Since the new AnimatorSet is cloned from the old one, the order must be the
+                    // same inside the array.
+                    ArrayList<Animator> oldAnim = copy.mAnimatorSet.getChildAnimations();
+                    ArrayList<Animator> newAnim = mAnimatorSet.getChildAnimations();
+
                     for (int i = 0; i < numAnimators; ++i) {
-                        Animator anim = copy.mAnimators.get(i);
-                        Animator animClone = anim.clone();
-                        String targetName = copy.mTargetNameMap.get(anim);
-                        Object targetObject = mVectorDrawable.getTargetByName(targetName);
-                        animClone.setTarget(targetObject);
-                        mAnimators.add(animClone);
-                        mTargetNameMap.put(animClone, targetName);
+                        // Target name must be the same for new and old
+                        String targetName = copy.mTargetNameMap.get(oldAnim.get(i));
+
+                        Object newTargetObject = mVectorDrawable.getTargetByName(targetName);
+                        newAnim.get(i).setTarget(newTargetObject);
+                        mTargetNameMap.put(newAnim.get(i), targetName);
                     }
                 }
             } else {
@@ -397,11 +448,11 @@
     private void setupAnimatorsForTarget(String name, Animator animator) {
         Object target = mAnimatedVectorState.mVectorDrawable.getTargetByName(name);
         animator.setTarget(target);
-        if (mAnimatedVectorState.mAnimators == null) {
-            mAnimatedVectorState.mAnimators = new ArrayList<Animator>();
+        if (mAnimatedVectorState.mTempAnimators == null) {
+            mAnimatedVectorState.mTempAnimators = new ArrayList<Animator>();
             mAnimatedVectorState.mTargetNameMap = new ArrayMap<Animator, String>();
         }
-        mAnimatedVectorState.mAnimators.add(animator);
+        mAnimatedVectorState.mTempAnimators.add(animator);
         mAnimatedVectorState.mTargetNameMap.put(animator, name);
         if (DBG_ANIMATION_VECTOR_DRAWABLE) {
             Log.v(LOGTAG, "add animator  for target " + name + " " + animator);
@@ -410,27 +461,11 @@
 
     @Override
     public boolean isRunning() {
-        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
-        final int size = animators.size();
-        for (int i = 0; i < size; i++) {
-            final Animator animator = animators.get(i);
-            if (animator.isRunning()) {
-                return true;
-            }
-        }
-        return false;
+        return mAnimatedVectorState.mAnimatorSet.isRunning();
     }
 
     private boolean isStarted() {
-        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
-        final int size = animators.size();
-        for (int i = 0; i < size; i++) {
-            final Animator animator = animators.get(i);
-            if (animator.isStarted()) {
-                return true;
-            }
-        }
-        return false;
+        return mAnimatedVectorState.mAnimatorSet.isStarted();
     }
 
     @Override
@@ -439,24 +474,13 @@
         if (isStarted()) {
             return;
         }
-        // Otherwise, kick off every animator.
-        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
-        final int size = animators.size();
-        for (int i = 0; i < size; i++) {
-            final Animator animator = animators.get(i);
-            animator.start();
-        }
+        mAnimatedVectorState.mAnimatorSet.start();
         invalidateSelf();
     }
 
     @Override
     public void stop() {
-        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
-        final int size = animators.size();
-        for (int i = 0; i < size; i++) {
-            final Animator animator = animators.get(i);
-            animator.end();
-        }
+        mAnimatedVectorState.mAnimatorSet.end();
     }
 
     /**
@@ -473,27 +497,14 @@
             Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
             return;
         }
-        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
-        final int size = animators.size();
-        for (int i = 0; i < size; i++) {
-            final Animator animator = animators.get(i);
-            animator.reverse();
-        }
+        mAnimatedVectorState.mAnimatorSet.reverse();
     }
 
     /**
      * @hide
      */
     public boolean canReverse() {
-        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
-        final int size = animators.size();
-        for (int i = 0; i < size; i++) {
-            final Animator animator = animators.get(i);
-            if (!animator.canReverse()) {
-                return false;
-            }
-        }
-        return true;
+        return mAnimatedVectorState.mAnimatorSet.canReverse();
     }
 
     private final Callback mCallback = new Callback() {
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 68ffed6..6fe6b56 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -454,7 +454,7 @@
 
     @Override
     public int getChangingConfigurations() {
-        return super.getChangingConfigurations() | mBitmapState.mChangingConfigurations;
+        return super.getChangingConfigurations() | mBitmapState.getChangingConfigurations();
     }
 
     private boolean needMirroring() {
@@ -721,7 +721,7 @@
 
         final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.BitmapDrawable);
         updateStateFromTypedArray(a);
-        verifyState(a);
+        verifyRequiredAttributes(a);
         a.recycle();
 
         // Update local properties.
@@ -733,11 +733,13 @@
      *
      * @throws XmlPullParserException if any required attributes are missing
      */
-    private void verifyState(TypedArray a) throws XmlPullParserException {
+    private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+        // If we're not waiting on a theme, verify required attributes.
         final BitmapState state = mBitmapState;
-        if (state.mBitmap == null) {
+        if (state.mBitmap == null && (state.mThemeAttrs == null
+                || state.mThemeAttrs[R.styleable.BitmapDrawable_src] == 0)) {
             throw new XmlPullParserException(a.getPositionDescription() +
-                    ": <bitmap> requires a valid src attribute");
+                    ": <bitmap> requires a valid 'src' attribute");
         }
     }
 
@@ -759,7 +761,7 @@
             final Bitmap bitmap = BitmapFactory.decodeResource(r, srcResId);
             if (bitmap == null) {
                 throw new XmlPullParserException(a.getPositionDescription() +
-                        ": <bitmap> requires a valid src attribute");
+                        ": <bitmap> requires a valid 'src' attribute");
             }
 
             state.mBitmap = bitmap;
@@ -832,7 +834,7 @@
 
         // Apply theme to contained color state list.
         if (state.mTint != null && state.mTint.canApplyTheme()) {
-            state.mTint.applyTheme(t);
+            state.mTint = state.mTint.obtainForTheme(t);
         }
 
         // Update local properties.
@@ -880,7 +882,7 @@
 
     @Override
     public final ConstantState getConstantState() {
-        mBitmapState.mChangingConfigurations = getChangingConfigurations();
+        mBitmapState.mChangingConfigurations |= getChangingConfigurations();
         return mBitmapState;
     }
 
@@ -948,7 +950,8 @@
 
         @Override
         public int getChangingConfigurations() {
-            return mChangingConfigurations;
+            return mChangingConfigurations
+                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index f75ab36..8e91621 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -276,7 +276,7 @@
         }
 
         if (state.mTint != null && state.mTint.canApplyTheme()) {
-            state.mTint.applyTheme(t);
+            state.mTint = state.mTint.obtainForTheme(t);
         }
 
         updateLocalState(t.getResources());
@@ -327,7 +327,8 @@
 
         @Override
         public int getChangingConfigurations() {
-            return mChangingConfigurations;
+            return mChangingConfigurations
+                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 56876e94..e8b8c77 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -816,9 +816,12 @@
      * returned.  You can use the method {@link #resolveOpacity} to perform a
      * standard reduction of two opacities to the appropriate single output.
      *
-     * <p>Note that the returned value does <em>not</em> take into account a
+     * <p>Note that the returned value does not necessarily take into account a
      * custom alpha or color filter that has been applied by the client through
-     * the {@link #setAlpha} or {@link #setColorFilter} methods.
+     * the {@link #setAlpha} or {@link #setColorFilter} methods. Some subclasses,
+     * such as {@link BitmapDrawable}, {@link ColorDrawable}, and {@link GradientDrawable},
+     * do account for the value of {@link #setAlpha}, but the general behavior is dependent
+     * upon the implementation of the subclass.
      *
      * @return int The opacity class of the Drawable.
      *
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index ddcb48b..b03fe3a 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -87,8 +87,7 @@
     @Override
     public int getChangingConfigurations() {
         return super.getChangingConfigurations()
-                | mDrawableContainerState.mChangingConfigurations
-                | mDrawableContainerState.mChildrenChangingConfigurations;
+                | mDrawableContainerState.getChangingConfigurations();
     }
 
     private boolean needsMirroring() {
@@ -865,6 +864,9 @@
                 for (int i = 0; i < N; i++) {
                     if (drawables[i] != null && drawables[i].canApplyTheme()) {
                         drawables[i].applyTheme(theme);
+
+                        // Update cached mask of child changing configurations.
+                        mChildrenChangingConfigurations |= drawables[i].getChangingConfigurations();
                     }
                 }
             }
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index 1d6c60f..0da4275 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -180,8 +180,7 @@
     @Override
     public int getChangingConfigurations() {
         return super.getChangingConfigurations()
-                | (mState != null ? mState.mChangingConfigurations : 0)
-                | mDrawable.getChangingConfigurations();
+                | (mState != null ? mState.getChangingConfigurations() : 0);
     }
 
     @Override
@@ -433,7 +432,7 @@
 
         @Override
         public int getChangingConfigurations() {
-            return mChangingConfigurations;
+            return mChangingConfigurations | mDrawableState.getChangingConfigurations();
         }
 
         public boolean canConstantState() {
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index eff152c..4c2817c 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -491,19 +491,21 @@
     }
 
     /**
-     * <p>Sets the colors used to draw the gradient. Each color is specified as an
-     * ARGB integer and the array must contain at least 2 colors.</p>
-     * <p><strong>Note</strong>: changing colors will affect all instances
-     * of a drawable loaded from a resource. It is recommended to invoke
-     * {@link #mutate()} before changing the colors.</p>
+     * Sets the colors used to draw the gradient.
+     * <p>
+     * Each color is specified as an ARGB integer and the array must contain at
+     * least 2 colors.
+     * <p>
+     * <strong>Note</strong>: changing colors will affect all instances of a
+     * drawable loaded from a resource. It is recommended to invoke
+     * {@link #mutate()} before changing the colors.
      *
-     * @param colors 2 or more ARGB colors
-     *
+     * @param colors an array containing 2 or more ARGB colors
      * @see #mutate()
      * @see #setColor(int)
      */
     public void setColors(@ColorInt int[] colors) {
-        mGradientState.setColors(colors);
+        mGradientState.setGradientColors(colors);
         mGradientIsDirty = true;
         invalidateSelf();
     }
@@ -568,7 +570,7 @@
             mFillPaint.setAlpha(currFillAlpha);
             mFillPaint.setDither(st.mDither);
             mFillPaint.setColorFilter(colorFilter);
-            if (colorFilter != null && st.mColorStateList == null) {
+            if (colorFilter != null && st.mSolidColors == null) {
                 mFillPaint.setColor(mAlpha << 24);
             }
             if (haveStroke) {
@@ -715,7 +717,7 @@
      * @see #setColors(int[])
      */
     public void setColor(@ColorInt int argb) {
-        mGradientState.setColorStateList(ColorStateList.valueOf(argb));
+        mGradientState.setSolidColors(ColorStateList.valueOf(argb));
         mFillPaint.setColor(argb);
         invalidateSelf();
     }
@@ -734,7 +736,7 @@
      * @see #mutate()
      */
     public void setColor(ColorStateList colorStateList) {
-        mGradientState.setColorStateList(colorStateList);
+        mGradientState.setSolidColors(colorStateList);
         final int color;
         if (colorStateList == null) {
             color = Color.TRANSPARENT;
@@ -751,9 +753,9 @@
         boolean invalidateSelf = false;
 
         final GradientState s = mGradientState;
-        final ColorStateList stateList = s.mColorStateList;
-        if (stateList != null) {
-            final int newColor = stateList.getColorForState(stateSet, 0);
+        final ColorStateList solidColors = s.mSolidColors;
+        if (solidColors != null) {
+            final int newColor = solidColors.getColorForState(stateSet, 0);
             final int oldColor = mFillPaint.getColor();
             if (oldColor != newColor) {
                 mFillPaint.setColor(newColor);
@@ -763,12 +765,12 @@
 
         final Paint strokePaint = mStrokePaint;
         if (strokePaint != null) {
-            final ColorStateList strokeStateList = s.mStrokeColorStateList;
-            if (strokeStateList != null) {
-                final int newStrokeColor = strokeStateList.getColorForState(stateSet, 0);
-                final int oldStrokeColor = strokePaint.getColor();
-                if (oldStrokeColor != newStrokeColor) {
-                    strokePaint.setColor(newStrokeColor);
+            final ColorStateList strokeColors = s.mStrokeColors;
+            if (strokeColors != null) {
+                final int newColor = strokeColors.getColorForState(stateSet, 0);
+                final int oldColor = strokePaint.getColor();
+                if (oldColor != newColor) {
+                    strokePaint.setColor(newColor);
                     invalidateSelf = true;
                 }
             }
@@ -791,14 +793,14 @@
     public boolean isStateful() {
         final GradientState s = mGradientState;
         return super.isStateful()
-                || (s.mColorStateList != null && s.mColorStateList.isStateful())
-                || (s.mStrokeColorStateList != null && s.mStrokeColorStateList.isStateful())
+                || (s.mSolidColors != null && s.mSolidColors.isStateful())
+                || (s.mStrokeColors != null && s.mStrokeColors.isStateful())
                 || (s.mTint != null && s.mTint.isStateful());
     }
 
     @Override
     public int getChangingConfigurations() {
-        return super.getChangingConfigurations() | mGradientState.mChangingConfigurations;
+        return super.getChangingConfigurations() | mGradientState.getChangingConfigurations();
     }
 
     @Override
@@ -899,10 +901,10 @@
             mRect.set(bounds.left + inset, bounds.top + inset,
                       bounds.right - inset, bounds.bottom - inset);
 
-            final int[] colors = st.mColors;
-            if (colors != null) {
-                RectF r = mRect;
-                float x0, x1, y0, y1;
+            final int[] gradientColors = st.mGradientColors;
+            if (gradientColors != null) {
+                final RectF r = mRect;
+                final float x0, x1, y0, y1;
 
                 if (st.mGradient == LINEAR_GRADIENT) {
                     final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f;
@@ -942,7 +944,7 @@
                     }
 
                     mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1,
-                            colors, st.mPositions, Shader.TileMode.CLAMP));
+                            gradientColors, st.mPositions, Shader.TileMode.CLAMP));
                 } else if (st.mGradient == RADIAL_GRADIENT) {
                     x0 = r.left + (r.right - r.left) * st.mCenterX;
                     y0 = r.top + (r.bottom - r.top) * st.mCenterY;
@@ -971,22 +973,22 @@
                     }
 
                     mFillPaint.setShader(new RadialGradient(
-                            x0, y0, radius, colors, null, Shader.TileMode.CLAMP));
+                            x0, y0, radius, gradientColors, null, Shader.TileMode.CLAMP));
                 } else if (st.mGradient == SWEEP_GRADIENT) {
                     x0 = r.left + (r.right - r.left) * st.mCenterX;
                     y0 = r.top + (r.bottom - r.top) * st.mCenterY;
 
-                    int[] tempColors = colors;
+                    int[] tempColors = gradientColors;
                     float[] tempPositions = null;
 
                     if (st.mUseLevel) {
                         tempColors = st.mTempColors;
-                        final int length = colors.length;
+                        final int length = gradientColors.length;
                         if (tempColors == null || tempColors.length != length + 1) {
                             tempColors = st.mTempColors = new int[length + 1];
                         }
-                        System.arraycopy(colors, 0, tempColors, 0, length);
-                        tempColors[length] = colors[length - 1];
+                        System.arraycopy(gradientColors, 0, tempColors, 0, length);
+                        tempColors[length] = gradientColors[length - 1];
 
                         tempPositions = st.mTempPositions;
                         final float fraction = 1.0f / (length - 1);
@@ -1006,7 +1008,7 @@
 
                 // If we don't have a solid color, the alpha channel must be
                 // maxed out so that alpha modulation works correctly.
-                if (st.mColorStateList == null) {
+                if (st.mSolidColors == null) {
                     mFillPaint.setColor(Color.BLACK);
                 }
             }
@@ -1044,15 +1046,15 @@
         }
 
         if (state.mTint != null && state.mTint.canApplyTheme()) {
-            state.mTint.applyTheme(t);
+            state.mTint = state.mTint.obtainForTheme(t);
         }
 
-        if (state.mColorStateList != null && state.mColorStateList.canApplyTheme()) {
-            state.mColorStateList.applyTheme(t);
+        if (state.mSolidColors != null && state.mSolidColors.canApplyTheme()) {
+            state.mSolidColors = state.mSolidColors.obtainForTheme(t);
         }
 
-        if (state.mStrokeColorStateList != null && state.mStrokeColorStateList.canApplyTheme()) {
-            state.mStrokeColorStateList.applyTheme(t);
+        if (state.mStrokeColors != null && state.mStrokeColors.canApplyTheme()) {
+            state.mStrokeColors = state.mStrokeColors.obtainForTheme(t);
         }
 
         applyThemeChildElements(t);
@@ -1288,7 +1290,7 @@
         ColorStateList colorStateList = a.getColorStateList(
                 R.styleable.GradientDrawableStroke_color);
         if (colorStateList == null) {
-            colorStateList = st.mStrokeColorStateList;
+            colorStateList = st.mStrokeColors;
         }
 
         if (dashWidth != 0.0f) {
@@ -1346,10 +1348,10 @@
                 R.styleable.GradientDrawableGradient_endColor, 0);
 
         if (hasCenterColor) {
-            st.mColors = new int[3];
-            st.mColors[0] = startColor;
-            st.mColors[1] = centerColor;
-            st.mColors[2] = endColor;
+            st.mGradientColors = new int[3];
+            st.mGradientColors[0] = startColor;
+            st.mGradientColors[1] = centerColor;
+            st.mGradientColors[2] = endColor;
 
             st.mPositions = new float[3];
             st.mPositions[0] = 0.0f;
@@ -1357,9 +1359,9 @@
             st.mPositions[1] = st.mCenterX != 0.5f ? st.mCenterX : st.mCenterY;
             st.mPositions[2] = 1f;
         } else {
-            st.mColors = new int[2];
-            st.mColors[0] = startColor;
-            st.mColors[1] = endColor;
+            st.mGradientColors = new int[2];
+            st.mGradientColors[0] = startColor;
+            st.mGradientColors[1] = endColor;
         }
 
         if (st.mGradient == LINEAR_GRADIENT) {
@@ -1552,9 +1554,9 @@
         public int mGradient = LINEAR_GRADIENT;
         public int mAngle = 0;
         public Orientation mOrientation;
-        public ColorStateList mColorStateList;
-        public ColorStateList mStrokeColorStateList;
-        public int[] mColors;
+        public ColorStateList mSolidColors;
+        public ColorStateList mStrokeColors;
+        public int[] mGradientColors;
         public int[] mTempColors; // no need to copy
         public float[] mTempPositions; // no need to copy
         public float[] mPositions;
@@ -1593,9 +1595,9 @@
         int[] mAttrCorners;
         int[] mAttrPadding;
 
-        public GradientState(Orientation orientation, int[] colors) {
+        public GradientState(Orientation orientation, int[] gradientColors) {
             mOrientation = orientation;
-            setColors(colors);
+            setGradientColors(gradientColors);
         }
 
         public GradientState(GradientState state) {
@@ -1604,14 +1606,14 @@
             mGradient = state.mGradient;
             mAngle = state.mAngle;
             mOrientation = state.mOrientation;
-            mColorStateList = state.mColorStateList;
-            if (state.mColors != null) {
-                mColors = state.mColors.clone();
+            mSolidColors = state.mSolidColors;
+            if (state.mGradientColors != null) {
+                mGradientColors = state.mGradientColors.clone();
             }
             if (state.mPositions != null) {
                 mPositions = state.mPositions.clone();
             }
-            mStrokeColorStateList = state.mStrokeColorStateList;
+            mStrokeColors = state.mStrokeColors;
             mStrokeWidth = state.mStrokeWidth;
             mStrokeDashWidth = state.mStrokeDashWidth;
             mStrokeDashGap = state.mStrokeDashGap;
@@ -1655,8 +1657,8 @@
                     || mAttrSolid != null || mAttrStroke != null
                     || mAttrCorners != null || mAttrPadding != null
                     || (mTint != null && mTint.canApplyTheme())
-                    || (mStrokeColorStateList != null && mStrokeColorStateList.canApplyTheme())
-                    || (mColorStateList != null && mColorStateList.canApplyTheme())
+                    || (mStrokeColors != null && mStrokeColors.canApplyTheme())
+                    || (mSolidColors != null && mSolidColors.canApplyTheme())
                     || super.canApplyTheme();
         }
 
@@ -1672,7 +1674,10 @@
 
         @Override
         public int getChangingConfigurations() {
-            return mChangingConfigurations;
+            return mChangingConfigurations
+                    | (mStrokeColors != null ? mStrokeColors.getChangingConfigurations() : 0)
+                    | (mSolidColors != null ? mSolidColors.getChangingConfigurations() : 0)
+                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
 
         public void setShape(int shape) {
@@ -1689,15 +1694,15 @@
             mCenterY = y;
         }
 
-        public void setColors(int[] colors) {
-            mColors = colors;
-            mColorStateList = null;
+        public void setGradientColors(int[] colors) {
+            mGradientColors = colors;
+            mSolidColors = null;
             computeOpacity();
         }
 
-        public void setColorStateList(ColorStateList colorStateList) {
-            mColors = null;
-            mColorStateList = colorStateList;
+        public void setSolidColors(ColorStateList colors) {
+            mGradientColors = null;
+            mSolidColors = colors;
             computeOpacity();
         }
 
@@ -1705,16 +1710,16 @@
             mOpaqueOverBounds = false;
             mOpaqueOverShape = false;
 
-            if (mColors != null) {
-                for (int i = 0; i < mColors.length; i++) {
-                    if (!isOpaque(mColors[i])) {
+            if (mGradientColors != null) {
+                for (int i = 0; i < mGradientColors.length; i++) {
+                    if (!isOpaque(mGradientColors[i])) {
                         return;
                     }
                 }
             }
 
             // An unfilled shape is not opaque over bounds or shape
-            if (mColors == null && mColorStateList == null) {
+            if (mGradientColors == null && mSolidColors == null) {
                 return;
             }
 
@@ -1726,10 +1731,9 @@
                     && mRadiusArray == null;
         }
 
-        public void setStroke(
-                int width, ColorStateList colorStateList, float dashWidth, float dashGap) {
+        public void setStroke(int width, ColorStateList colors, float dashWidth, float dashGap) {
             mStrokeWidth = width;
-            mStrokeColorStateList = colorStateList;
+            mStrokeColors = colors;
             mStrokeDashWidth = dashWidth;
             mStrokeDashGap = dashGap;
             computeOpacity();
@@ -1781,11 +1785,11 @@
     private void updateLocalState(Resources res) {
         final GradientState state = mGradientState;
 
-        if (state.mColorStateList != null) {
+        if (state.mSolidColors != null) {
             final int[] currentState = getState();
-            final int stateColor = state.mColorStateList.getColorForState(currentState, 0);
+            final int stateColor = state.mSolidColors.getColorForState(currentState, 0);
             mFillPaint.setColor(stateColor);
-        } else if (state.mColors == null) {
+        } else if (state.mGradientColors == null) {
             // If we don't have a solid color and we don't have a gradient,
             // the app is stroking the shape, set the color to the default
             // value of state.mSolidColor
@@ -1802,9 +1806,9 @@
             mStrokePaint.setStyle(Paint.Style.STROKE);
             mStrokePaint.setStrokeWidth(state.mStrokeWidth);
 
-            if (state.mStrokeColorStateList != null) {
+            if (state.mStrokeColors != null) {
                 final int[] currentState = getState();
-                final int strokeStateColor = state.mStrokeColorStateList.getColorForState(
+                final int strokeStateColor = state.mStrokeColors.getColorForState(
                         currentState, 0);
                 mStrokePaint.setColor(strokeStateColor);
             }
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 97f7105..e1ebdbb 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -242,26 +242,12 @@
     }
 
     @Override
-    public ConstantState getConstantState() {
-        if (mState.canConstantState()) {
-            mState.mChangingConfigurations = getChangingConfigurations();
-            return mState;
-        }
-        return null;
-    }
-
-    @Override
     DrawableWrapperState mutateConstantState() {
         mState = new InsetState(mState);
         return mState;
     }
 
     static final class InsetState extends DrawableWrapper.DrawableWrapperState {
-        int[] mThemeAttrs;
-        int mChangingConfigurations;
-
-        ConstantState mDrawableState;
-
         int mInsetLeft = 0;
         int mInsetTop = 0;
         int mInsetRight = 0;
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 30fbe16..a2f71e5 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -296,6 +296,9 @@
             final Drawable d = layer.mDrawable;
             if (d.canApplyTheme()) {
                 d.applyTheme(t);
+
+                // Update cached mask of child changing configurations.
+                state.mChildrenChangingConfigurations |= d.getChangingConfigurations();
             }
         }
 
@@ -882,9 +885,7 @@
 
     @Override
     public int getChangingConfigurations() {
-        return super.getChangingConfigurations()
-                | mLayerState.mChangingConfigurations
-                | mLayerState.mChildrenChangingConfigurations;
+        return super.getChangingConfigurations() | mLayerState.getChangingConfigurations();
     }
 
     @Override
@@ -1493,7 +1494,8 @@
 
         @Override
         public int getChangingConfigurations() {
-            return mChangingConfigurations;
+            return mChangingConfigurations
+                    | mChildrenChangingConfigurations;
         }
 
         public final int getOpacity() {
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 487162e..9bf33cf 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -266,7 +266,7 @@
 
     @Override
     public int getChangingConfigurations() {
-        return super.getChangingConfigurations() | mNinePatchState.mChangingConfigurations;
+        return super.getChangingConfigurations() | mNinePatchState.getChangingConfigurations();
     }
 
     @Override
@@ -498,7 +498,7 @@
         }
 
         if (state.mTint != null && state.mTint.canApplyTheme()) {
-            state.mTint.applyTheme(t);
+            state.mTint = state.mTint.obtainForTheme(t);
         }
 
         updateLocalState(t.getResources());
@@ -680,7 +680,8 @@
 
         @Override
         public int getChangingConfigurations() {
-            return mChangingConfigurations;
+            return mChangingConfigurations
+                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 23f93fd..6731a17 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -479,7 +479,7 @@
         }
 
         if (state.mColor != null && state.mColor.canApplyTheme()) {
-            state.mColor.applyTheme(t);
+            state.mColor = state.mColor.obtainForTheme(t);
         }
 
         updateLocalState();
@@ -955,6 +955,12 @@
         public Drawable newDrawable(Resources res) {
             return new RippleDrawable(this, res);
         }
+
+        @Override
+        public int getChangingConfigurations() {
+            return super.getChangingConfigurations()
+                    | (mColor != null ? mColor.getChangingConfigurations() : 0);
+        }
     }
 
     private RippleDrawable(RippleState state, Resources res) {
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 15e16f1..036a078 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -89,9 +89,6 @@
 
         final RotateState state = mState;
 
-        // Account for any configuration changes.
-        state.mChangingConfigurations |= a.getChangingConfigurations();
-
         // Extract the theme attributes, if any.
         state.mThemeAttrs = a.extractThemeAttrs();
 
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index fc88c15..334b3bd 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -53,9 +53,9 @@
  * For more information about how to use ShapeDrawable, read the <a
  * href="{@docRoot}guide/topics/graphics/2d-graphics.html#shape-drawable">
  * Canvas and Drawables</a> document. For more information about defining a
- * ShapeDrawable in XML, read the <a href="{@docRoot}
- * guide/topics/resources/drawable-resource.html#Shape">Drawable Resources</a>
- * document.
+ * ShapeDrawable in XML, read the
+ * <a href="{@docRoot}guide/topics/resources/drawable-resource.html#Shape">
+ * Drawable Resources</a> document.
  * </p>
  * </div>
  *
@@ -261,8 +261,7 @@
 
     @Override
     public int getChangingConfigurations() {
-        return super.getChangingConfigurations()
-                | mShapeState.mChangingConfigurations;
+        return super.getChangingConfigurations() | mShapeState.getChangingConfigurations();
     }
 
     /**
@@ -427,7 +426,7 @@
 
         // Apply theme to contained color state list.
         if (state.mTint != null && state.mTint.canApplyTheme()) {
-            state.mTint.applyTheme(t);
+            state.mTint = state.mTint.obtainForTheme(t);
         }
 
         // Update local properties.
@@ -578,7 +577,8 @@
 
         @Override
         public int getChangingConfigurations() {
-            return mChangingConfigurations;
+            return mChangingConfigurations
+                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 39a33ce..f4df14e 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -36,6 +36,7 @@
 import android.util.AttributeSet;
 import android.util.LayoutDirection;
 import android.util.Log;
+import android.util.MathUtils;
 import android.util.PathParser;
 import android.util.Xml;
 
@@ -56,21 +57,21 @@
  * <p/>
  * <dt><code>&lt;vector></code></dt>
  * <dl>
- * <dd>Used to defined a vector drawable
+ * <dd>Used to define a vector drawable
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of this vector drawable.</dd>
  * <dt><code>android:width</code></dt>
- * <dd>Used to defined the intrinsic width of the drawable.
+ * <dd>Used to define the intrinsic width of the drawable.
  * This support all the dimension units, normally specified with dp.</dd>
  * <dt><code>android:height</code></dt>
- * <dd>Used to defined the intrinsic height the drawable.
+ * <dd>Used to define the intrinsic height the drawable.
  * This support all the dimension units, normally specified with dp.</dd>
  * <dt><code>android:viewportWidth</code></dt>
- * <dd>Used to defined the width of the viewport space. Viewport is basically
+ * <dd>Used to define the width of the viewport space. Viewport is basically
  * the virtual canvas where the paths are drawn on.</dd>
  * <dt><code>android:viewportHeight</code></dt>
- * <dd>Used to defined the height of the viewport space. Viewport is basically
+ * <dd>Used to define the height of the viewport space. Viewport is basically
  * the virtual canvas where the paths are drawn on.</dd>
  * <dt><code>android:tint</code></dt>
  * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
@@ -120,7 +121,7 @@
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of the path.</dd>
  * <dt><code>android:pathData</code></dt>
- * <dd>Defines path string. This is using exactly same format as "d" attribute
+ * <dd>Defines path data using exactly same format as "d" attribute
  * in the SVG's path data. This is defined in the viewport space.</dd>
  * <dt><code>android:fillColor</code></dt>
  * <dd>Defines the color to fill the path (none if not present).</dd>
@@ -156,7 +157,7 @@
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of the clip path.</dd>
  * <dt><code>android:pathData</code></dt>
- * <dd>Defines clip path string. This is using exactly same format as "d" attribute
+ * <dd>Defines clip path using the same format as "d" attribute
  * in the SVG's path data.</dd>
  * </dl></dd>
  * </dl>
@@ -249,8 +250,8 @@
     @Override
     public void draw(Canvas canvas) {
         final Rect bounds = getBounds();
-        if (bounds.width() == 0 || bounds.height() == 0) {
-            // too small to draw
+        if (bounds.width() <= 0 || bounds.height() <= 0) {
+            // Nothing to draw
             return;
         }
 
@@ -389,7 +390,7 @@
 
         // Apply theme to contained color state list.
         if (state.mTint != null && state.mTint.canApplyTheme()) {
-            state.mTint.applyTheme(t);
+            state.mTint = state.mTint.obtainForTheme(t);
         }
 
         final VPathRenderer path = state.mVPathRenderer;
@@ -625,7 +626,7 @@
 
     @Override
     public int getChangingConfigurations() {
-        return super.getChangingConfigurations() | mVectorState.mChangingConfigurations;
+        return super.getChangingConfigurations() | mVectorState.getChangingConfigurations();
     }
 
     void setAllowCaching(boolean allowCaching) {
@@ -784,7 +785,8 @@
 
         @Override
         public int getChangingConfigurations() {
-            return mChangingConfigurations;
+            return mChangingConfigurations
+                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
     }
 
@@ -955,10 +957,16 @@
             final float scaleX = w / mViewportWidth;
             final float scaleY = h / mViewportHeight;
             final float minScale = Math.min(scaleX, scaleY);
+            final Matrix groupStackedMatrix = vGroup.mStackedMatrix;
 
-            mFinalPathMatrix.set(vGroup.mStackedMatrix);
+            mFinalPathMatrix.set(groupStackedMatrix);
             mFinalPathMatrix.postScale(scaleX, scaleY);
 
+            final float matrixScale = getMatrixScale(groupStackedMatrix);
+            if (matrixScale == 0) {
+                // When either x or y is scaled to 0, we don't need to draw anything.
+                return;
+            }
             vPath.toPath(mPath);
             final Path path = mPath;
 
@@ -966,7 +974,7 @@
 
             if (vPath.isClipPath()) {
                 mRenderPath.addPath(path, mFinalPathMatrix);
-                canvas.clipPath(mRenderPath, Region.Op.REPLACE);
+                canvas.clipPath(mRenderPath);
             } else {
                 VFullPath fullPath = (VFullPath) vPath;
                 if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
@@ -1024,11 +1032,41 @@
                     strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
                     strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
                     strokePaint.setColorFilter(filter);
-                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * minScale);
+                    final float finalStrokeScale = minScale * matrixScale;
+                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
                     canvas.drawPath(mRenderPath, strokePaint);
                 }
             }
         }
+
+        private float getMatrixScale(Matrix groupStackedMatrix) {
+            // Given unit vectors A = (0, 1) and B = (1, 0).
+            // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
+            // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
+            // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
+            // If  max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
+            //
+            // For non-skew case, which is most of the cases, matrix scale is computing exactly the
+            // scale on x and y axis, and take the minimal of these two.
+            // For skew case, an unit square will mapped to a parallelogram. And this function will
+            // return the minimal height of the 2 bases.
+            float[] unitVectors = new float[] {0, 1, 1, 0};
+            groupStackedMatrix.mapVectors(unitVectors);
+            float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]);
+            float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]);
+            float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1],
+                    unitVectors[2], unitVectors[3]);
+            float maxScale = MathUtils.max(scaleX, scaleY);
+
+            float matrixScale = 0;
+            if (maxScale > 0) {
+                matrixScale = MathUtils.abs(crossProduct) / maxScale;
+            }
+            if (DBG_VECTOR_DRAWABLE) {
+                Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
+            }
+            return matrixScale;
+        }
     }
 
     private static class VGroup {
diff --git a/include/android_runtime/android_view_Surface.h b/include/android_runtime/android_view_Surface.h
index a6836a8..ed83314 100644
--- a/include/android_runtime/android_view_Surface.h
+++ b/include/android_runtime/android_view_Surface.h
@@ -43,6 +43,7 @@
     NV21              = 0x11,
     YUY2              = 0x14,
     RAW_SENSOR        = 0x20,
+    PRIVATE           = 0x22,
     YUV_420_888       = 0x23,
     RAW10             = 0x25,
     JPEG              = 0x100,
diff --git a/include/androidfw/BackupHelpers.h b/include/androidfw/BackupHelpers.h
index 0841af6..fc1ad47 100644
--- a/include/androidfw/BackupHelpers.h
+++ b/include/androidfw/BackupHelpers.h
@@ -17,6 +17,8 @@
 #ifndef _UTILS_BACKUP_HELPERS_H
 #define _UTILS_BACKUP_HELPERS_H
 
+#include <sys/stat.h>
+
 #include <utils/Errors.h>
 #include <utils/String8.h>
 #include <utils/KeyedVector.h>
@@ -135,7 +137,8 @@
         char const* const* files, char const* const *keys, int fileCount);
 
 int write_tarfile(const String8& packageName, const String8& domain,
-        const String8& rootPath, const String8& filePath, BackupDataWriter* outputStream);
+        const String8& rootPath, const String8& filePath, off_t* outSize,
+        BackupDataWriter* outputStream);
 
 class RestoreHelperBase
 {
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 65160d5..a5776a4 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1333,7 +1333,11 @@
         FLAG_COMPLEX = 0x0001,
         // If set, this resource has been declared public, so libraries
         // are allowed to reference it.
-        FLAG_PUBLIC = 0x0002
+        FLAG_PUBLIC = 0x0002,
+        // If set, this is a weak resource and may be overriden by strong
+        // resources of the same name/type. This is only useful during
+        // linking with other resource tables.
+        FLAG_WEAK = 0x0004
     };
     uint16_t flags;
     
diff --git a/keystore/java/android/security/AndroidKeyPairGenerator.java b/keystore/java/android/security/AndroidKeyPairGenerator.java
index 9d9a173..5fae831 100644
--- a/keystore/java/android/security/AndroidKeyPairGenerator.java
+++ b/keystore/java/android/security/AndroidKeyPairGenerator.java
@@ -136,6 +136,8 @@
             throw new IllegalStateException("could not generate key in keystore");
         }
 
+        Credentials.deleteSecretKeyTypeForAlias(mKeyStore, alias);
+
         final PrivateKey privKey;
         final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
         try {
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index acbae8f..ed690de 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -19,6 +19,9 @@
 import com.android.org.conscrypt.OpenSSLEngine;
 import com.android.org.conscrypt.OpenSSLKeyHolder;
 
+import android.security.keymaster.KeyCharacteristics;
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterDefs;
 import android.util.Log;
 
 import java.io.ByteArrayInputStream;
@@ -31,6 +34,7 @@
 import java.security.KeyStore.PrivateKeyEntry;
 import java.security.KeyStore.ProtectionParameter;
 import java.security.KeyStore;
+import java.security.KeyStore.SecretKeyEntry;
 import java.security.KeyStoreException;
 import java.security.KeyStoreSpi;
 import java.security.NoSuchAlgorithmException;
@@ -50,6 +54,8 @@
 import java.util.Iterator;
 import java.util.Set;
 
+import javax.crypto.SecretKey;
+
 /**
  * A java.security.KeyStore interface for the Android KeyStore. An instance of
  * it can be created via the {@link java.security.KeyStore#getInstance(String)
@@ -77,18 +83,72 @@
     @Override
     public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException,
             UnrecoverableKeyException {
-        if (!isKeyEntry(alias)) {
-            return null;
+        if (isPrivateKeyEntry(alias)) {
+            final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
+            try {
+                return engine.getPrivateKeyById(Credentials.USER_PRIVATE_KEY + alias);
+            } catch (InvalidKeyException e) {
+                UnrecoverableKeyException t = new UnrecoverableKeyException("Can't get key");
+                t.initCause(e);
+                throw t;
+            }
+        } else if (isSecretKeyEntry(alias)) {
+            KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
+            String keyAliasInKeystore = Credentials.USER_SECRET_KEY + alias;
+            int errorCode = mKeyStore.getKeyCharacteristics(
+                    keyAliasInKeystore, null, null, keyCharacteristics);
+            if ((errorCode != KeymasterDefs.KM_ERROR_OK)
+                    && (errorCode != android.security.KeyStore.NO_ERROR)) {
+                throw new UnrecoverableKeyException("Failed to load information about key."
+                        + " Error code: " + errorCode);
+            }
+
+            int keymasterAlgorithm =
+                    keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_ALGORITHM, -1);
+            if (keymasterAlgorithm == -1) {
+                keymasterAlgorithm =
+                        keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_ALGORITHM, -1);
+            }
+            if (keymasterAlgorithm == -1) {
+                throw new UnrecoverableKeyException("Key algorithm unknown");
+            }
+            @KeyStoreKeyConstraints.AlgorithmEnum int keyAlgorithm;
+            try {
+                keyAlgorithm = KeyStoreKeyConstraints.Algorithm.fromKeymaster(keymasterAlgorithm);
+            } catch (IllegalArgumentException e) {
+                throw (UnrecoverableKeyException)
+                        new UnrecoverableKeyException("Unsupported key algorithm").initCause(e);
+            }
+
+            int keymasterDigest =
+                    keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_DIGEST, -1);
+            if (keymasterDigest == -1) {
+                keymasterDigest =
+                        keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_DIGEST, -1);
+            }
+            @KeyStoreKeyConstraints.DigestEnum Integer digest = null;
+            if (keymasterDigest != -1) {
+                try {
+                    digest = KeyStoreKeyConstraints.Digest.fromKeymaster(keymasterDigest);
+                } catch (IllegalArgumentException e) {
+                    throw (UnrecoverableKeyException)
+                            new UnrecoverableKeyException("Unsupported digest").initCause(e);
+                }
+            }
+
+            String keyAlgorithmString;
+            try {
+                keyAlgorithmString = KeyStoreKeyConstraints.Algorithm.toJCASecretKeyAlgorithm(
+                    keyAlgorithm, digest);
+            } catch (IllegalArgumentException e) {
+                throw (UnrecoverableKeyException)
+                        new UnrecoverableKeyException("Unsupported secret key type").initCause(e);
+            }
+
+            return new KeyStoreSecretKey(keyAliasInKeystore, keyAlgorithmString);
         }
 
-        final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
-        try {
-            return engine.getPrivateKeyById(Credentials.USER_PRIVATE_KEY + alias);
-        } catch (InvalidKeyException e) {
-            UnrecoverableKeyException t = new UnrecoverableKeyException("Can't get key");
-            t.initCause(e);
-            throw t;
-        }
+        return null;
     }
 
     @Override
@@ -186,6 +246,11 @@
             return d;
         }
 
+        d = getModificationDate(Credentials.USER_SECRET_KEY + alias);
+        if (d != null) {
+            return d;
+        }
+
         d = getModificationDate(Credentials.USER_CERTIFICATE + alias);
         if (d != null) {
             return d;
@@ -203,8 +268,10 @@
 
         if (key instanceof PrivateKey) {
             setPrivateKeyEntry(alias, (PrivateKey) key, chain, null);
+        } else if (key instanceof SecretKey) {
+            setSecretKeyEntry(alias, (SecretKey) key, null);
         } else {
-            throw new KeyStoreException("Only PrivateKeys are supported");
+            throw new KeyStoreException("Only PrivateKey and SecretKey are supported");
         }
     }
 
@@ -319,6 +386,7 @@
             Credentials.deleteAllTypesForAlias(mKeyStore, alias);
         } else {
             Credentials.deleteCertificateTypesForAlias(mKeyStore, alias);
+            Credentials.deleteSecretKeyTypeForAlias(mKeyStore, alias);
         }
 
         final int flags = (params == null) ? 0 : params.getFlags();
@@ -340,6 +408,171 @@
         }
     }
 
+    private void setSecretKeyEntry(String entryAlias, SecretKey key, KeyStoreParameter params)
+            throws KeyStoreException {
+        if (key instanceof KeyStoreSecretKey) {
+            // KeyStore-backed secret key. It cannot be duplicated into another entry and cannot
+            // overwrite its own entry.
+            String keyAliasInKeystore = ((KeyStoreSecretKey) key).getAlias();
+            if (keyAliasInKeystore == null) {
+                throw new KeyStoreException("KeyStore-backed secret key does not have an alias");
+            }
+            if (!keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)) {
+                throw new KeyStoreException("KeyStore-backed secret key has invalid alias: "
+                        + keyAliasInKeystore);
+            }
+            String keyEntryAlias =
+                    keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length());
+            if (!entryAlias.equals(keyEntryAlias)) {
+                throw new KeyStoreException("Can only replace KeyStore-backed keys with same"
+                        + " alias: " + entryAlias + " != " + keyEntryAlias);
+            }
+            // This is the entry where this key is already stored. No need to do anything.
+            if (params != null) {
+                throw new KeyStoreException("Modifying KeyStore-backed key using protection"
+                        + " parameters not supported");
+            }
+            return;
+        }
+
+        if (params == null) {
+            throw new KeyStoreException(
+                    "Protection parameters must be specified when importing a symmetric key");
+        }
+
+        // Not a KeyStore-backed secret key -- import its key material into keystore.
+        String keyExportFormat = key.getFormat();
+        if (keyExportFormat == null) {
+            throw new KeyStoreException(
+                    "Only secret keys that export their key material are supported");
+        } else if (!"RAW".equals(keyExportFormat)) {
+            throw new KeyStoreException(
+                    "Unsupported secret key material export format: " + keyExportFormat);
+        }
+        byte[] keyMaterial = key.getEncoded();
+        if (keyMaterial == null) {
+            throw new KeyStoreException("Key did not export its key material despite supporting"
+                    + " RAW format export");
+        }
+
+        String keyAlgorithmString = key.getAlgorithm();
+        @KeyStoreKeyConstraints.AlgorithmEnum int keyAlgorithm;
+        @KeyStoreKeyConstraints.DigestEnum Integer digest;
+        try {
+            keyAlgorithm =
+                    KeyStoreKeyConstraints.Algorithm.fromJCASecretKeyAlgorithm(keyAlgorithmString);
+            digest = KeyStoreKeyConstraints.Digest.fromJCASecretKeyAlgorithm(keyAlgorithmString);
+        } catch (IllegalArgumentException e) {
+            throw new KeyStoreException("Unsupported secret key algorithm: " + keyAlgorithmString);
+        }
+
+        KeymasterArguments args = new KeymasterArguments();
+        args.addInt(KeymasterDefs.KM_TAG_ALGORITHM,
+                KeyStoreKeyConstraints.Algorithm.toKeymaster(keyAlgorithm));
+
+        @KeyStoreKeyConstraints.DigestEnum int digests;
+        if (params.isDigestsSpecified()) {
+            // Digest(s) specified in parameters
+            if (digest != null) {
+                // Digest also specified in the JCA key algorithm name.
+                if ((params.getDigests() & digest) != digest) {
+                    throw new KeyStoreException("Key digest mismatch"
+                            + ". Key: " + keyAlgorithmString
+                            + ", parameter spec: "
+                            + KeyStoreKeyConstraints.Digest.allToString(params.getDigests()));
+                }
+            }
+            digests = params.getDigests();
+        } else {
+            // No digest specified in parameters
+            if (digest != null) {
+                // Digest specified in the JCA key algorithm name.
+                digests = digest;
+            } else {
+                digests = 0;
+            }
+        }
+        for (int keymasterDigest : KeyStoreKeyConstraints.Digest.allToKeymaster(digests)) {
+            args.addInt(KeymasterDefs.KM_TAG_DIGEST, keymasterDigest);
+        }
+        if (digests != 0) {
+            // TODO: Remove MAC length constraint once Keymaster API no longer requires it.
+            // This code will blow up if mode than one digest is specified.
+            Integer digestOutputSizeBytes =
+                    KeyStoreKeyConstraints.Digest.getOutputSizeBytes(digest);
+            if (digestOutputSizeBytes != null) {
+                // TODO: Switch to bits instead of bytes, once this is fixed in Keymaster
+                args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, digestOutputSizeBytes);
+            }
+        }
+        if (keyAlgorithm == KeyStoreKeyConstraints.Algorithm.HMAC) {
+            if (digests == 0) {
+                throw new KeyStoreException("At least one digest algorithm must be specified"
+                        + " for key algorithm " + keyAlgorithmString);
+            }
+        }
+
+        int purposes = params.getPurposes();
+        for (int keymasterPurpose : KeyStoreKeyConstraints.Purpose.allToKeymaster(purposes)) {
+            args.addInt(KeymasterDefs.KM_TAG_PURPOSE, keymasterPurpose);
+        }
+        for (int keymasterBlockMode :
+            KeyStoreKeyConstraints.BlockMode.allToKeymaster(params.getBlockModes())) {
+            args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockMode);
+        }
+        for (int keymasterPadding :
+            KeyStoreKeyConstraints.Padding.allToKeymaster(params.getPaddings())) {
+            args.addInt(KeymasterDefs.KM_TAG_PADDING, keymasterPadding);
+        }
+        if (params.getUserAuthenticators() == 0) {
+            args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
+        } else {
+            args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
+                    KeyStoreKeyConstraints.UserAuthenticator.allToKeymaster(
+                            params.getUserAuthenticators()));
+        }
+        if (params.isInvalidatedOnNewFingerprintEnrolled()) {
+            // TODO: Add the invalidate on fingerprint enrolled constraint once Keymaster supports
+            // that.
+        }
+        if (params.getUserAuthenticationValidityDurationSeconds() != -1) {
+            args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
+                    params.getUserAuthenticationValidityDurationSeconds());
+        }
+        args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
+                (params.getKeyValidityStart() != null)
+                        ? params.getKeyValidityStart() : new Date(0));
+        args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
+                (params.getKeyValidityForOriginationEnd() != null)
+                        ? params.getKeyValidityForOriginationEnd() : new Date(Long.MAX_VALUE));
+        args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
+                (params.getKeyValidityForConsumptionEnd() != null)
+                        ? params.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE));
+
+        // TODO: Remove this once keymaster does not require us to specify the size of imported key.
+        args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, keyMaterial.length * 8);
+
+        if (((purposes & KeyStoreKeyConstraints.Purpose.ENCRYPT) != 0)
+                || ((purposes & KeyStoreKeyConstraints.Purpose.DECRYPT) != 0)) {
+            // Permit caller-specified IV. This is needed for the Cipher abstraction.
+            args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
+        }
+
+        Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias);
+        String keyAliasInKeystore = Credentials.USER_SECRET_KEY + entryAlias;
+        int errorCode = mKeyStore.importKey(
+                keyAliasInKeystore,
+                args,
+                KeymasterDefs.KM_KEY_FORMAT_RAW,
+                keyMaterial,
+                params.getFlags(),
+                new KeyCharacteristics());
+        if (errorCode != android.security.KeyStore.NO_ERROR) {
+            throw new KeyStoreException("Failed to import secret key. Keystore error code: "
+                + errorCode);
+        }
+    }
+
     @Override
     public void engineSetKeyEntry(String alias, byte[] userKey, Certificate[] chain)
             throws KeyStoreException {
@@ -413,6 +646,7 @@
         }
 
         return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias)
+                || mKeyStore.contains(Credentials.USER_SECRET_KEY + alias)
                 || mKeyStore.contains(Credentials.USER_CERTIFICATE + alias)
                 || mKeyStore.contains(Credentials.CA_CERTIFICATE + alias);
     }
@@ -428,6 +662,10 @@
     }
 
     private boolean isKeyEntry(String alias) {
+        return isPrivateKeyEntry(alias) || isSecretKeyEntry(alias);
+    }
+
+    private boolean isPrivateKeyEntry(String alias) {
         if (alias == null) {
             throw new NullPointerException("alias == null");
         }
@@ -435,6 +673,14 @@
         return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias);
     }
 
+    private boolean isSecretKeyEntry(String alias) {
+        if (alias == null) {
+            throw new NullPointerException("alias == null");
+        }
+
+        return mKeyStore.contains(Credentials.USER_SECRET_KEY + alias);
+    }
+
     private boolean isCertificateEntry(String alias) {
         if (alias == null) {
             throw new NullPointerException("alias == null");
@@ -554,11 +800,14 @@
             PrivateKeyEntry prE = (PrivateKeyEntry) entry;
             setPrivateKeyEntry(alias, prE.getPrivateKey(), prE.getCertificateChain(),
                     (KeyStoreParameter) param);
-            return;
+        } else if (entry instanceof SecretKeyEntry) {
+            SecretKeyEntry secE = (SecretKeyEntry) entry;
+            setSecretKeyEntry(alias, secE.getSecretKey(), (KeyStoreParameter) param);
+        } else {
+            throw new KeyStoreException(
+                    "Entry must be a PrivateKeyEntry, SecretKeyEntry or TrustedCertificateEntry"
+                    + "; was " + entry);
         }
-
-        throw new KeyStoreException(
-                "Entry must be a PrivateKeyEntry or TrustedCertificateEntry; was " + entry);
     }
 
 }
diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java
index 9081e92..a59927d 100644
--- a/keystore/java/android/security/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/AndroidKeyStoreProvider.java
@@ -18,6 +18,9 @@
 
 import java.security.Provider;
 
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+
 /**
  * A provider focused on providing JCA interfaces for the Android KeyStore.
  *
@@ -26,14 +29,89 @@
 public class AndroidKeyStoreProvider extends Provider {
     public static final String PROVIDER_NAME = "AndroidKeyStore";
 
+    // IMPLEMENTATION NOTE: Class names are hard-coded in this provider to avoid loading these
+    // classes when this provider is instantiated and installed early on during each app's
+    // initialization process.
+
+    private static final String PACKAGE_NAME = "android.security";
+    private static final String KEYSTORE_SECRET_KEY_CLASS_NAME =
+            PACKAGE_NAME + ".KeyStoreSecretKey";
+
     public AndroidKeyStoreProvider() {
         super(PROVIDER_NAME, 1.0, "Android KeyStore security provider");
 
         // java.security.KeyStore
-        put("KeyStore." + AndroidKeyStore.NAME, AndroidKeyStore.class.getName());
+        put("KeyStore.AndroidKeyStore", PACKAGE_NAME + ".AndroidKeyStore");
 
         // java.security.KeyPairGenerator
-        put("KeyPairGenerator.EC", AndroidKeyPairGenerator.EC.class.getName());
-        put("KeyPairGenerator.RSA", AndroidKeyPairGenerator.RSA.class.getName());
+        put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyPairGenerator$EC");
+        put("KeyPairGenerator.RSA", PACKAGE_NAME +  ".AndroidKeyPairGenerator$RSA");
+
+        // javax.crypto.KeyGenerator
+        put("KeyGenerator.AES", PACKAGE_NAME + ".KeyStoreKeyGeneratorSpi$AES");
+        put("KeyGenerator.HmacSHA256", PACKAGE_NAME + ".KeyStoreKeyGeneratorSpi$HmacSHA256");
+
+        // java.security.SecretKeyFactory
+        put("SecretKeyFactory.AES", PACKAGE_NAME + ".KeyStoreSecretKeyFactorySpi");
+        put("SecretKeyFactory.HmacSHA256", PACKAGE_NAME + ".KeyStoreSecretKeyFactorySpi");
+
+        // javax.crypto.Mac
+        putMacImpl("HmacSHA256", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA256");
+
+        // javax.crypto.Cipher
+        putSymmetricCipherImpl("AES/ECB/NoPadding",
+                PACKAGE_NAME + ".KeyStoreCipherSpi$AES$ECB$NoPadding");
+        putSymmetricCipherImpl("AES/ECB/PKCS7Padding",
+                PACKAGE_NAME + ".KeyStoreCipherSpi$AES$ECB$PKCS7Padding");
+
+        putSymmetricCipherImpl("AES/CBC/NoPadding",
+                PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CBC$NoPadding");
+        putSymmetricCipherImpl("AES/CBC/PKCS7Padding",
+                PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CBC$PKCS7Padding");
+
+        putSymmetricCipherImpl("AES/CTR/NoPadding",
+                PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CTR$NoPadding");
+    }
+
+    private void putMacImpl(String algorithm, String implClass) {
+        put("Mac." + algorithm, implClass);
+        put("Mac." + algorithm + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME);
+    }
+
+    private void putSymmetricCipherImpl(String transformation, String implClass) {
+        put("Cipher." + transformation, implClass);
+        put("Cipher." + transformation + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME);
+    }
+
+    /**
+     * Gets the {@link KeyStore} operation handle corresponding to the provided JCA crypto
+     * primitive.
+     *
+     * <p>The following primitives are supported: {@link Cipher} and {@link Mac}.
+     *
+     * @return KeyStore operation handle or {@code null} if the provided primitive's KeyStore
+     *         operation is not in progress.
+     *
+     * @throws IllegalArgumentException if the provided primitive is not supported or is not backed
+     *         by AndroidKeyStore provider.
+     */
+    public static Long getKeyStoreOperationHandle(Object cryptoPrimitive) {
+        if (cryptoPrimitive == null) {
+            throw new NullPointerException();
+        }
+        Object spi;
+        if (cryptoPrimitive instanceof Mac) {
+            spi = ((Mac) cryptoPrimitive).getSpi();
+        } else if (cryptoPrimitive instanceof Cipher) {
+            spi = ((Cipher) cryptoPrimitive).getSpi();
+        } else {
+            throw new IllegalArgumentException("Unsupported crypto primitive: " + cryptoPrimitive);
+        }
+        if (!(spi instanceof KeyStoreCryptoOperation)) {
+            throw new IllegalArgumentException(
+                    "Crypto primitive not backed by AndroidKeyStore: " + cryptoPrimitive
+                    + ", spi: " + spi);
+        }
+        return ((KeyStoreCryptoOperation) spi).getOperationHandle();
     }
 }
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index af76d9d..6283e02 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -61,6 +61,9 @@
     /** Key prefix for user private keys. */
     public static final String USER_PRIVATE_KEY = "USRPKEY_";
 
+    /** Key prefix for user secret keys. */
+    public static final String USER_SECRET_KEY = "USRSKEY_";
+
     /** Key prefix for VPN. */
     public static final String VPN = "VPN_";
 
@@ -218,7 +221,8 @@
          * Make sure every type is deleted. There can be all three types, so
          * don't use a conditional here.
          */
-        return keystore.delKey(Credentials.USER_PRIVATE_KEY + alias)
+        return keystore.delete(Credentials.USER_PRIVATE_KEY + alias)
+                | keystore.delete(Credentials.USER_SECRET_KEY + alias)
                 | deleteCertificateTypesForAlias(keystore, alias);
     }
 
@@ -235,4 +239,20 @@
         return keystore.delete(Credentials.USER_CERTIFICATE + alias)
                 | keystore.delete(Credentials.CA_CERTIFICATE + alias);
     }
+
+    /**
+     * Delete private key for a particular {@code alias}.
+     * Returns {@code true} if an entry was was deleted.
+     */
+    static boolean deletePrivateKeyTypeForAlias(KeyStore keystore, String alias) {
+        return keystore.delete(Credentials.USER_PRIVATE_KEY + alias);
+    }
+
+    /**
+     * Delete secret key for a particular {@code alias}.
+     * Returns {@code true} if an entry was was deleted.
+     */
+    static boolean deleteSecretKeyTypeForAlias(KeyStore keystore, String alias) {
+        return keystore.delete(Credentials.USER_SECRET_KEY + alias);
+    }
 }
diff --git a/keystore/java/android/security/CryptoOperationException.java b/keystore/java/android/security/CryptoOperationException.java
new file mode 100644
index 0000000..00c142f
--- /dev/null
+++ b/keystore/java/android/security/CryptoOperationException.java
@@ -0,0 +1,61 @@
+/*
+ * 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.security;
+
+/**
+ * Base class for exceptions during cryptographic operations which cannot throw a suitable checked
+ * exception.
+ *
+ * <p>The contract of the majority of crypto primitives/operations (e.g. {@code Cipher} or
+ * {@code Signature}) is that they can throw a checked exception during initialization, but are not
+ * permitted to throw a checked exception during operation. Because crypto operations can fail
+ * for a variety of reasons after initialization, this base class provides type-safety for unchecked
+ * exceptions that may be thrown in those cases.
+ *
+ * @hide
+ */
+public class CryptoOperationException extends RuntimeException {
+
+    /**
+     * Constructs a new {@code CryptoOperationException} without detail message and cause.
+     */
+    public CryptoOperationException() {
+        super();
+    }
+
+    /**
+     * Constructs a new {@code CryptoOperationException} with the provided detail message and no
+     * cause.
+     */
+    public CryptoOperationException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new {@code CryptoOperationException} with the provided detail message and cause.
+     */
+    public CryptoOperationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new {@code CryptoOperationException} with the provided cause.
+     */
+    public CryptoOperationException(Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/keystore/java/android/security/KeyExpiredException.java b/keystore/java/android/security/KeyExpiredException.java
new file mode 100644
index 0000000..35a5acc
--- /dev/null
+++ b/keystore/java/android/security/KeyExpiredException.java
@@ -0,0 +1,47 @@
+/*
+ * 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.security;
+
+/**
+ * Indicates that a cryptographic operation failed because the employed key's validity end date
+ * is in the past.
+ *
+ * @hide
+ */
+public class KeyExpiredException extends CryptoOperationException {
+
+    /**
+     * Constructs a new {@code KeyExpiredException} without detail message and cause.
+     */
+    public KeyExpiredException() {
+        super("Key expired");
+    }
+
+    /**
+     * Constructs a new {@code KeyExpiredException} with the provided detail message and no cause.
+     */
+    public KeyExpiredException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new {@code KeyExpiredException} with the provided detail message and cause.
+     */
+    public KeyExpiredException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/keystore/java/android/security/KeyGeneratorSpec.java b/keystore/java/android/security/KeyGeneratorSpec.java
new file mode 100644
index 0000000..0e490cd
--- /dev/null
+++ b/keystore/java/android/security/KeyGeneratorSpec.java
@@ -0,0 +1,435 @@
+/*
+ * 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.security;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Date;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+/**
+ * {@link AlgorithmParameterSpec} for initializing a {@code KeyGenerator} that works with
+ * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>.
+ *
+ * <p>The Android KeyStore facility is accessed through a {@link KeyGenerator} API using the
+ * {@code AndroidKeyStore} provider. The {@code context} passed in may be used to pop up some UI to
+ * ask the user to unlock or initialize the Android KeyStore facility.
+ *
+ * <p>After generation, the {@code keyStoreAlias} is used with the
+ * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)}
+ * interface to retrieve the {@link SecretKey}.
+ *
+ * @hide
+ */
+public class KeyGeneratorSpec implements AlgorithmParameterSpec {
+
+    private final Context mContext;
+    private final String mKeystoreAlias;
+    private final int mFlags;
+    private final Integer mKeySize;
+    private final Date mKeyValidityStart;
+    private final Date mKeyValidityForOriginationEnd;
+    private final Date mKeyValidityForConsumptionEnd;
+    private final @KeyStoreKeyConstraints.PurposeEnum int mPurposes;
+    private final @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
+    private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+    private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
+    private final int mUserAuthenticationValidityDurationSeconds;
+    private final boolean mInvalidatedOnNewFingerprintEnrolled;
+
+    private KeyGeneratorSpec(
+            Context context,
+            String keyStoreAlias,
+            int flags,
+            Integer keySize,
+            Date keyValidityStart,
+            Date keyValidityForOriginationEnd,
+            Date keyValidityForConsumptionEnd,
+            @KeyStoreKeyConstraints.PurposeEnum int purposes,
+            @KeyStoreKeyConstraints.PaddingEnum int paddings,
+            @KeyStoreKeyConstraints.BlockModeEnum int blockModes,
+            @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators,
+            int userAuthenticationValidityDurationSeconds,
+            boolean invalidatedOnNewFingerprintEnrolled) {
+        if (context == null) {
+            throw new IllegalArgumentException("context == null");
+        } else if (TextUtils.isEmpty(keyStoreAlias)) {
+            throw new IllegalArgumentException("keyStoreAlias must not be empty");
+        } else if ((userAuthenticationValidityDurationSeconds < 0)
+                && (userAuthenticationValidityDurationSeconds != -1)) {
+            throw new IllegalArgumentException(
+                    "userAuthenticationValidityDurationSeconds must not be negative");
+        }
+
+        mContext = context;
+        mKeystoreAlias = keyStoreAlias;
+        mFlags = flags;
+        mKeySize = keySize;
+        mKeyValidityStart = keyValidityStart;
+        mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
+        mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd;
+        mPurposes = purposes;
+        mPaddings = paddings;
+        mBlockModes = blockModes;
+        mUserAuthenticators = userAuthenticators;
+        mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
+        mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
+    }
+
+    /**
+     * Gets the Android context used for operations with this instance.
+     */
+    public Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * Returns the alias that will be used in the {@code java.security.KeyStore} in conjunction with
+     * the {@code AndroidKeyStore}.
+     */
+    public String getKeystoreAlias() {
+        return mKeystoreAlias;
+    }
+
+    /**
+     * @hide
+     */
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /**
+     * Gets the requested key size or {@code null} if the default size should be used.
+     */
+    public Integer getKeySize() {
+        return mKeySize;
+    }
+
+    /**
+     * Gets the time instant before which the key is not yet valid.
+     *
+     * @return instant or {@code null} if not restricted.
+     */
+    public Date getKeyValidityStart() {
+        return mKeyValidityStart;
+    }
+
+    /**
+     * Gets the time instant after which the key is no longer valid for decryption and verification.
+     *
+     * @return instant or {@code null} if not restricted.
+     */
+    public Date getKeyValidityForConsumptionEnd() {
+        return mKeyValidityForConsumptionEnd;
+    }
+
+    /**
+     * Gets the time instant after which the key is no longer valid for encryption and signing.
+     *
+     * @return instant or {@code null} if not restricted.
+     */
+    public Date getKeyValidityForOriginationEnd() {
+        return mKeyValidityForOriginationEnd;
+    }
+
+    /**
+     * Gets the set of purposes for which the key can be used.
+     */
+    public @KeyStoreKeyConstraints.PurposeEnum int getPurposes() {
+        return mPurposes;
+    }
+
+    /**
+     * Gets the set of padding schemes to which the key is restricted.
+     */
+    public @KeyStoreKeyConstraints.PaddingEnum int getPaddings() {
+        return mPaddings;
+    }
+
+    /**
+     * Gets the set of block modes to which the key is restricted.
+     */
+    public @KeyStoreKeyConstraints.BlockModeEnum int getBlockModes() {
+        return mBlockModes;
+    }
+
+    /**
+     * Gets the set of user authenticators which protect access to this key. The key can only be
+     * used iff the user has authenticated to at least one of these user authenticators.
+     *
+     * @return user authenticators or {@code 0} if the key can be used without user authentication.
+     */
+    public @KeyStoreKeyConstraints.UserAuthenticatorEnum int getUserAuthenticators() {
+        return mUserAuthenticators;
+    }
+
+    /**
+     * Gets the duration of time (seconds) for which this key can be used after the user
+     * successfully authenticates to one of the associated user authenticators.
+     *
+     * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
+     *         is required for every use of the key.
+     */
+    public int getUserAuthenticationValidityDurationSeconds() {
+        return mUserAuthenticationValidityDurationSeconds;
+    }
+
+    /**
+     * Returns {@code true} if this key must be permanently invalidated once a new fingerprint is
+     * enrolled. This constraint only has effect if fingerprint reader is one of the user
+     * authenticators protecting access to this key.
+     *
+     * @see #getUserAuthenticators()
+     *
+     * @hide
+     */
+    public boolean isInvalidatedOnNewFingerprintEnrolled() {
+        return mInvalidatedOnNewFingerprintEnrolled;
+    }
+
+    /**
+     * Returns {@code true} if the key must be encrypted in the {@link java.security.KeyStore}.
+     */
+    public boolean isEncryptionRequired() {
+        return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0;
+    }
+
+    public static class Builder {
+        private final Context mContext;
+        private String mKeystoreAlias;
+        private int mFlags;
+        private Integer mKeySize;
+        private Date mKeyValidityStart;
+        private Date mKeyValidityForOriginationEnd;
+        private Date mKeyValidityForConsumptionEnd;
+        private @KeyStoreKeyConstraints.PurposeEnum int mPurposes;
+        private @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
+        private @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+        private @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
+        private int mUserAuthenticationValidityDurationSeconds = -1;
+        private boolean mInvalidatedOnNewFingerprintEnrolled;
+
+        /**
+         * Creates a new instance of the {@code Builder} with the given {@code context}. The
+         * {@code context} passed in may be used to pop up some UI to ask the user to unlock or
+         * initialize the Android KeyStore facility.
+         */
+        public Builder(Context context) {
+            if (context == null) {
+                throw new NullPointerException("context == null");
+            }
+            mContext = context;
+        }
+
+        /**
+         * Sets the alias to be used to retrieve the key later from a {@link java.security.KeyStore}
+         * instance using the {@code AndroidKeyStore} provider.
+         *
+         * <p>The alias must be provided. There is no default.
+         */
+        public Builder setAlias(String alias) {
+            if (alias == null) {
+                throw new NullPointerException("alias == null");
+            }
+            mKeystoreAlias = alias;
+            return this;
+        }
+
+        /**
+         * Sets the size (in bits) of the key to be generated.
+         *
+         * <p>By default, the key size will be determines based on the key algorithm. For example,
+         * for {@code HmacSHA256}, the key size will default to {@code 256}.
+         */
+        public Builder setKeySize(int keySize) {
+            mKeySize = keySize;
+            return this;
+        }
+
+        /**
+         * Indicates that this key must be encrypted at rest on storage. Note that enabling this
+         * will require that the user enable a strong lock screen (e.g., PIN, password) before
+         * creating or using the generated key is successful.
+         */
+        public Builder setEncryptionRequired(boolean required) {
+            if (required) {
+                mFlags |= KeyStore.FLAG_ENCRYPTED;
+            } else {
+                mFlags &= ~KeyStore.FLAG_ENCRYPTED;
+            }
+            return this;
+        }
+
+        /**
+         * Sets the time instant before which the key is not yet valid.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityEnd(Date)
+         */
+        public Builder setKeyValidityStart(Date startDate) {
+            mKeyValidityStart = startDate;
+            return this;
+        }
+
+        /**
+         * Sets the time instant after which the key is no longer valid.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityStart(Date)
+         * @see #setKeyValidityForConsumptionEnd(Date)
+         * @see #setKeyValidityForOriginationEnd(Date)
+         */
+        public Builder setKeyValidityEnd(Date endDate) {
+            setKeyValidityForOriginationEnd(endDate);
+            setKeyValidityForConsumptionEnd(endDate);
+            return this;
+        }
+
+        /**
+         * Sets the time instant after which the key is no longer valid for encryption and signing.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityForConsumptionEnd(Date)
+         */
+        public Builder setKeyValidityForOriginationEnd(Date endDate) {
+            mKeyValidityForOriginationEnd = endDate;
+            return this;
+        }
+
+        /**
+         * Sets the time instant after which the key is no longer valid for decryption and
+         * verification.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityForOriginationEnd(Date)
+         */
+        public Builder setKeyValidityForConsumptionEnd(Date endDate) {
+            mKeyValidityForConsumptionEnd = endDate;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only for the provided set of purposes.
+         *
+         * <p>This restriction must be specified. There is no default.
+         */
+        public Builder setPurposes(@KeyStoreKeyConstraints.PurposeEnum int purposes) {
+            mPurposes = purposes;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only with the provided padding schemes. Attempts to use
+         * the key with any other padding will be rejected.
+         *
+         * <p>This restriction must be specified for keys which are used for encryption/decryption.
+         */
+        public Builder setPaddings(@KeyStoreKeyConstraints.PaddingEnum int paddings) {
+            mPaddings = paddings;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only with the provided block modes. Attempts to use the
+         * key with any other block modes will be rejected.
+         *
+         * <p>This restriction must be specified for keys which are used for encryption/decryption.
+         */
+        public Builder setBlockModes(@KeyStoreKeyConstraints.BlockModeEnum int blockModes) {
+            mBlockModes = blockModes;
+            return this;
+        }
+
+        /**
+         * Sets the user authenticators which protect access to this key. The key can only be used
+         * iff the user has authenticated to at least one of these user authenticators.
+         *
+         * <p>By default, the key can be used without user authentication.
+         *
+         * @param userAuthenticators user authenticators or empty list if this key can be accessed
+         *        without user authentication.
+         *
+         * @see #setUserAuthenticationValidityDurationSeconds(int)
+         */
+        public Builder setUserAuthenticators(
+                @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators) {
+            mUserAuthenticators = userAuthenticators;
+            return this;
+        }
+
+        /**
+         * Sets the duration of time (seconds) for which this key can be used after the user
+         * successfully authenticates to one of the associated user authenticators.
+         *
+         * <p>By default, the user needs to authenticate for every use of the key.
+         *
+         * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for
+         *        every use of the key.
+         *
+         * @see #setUserAuthenticators(int)
+         */
+        public Builder setUserAuthenticationValidityDurationSeconds(int seconds) {
+            mUserAuthenticationValidityDurationSeconds = seconds;
+            return this;
+        }
+
+        /**
+         * Sets whether this key must be invalidated (permanently) once a new fingerprint is
+         * enrolled. This only has effect if fingerprint reader is one of the user authenticators
+         * protecting access to the key.
+         *
+         * <p>By default, enrolling a new fingerprint does not invalidate the key.
+         *
+         * @see #setUserAuthenticators(Set)
+         *
+         * @hide
+         */
+        public Builder setInvalidatedOnNewFingerprintEnrolled(boolean invalidated) {
+            mInvalidatedOnNewFingerprintEnrolled = invalidated;
+            return this;
+        }
+
+        /**
+         * Builds a new instance instance of {@code KeyGeneratorSpec}.
+         *
+         * @throws IllegalArgumentException if a required field is missing or violates a constraint.
+         */
+        public KeyGeneratorSpec build() {
+            return new KeyGeneratorSpec(mContext,
+                    mKeystoreAlias,
+                    mFlags,
+                    mKeySize,
+                    mKeyValidityStart,
+                    mKeyValidityForOriginationEnd,
+                    mKeyValidityForConsumptionEnd,
+                    mPurposes,
+                    mPaddings,
+                    mBlockModes,
+                    mUserAuthenticators,
+                    mUserAuthenticationValidityDurationSeconds,
+                    mInvalidatedOnNewFingerprintEnrolled);
+        }
+    }
+}
diff --git a/keystore/java/android/security/KeyNotYetValidException.java b/keystore/java/android/security/KeyNotYetValidException.java
new file mode 100644
index 0000000..f1c2cac
--- /dev/null
+++ b/keystore/java/android/security/KeyNotYetValidException.java
@@ -0,0 +1,48 @@
+/*
+ * 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.security;
+
+/**
+ * Indicates that a cryptographic operation failed because the employed key's validity start date
+ * is in the future.
+ *
+ * @hide
+ */
+public class KeyNotYetValidException extends CryptoOperationException {
+
+    /**
+     * Constructs a new {@code KeyNotYetValidException} without detail message and cause.
+     */
+    public KeyNotYetValidException() {
+        super("Key not yet valid");
+    }
+
+    /**
+     * Constructs a new {@code KeyNotYetValidException} with the provided detail message and no
+     * cause.
+     */
+    public KeyNotYetValidException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new {@code KeyNotYetValidException} with the provided detail message and cause.
+     */
+    public KeyNotYetValidException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
index cc097aa..52b7097 100644
--- a/keystore/java/android/security/KeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/KeyPairGeneratorSpec.java
@@ -72,6 +72,26 @@
 
     private final int mFlags;
 
+    private final Date mKeyValidityStart;
+
+    private final Date mKeyValidityForOriginationEnd;
+
+    private final Date mKeyValidityForConsumptionEnd;
+
+    private final @KeyStoreKeyConstraints.PurposeEnum int mPurposes;
+
+    private final @KeyStoreKeyConstraints.DigestEnum int mDigests;
+
+    private final @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
+
+    private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+
+    private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
+
+    private final int mUserAuthenticationValidityDurationSeconds;
+
+    private final boolean mInvalidatedOnNewFingerprintEnrolled;
+
     /**
      * Parameter specification for the "{@code AndroidKeyPairGenerator}"
      * instance of the {@link java.security.KeyPairGenerator} API. The
@@ -106,7 +126,17 @@
      */
     public KeyPairGeneratorSpec(Context context, String keyStoreAlias, String keyType, int keySize,
             AlgorithmParameterSpec spec, X500Principal subjectDN, BigInteger serialNumber,
-            Date startDate, Date endDate, int flags) {
+            Date startDate, Date endDate, int flags,
+            Date keyValidityStart,
+            Date keyValidityForOriginationEnd,
+            Date keyValidityForConsumptionEnd,
+            @KeyStoreKeyConstraints.PurposeEnum int purposes,
+            @KeyStoreKeyConstraints.DigestEnum int digests,
+            @KeyStoreKeyConstraints.PaddingEnum int paddings,
+            @KeyStoreKeyConstraints.BlockModeEnum int blockModes,
+            @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators,
+            int userAuthenticationValidityDurationSeconds,
+            boolean invalidatedOnNewFingerprintEnrolled) {
         if (context == null) {
             throw new IllegalArgumentException("context == null");
         } else if (TextUtils.isEmpty(keyStoreAlias)) {
@@ -121,6 +151,10 @@
             throw new IllegalArgumentException("endDate == null");
         } else if (endDate.before(startDate)) {
             throw new IllegalArgumentException("endDate < startDate");
+        } else if ((userAuthenticationValidityDurationSeconds < 0)
+                && (userAuthenticationValidityDurationSeconds != -1)) {
+            throw new IllegalArgumentException(
+                    "userAuthenticationValidityDurationSeconds must not be negative");
         }
 
         mContext = context;
@@ -133,6 +167,27 @@
         mStartDate = startDate;
         mEndDate = endDate;
         mFlags = flags;
+        mKeyValidityStart = keyValidityStart;
+        mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
+        mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd;
+        mPurposes = purposes;
+        mDigests = digests;
+        mPaddings = paddings;
+        mBlockModes = blockModes;
+        mUserAuthenticators = userAuthenticators;
+        mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
+        mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
+    }
+
+    /**
+     * TODO: Remove this constructor once tests are switched over to the new one above.
+     * @hide
+     */
+    public KeyPairGeneratorSpec(Context context, String keyStoreAlias, String keyType, int keySize,
+            AlgorithmParameterSpec spec, X500Principal subjectDN, BigInteger serialNumber,
+            Date startDate, Date endDate, int flags) {
+        this(context, keyStoreAlias, keyType, keySize, spec, subjectDN, serialNumber, startDate,
+                endDate, flags, startDate, endDate, endDate, 0, 0, 0, 0, 0, -1, false);
     }
 
     /**
@@ -222,6 +277,120 @@
     }
 
     /**
+     * Gets the time instant before which the key pair is not yet valid.
+     *
+     * @return instant or {@code null} if not restricted.
+     *
+     * @hide
+     */
+    public Date getKeyValidityStart() {
+        return mKeyValidityStart;
+    }
+
+    /**
+     * Gets the time instant after which the key pair is no longer valid for decryption and
+     * verification.
+     *
+     * @return instant or {@code null} if not restricted.
+     *
+     * @hide
+     */
+    public Date getKeyValidityForConsumptionEnd() {
+        return mKeyValidityForConsumptionEnd;
+    }
+
+    /**
+     * Gets the time instant after which the key pair is no longer valid for encryption and signing.
+     *
+     * @return instant or {@code null} if not restricted.
+     *
+     * @hide
+     */
+    public Date getKeyValidityForOriginationEnd() {
+        return mKeyValidityForOriginationEnd;
+    }
+
+    /**
+     * Gets the set of purposes for which the key can be used.
+     *
+     * @hide
+     */
+    public @KeyStoreKeyConstraints.PurposeEnum int getPurposes() {
+        return mPurposes;
+    }
+
+    /**
+     * Gets the set of digests to which the key is restricted.
+     *
+     * @hide
+     */
+    public @KeyStoreKeyConstraints.DigestEnum int getDigests() {
+        return mDigests;
+    }
+
+    /**
+     * Gets the set of padding schemes to which the key is restricted.
+     *
+     * @hide
+     */
+    public @KeyStoreKeyConstraints.PaddingEnum int getPaddings() {
+        return mPaddings;
+    }
+
+    /**
+     * Gets the set of block modes to which the key is restricted.
+     *
+     * @hide
+     */
+    public @KeyStoreKeyConstraints.BlockModeEnum int getBlockModes() {
+        return mBlockModes;
+    }
+
+    /**
+     * Gets the set of user authenticators which protect access to the private key. The key can only
+     * be used iff the user has authenticated to at least one of these user authenticators.
+     *
+     * <p>This restriction applies only to private key operations. Public key operations are not
+     * restricted.
+     *
+     * @return user authenticators or {@code 0} if the key can be used without user authentication.
+     *
+     * @hide
+     */
+    public @KeyStoreKeyConstraints.UserAuthenticatorEnum int getUserAuthenticators() {
+        return mUserAuthenticators;
+    }
+
+    /**
+     * Gets the duration of time (seconds) for which the private key can be used after the user
+     * successfully authenticates to one of the associated user authenticators.
+     *
+     * <p>This restriction applies only to private key operations. Public key operations are not
+     * restricted.
+     *
+     * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
+     *         is required for every use of the key.
+     *
+     * @hide
+     */
+    public int getUserAuthenticationValidityDurationSeconds() {
+        return mUserAuthenticationValidityDurationSeconds;
+    }
+
+    /**
+     * Returns {@code true} if this key must be permanently invalidated once a new fingerprint is
+     * enrolled. This constraint only has effect if fingerprint reader is one of the user
+     * authenticators protecting access to this key.
+     *
+     * @see #getUserAuthenticators()
+     *
+     * @hide
+     */
+    public boolean isInvalidatedOnNewFingerprintEnrolled() {
+        return mInvalidatedOnNewFingerprintEnrolled;
+    }
+
+    /**
      * Builder class for {@link KeyPairGeneratorSpec} objects.
      * <p>
      * This will build a parameter spec for use with the <a href="{@docRoot}
@@ -263,6 +432,26 @@
 
         private int mFlags;
 
+        private Date mKeyValidityStart;
+
+        private Date mKeyValidityForOriginationEnd;
+
+        private Date mKeyValidityForConsumptionEnd;
+
+        private @KeyStoreKeyConstraints.PurposeEnum int mPurposes;
+
+        private @KeyStoreKeyConstraints.DigestEnum int mDigests;
+
+        private @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
+
+        private @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+
+        private @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
+
+        private int mUserAuthenticationValidityDurationSeconds = -1;
+
+        private boolean mInvalidatedOnNewFingerprintEnrolled;
+
         /**
          * Creates a new instance of the {@code Builder} with the given
          * {@code context}. The {@code context} passed in may be used to pop up
@@ -389,14 +578,202 @@
         }
 
         /**
+         * Sets the time instant before which the key is not yet valid.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityEnd(Date)
+         *
+         * @hide
+         */
+        public Builder setKeyValidityStart(Date startDate) {
+            mKeyValidityStart = startDate;
+            return this;
+        }
+
+        /**
+         * Sets the time instant after which the key is no longer valid.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityStart(Date)
+         * @see #setKeyValidityForConsumptionEnd(Date)
+         * @see #setKeyValidityForOriginationEnd(Date)
+         *
+         * @hide
+         */
+        public Builder setKeyValidityEnd(Date endDate) {
+            setKeyValidityForOriginationEnd(endDate);
+            setKeyValidityForConsumptionEnd(endDate);
+            return this;
+        }
+
+        /**
+         * Sets the time instant after which the key is no longer valid for encryption and signing.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityForConsumptionEnd(Date)
+         *
+         * @hide
+         */
+        public Builder setKeyValidityForOriginationEnd(Date endDate) {
+            mKeyValidityForOriginationEnd = endDate;
+            return this;
+        }
+
+        /**
+         * Sets the time instant after which the key is no longer valid for decryption and
+         * verification.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityForOriginationEnd(Date)
+         *
+         * @hide
+         */
+        public Builder setKeyValidityForConsumptionEnd(Date endDate) {
+            mKeyValidityForConsumptionEnd = endDate;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only for the provided set of purposes.
+         *
+         * <p>This restriction must be specified. There is no default.
+         *
+         * @hide
+         */
+        public Builder setPurposes(@KeyStoreKeyConstraints.PurposeEnum int purposes) {
+            mPurposes = purposes;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only with the provided digests. Attempts to use the key
+         * with any other digests be rejected.
+         *
+         * <p>This restriction must be specified for keys which are used for signing/verification.
+         *
+         * @hide
+         */
+        public Builder setDigests(@KeyStoreKeyConstraints.DigestEnum int digests) {
+            mDigests = digests;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only with the provided padding schemes. Attempts to use
+         * the key with any other padding will be rejected.
+         *
+         * <p>This restriction must be specified for keys which are used for encryption/decryption.
+         *
+         * @hide
+         */
+        public Builder setPaddings(@KeyStoreKeyConstraints.PaddingEnum int paddings) {
+            mPaddings = paddings;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only with the provided block mode when encrypting or
+         * decrypting. Attempts to use the key with any other block modes will be rejected.
+         *
+         * <p>This restriction must be specified for keys which are used for encryption/decryption.
+         *
+         * @hide
+         */
+        public Builder setBlockModes(@KeyStoreKeyConstraints.BlockModeEnum int blockModes) {
+            mBlockModes = blockModes;
+            return this;
+        }
+
+        /**
+         * Sets the user authenticators which protect access to this key. The key can only be used
+         * iff the user has authenticated to at least one of these user authenticators.
+         *
+         * <p>By default, the key can be used without user authentication.
+         *
+         * <p>This restriction applies only to private key operations. Public key operations are not
+         * restricted.
+         *
+         * @param userAuthenticators user authenticators or {@code 0} if this key can be accessed
+         *        without user authentication.
+         *
+         * @see #setUserAuthenticationValidityDurationSeconds(int)
+         *
+         * @hide
+         */
+        public Builder setUserAuthenticators(
+                @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators) {
+            mUserAuthenticators = userAuthenticators;
+            return this;
+        }
+
+        /**
+         * Sets the duration of time (seconds) for which this key can be used after the user
+         * successfully authenticates to one of the associated user authenticators.
+         *
+         * <p>By default, the user needs to authenticate for every use of the key.
+         *
+         * <p>This restriction applies only to private key operations. Public key operations are not
+         * restricted.
+         *
+         * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for
+         *        every use of the key.
+         *
+         * @see #setUserAuthenticators(int)
+         *
+         * @hide
+         */
+        public Builder setUserAuthenticationValidityDurationSeconds(int seconds) {
+            mUserAuthenticationValidityDurationSeconds = seconds;
+            return this;
+        }
+
+        /**
+         * Sets whether this key must be invalidated (permanently) once a new fingerprint is
+         * enrolled. This only has effect if fingerprint reader is one of the user authenticators
+         * protecting access to the key.
+         *
+         * <p>By default, enrolling a new fingerprint does not invalidate the key.
+         *
+         * @see #setUserAuthenticators(Set)
+         *
+         * @hide
+         */
+        public Builder setInvalidatedOnNewFingerprintEnrolled(boolean invalidated) {
+            mInvalidatedOnNewFingerprintEnrolled = invalidated;
+            return this;
+        }
+
+        /**
          * Builds the instance of the {@code KeyPairGeneratorSpec}.
          *
          * @throws IllegalArgumentException if a required field is missing
          * @return built instance of {@code KeyPairGeneratorSpec}
          */
         public KeyPairGeneratorSpec build() {
-            return new KeyPairGeneratorSpec(mContext, mKeystoreAlias, mKeyType, mKeySize, mSpec,
-                    mSubjectDN, mSerialNumber, mStartDate, mEndDate, mFlags);
+            return new KeyPairGeneratorSpec(mContext,
+                    mKeystoreAlias,
+                    mKeyType,
+                    mKeySize,
+                    mSpec,
+                    mSubjectDN,
+                    mSerialNumber,
+                    mStartDate,
+                    mEndDate,
+                    mFlags,
+                    mKeyValidityStart,
+                    mKeyValidityForOriginationEnd,
+                    mKeyValidityForConsumptionEnd,
+                    mPurposes,
+                    mDigests,
+                    mPaddings,
+                    mBlockModes,
+                    mUserAuthenticators,
+                    mUserAuthenticationValidityDurationSeconds,
+                    mInvalidatedOnNewFingerprintEnrolled);
         }
     }
 }
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index bfbf028..5af0527 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -25,6 +25,8 @@
 import android.security.keymaster.ExportResult;
 import android.security.keymaster.KeyCharacteristics;
 import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterBlob;
+import android.security.keymaster.KeymasterDefs;
 import android.security.keymaster.OperationResult;
 import android.util.Log;
 
@@ -388,22 +390,22 @@
         }
     }
 
-    public int generateKey(String alias, KeymasterArguments args, int uid, int flags,
-            KeyCharacteristics outCharacteristics) {
+    public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
+            int flags, KeyCharacteristics outCharacteristics) {
         try {
-            return mBinder.generateKey(alias, args, uid, flags, outCharacteristics);
+            return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
         }
     }
 
-    public int generateKey(String alias, KeymasterArguments args, int flags,
+    public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
             KeyCharacteristics outCharacteristics) {
-        return generateKey(alias, args, UID_SELF, flags, outCharacteristics);
+        return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
     }
 
-    public int getKeyCharacteristics(String alias, byte[] clientId, byte[] appId,
+    public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
             KeyCharacteristics outCharacteristics) {
         try {
             return mBinder.getKeyCharacteristics(alias, clientId, appId, outCharacteristics);
@@ -429,7 +431,8 @@
         return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
     }
 
-    public ExportResult exportKey(String alias, int format, byte[] clientId, byte[] appId) {
+    public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
+            KeymasterBlob appId) {
         try {
             return mBinder.exportKey(alias, format, clientId, appId);
         } catch (RemoteException e) {
@@ -439,9 +442,9 @@
     }
 
     public OperationResult begin(String alias, int purpose, boolean pruneable,
-            KeymasterArguments args, KeymasterArguments outArgs) {
+            KeymasterArguments args, byte[] entropy, KeymasterArguments outArgs) {
         try {
-            return mBinder.begin(getToken(), alias, purpose, pruneable, args, outArgs);
+            return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, outArgs);
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
@@ -474,4 +477,90 @@
             return SYSTEM_ERROR;
         }
     }
+
+    /**
+     * Check if the operation referenced by {@code token} is currently authorized.
+     *
+     * @param token An operation token returned by a call to {@link KeyStore.begin}.
+     */
+    public boolean isOperationAuthorized(IBinder token) {
+        try {
+            return mBinder.isOperationAuthorized(token);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Cannot connect to keystore", e);
+            return false;
+        }
+    }
+
+    /**
+     * Add an authentication record to the keystore authorization table.
+     *
+     * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
+     * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
+     * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
+     */
+    public int addAuthToken(byte[] authToken) {
+        try {
+            return mBinder.addAuthToken(authToken);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Cannot connect to keystore", e);
+            return SYSTEM_ERROR;
+        }
+    }
+
+    public static KeyStoreException getKeyStoreException(int errorCode) {
+        if (errorCode > 0) {
+            // KeyStore layer error
+            switch (errorCode) {
+                case NO_ERROR:
+                    return new KeyStoreException(errorCode, "OK");
+                case LOCKED:
+                    return new KeyStoreException(errorCode, "Keystore locked");
+                case UNINITIALIZED:
+                    return new KeyStoreException(errorCode, "Keystore not initialized");
+                case SYSTEM_ERROR:
+                    return new KeyStoreException(errorCode, "System error");
+                case PERMISSION_DENIED:
+                    return new KeyStoreException(errorCode, "Permission denied");
+                case KEY_NOT_FOUND:
+                    return new KeyStoreException(errorCode, "Key not found");
+                case VALUE_CORRUPTED:
+                    return new KeyStoreException(errorCode, "Key blob corrupted");
+                default:
+                    return new KeyStoreException(errorCode, String.valueOf(errorCode));
+            }
+        } else {
+            // Keymaster layer error
+            switch (errorCode) {
+                case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
+                    // The name of this parameter significantly differs between Keymaster and
+                    // framework APIs. Use the framework wording to make life easier for developers.
+                    return new KeyStoreException(errorCode,
+                            "Invalid user authentication validity duration");
+                default:
+                    return new KeyStoreException(errorCode,
+                            KeymasterDefs.getErrorMessage(errorCode));
+            }
+        }
+    }
+
+    public static CryptoOperationException getCryptoOperationException(KeyStoreException e) {
+        switch (e.getErrorCode()) {
+            case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
+                return new KeyExpiredException();
+            case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
+                return new KeyNotYetValidException();
+            case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
+                return new UserNotAuthenticatedException();
+            // TODO: Handle TBD Keymaster error code "invalid key: new fingerprint enrolled"
+            // case KeymasterDefs.KM_ERROR_TBD
+            //     return new NewFingerprintEnrolledException();
+            default:
+                return new CryptoOperationException("Crypto operation failed", e);
+        }
+    }
+
+    public static CryptoOperationException getCryptoOperationException(int errorCode) {
+        return getCryptoOperationException(getKeyStoreException(errorCode));
+    }
 }
diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java
new file mode 100644
index 0000000..ec358d6
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreCipherSpi.java
@@ -0,0 +1,573 @@
+/*
+ * 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.security;
+
+import android.os.IBinder;
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterDefs;
+import android.security.keymaster.OperationResult;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.Arrays;
+
+import javax.crypto.AEADBadTagException;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherSpi;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * Base class for {@link CipherSpi} providing Android KeyStore backed ciphers.
+ *
+ * @hide
+ */
+public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCryptoOperation {
+
+    public abstract static class AES extends KeyStoreCipherSpi {
+        protected AES(@KeyStoreKeyConstraints.BlockModeEnum int blockMode,
+                @KeyStoreKeyConstraints.PaddingEnum int padding, boolean ivUsed) {
+            super(KeyStoreKeyConstraints.Algorithm.AES,
+                    blockMode,
+                    padding,
+                    16,
+                    ivUsed);
+        }
+
+        public abstract static class ECB extends AES {
+            protected ECB(@KeyStoreKeyConstraints.PaddingEnum int padding) {
+                super(KeyStoreKeyConstraints.BlockMode.ECB, padding, false);
+            }
+
+            public static class NoPadding extends ECB {
+                public NoPadding() {
+                    super(KeyStoreKeyConstraints.Padding.NONE);
+                }
+            }
+
+            public static class PKCS7Padding extends ECB {
+                public PKCS7Padding() {
+                    super(KeyStoreKeyConstraints.Padding.PKCS7);
+                }
+            }
+        }
+
+        public abstract static class CBC extends AES {
+            protected CBC(@KeyStoreKeyConstraints.BlockModeEnum int padding) {
+                super(KeyStoreKeyConstraints.BlockMode.CBC, padding, true);
+            }
+
+            public static class NoPadding extends CBC {
+                public NoPadding() {
+                    super(KeyStoreKeyConstraints.Padding.NONE);
+                }
+            }
+
+            public static class PKCS7Padding extends CBC {
+                public PKCS7Padding() {
+                    super(KeyStoreKeyConstraints.Padding.PKCS7);
+                }
+            }
+        }
+
+        public abstract static class CTR extends AES {
+            protected CTR(@KeyStoreKeyConstraints.BlockModeEnum int padding) {
+                super(KeyStoreKeyConstraints.BlockMode.CTR, padding, true);
+            }
+
+            public static class NoPadding extends CTR {
+                public NoPadding() {
+                    super(KeyStoreKeyConstraints.Padding.NONE);
+                }
+            }
+        }
+    }
+
+    private final KeyStore mKeyStore;
+    private final @KeyStoreKeyConstraints.AlgorithmEnum int mAlgorithm;
+    private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockMode;
+    private final @KeyStoreKeyConstraints.PaddingEnum int mPadding;
+    private final int mBlockSizeBytes;
+    private final boolean mIvUsed;
+
+    // Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after
+    // doFinal finishes.
+    protected boolean mEncrypting;
+    private KeyStoreSecretKey mKey;
+    private SecureRandom mRng;
+    private boolean mFirstOperationInitiated;
+    byte[] mIv;
+
+    // Fields below must be reset
+    private byte[] mAdditionalEntropyForBegin;
+    /**
+     * Token referencing this operation inside keystore service. It is initialized by
+     * {@code engineInit} and is invalidated when {@code engineDoFinal} succeeds and one some
+     * error conditions in between.
+     */
+    private IBinder mOperationToken;
+    private Long mOperationHandle;
+    private KeyStoreCryptoOperationChunkedStreamer mMainDataStreamer;
+
+    protected KeyStoreCipherSpi(
+            @KeyStoreKeyConstraints.AlgorithmEnum int algorithm,
+            @KeyStoreKeyConstraints.BlockModeEnum int blockMode,
+            @KeyStoreKeyConstraints.PaddingEnum int padding,
+            int blockSizeBytes,
+            boolean ivUsed) {
+        mKeyStore = KeyStore.getInstance();
+        mAlgorithm = algorithm;
+        mBlockMode = blockMode;
+        mPadding = padding;
+        mBlockSizeBytes = blockSizeBytes;
+        mIvUsed = ivUsed;
+    }
+
+    @Override
+    protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
+        init(opmode, key, random);
+        initAlgorithmSpecificParameters();
+        ensureKeystoreOperationInitialized();
+    }
+
+    @Override
+    protected void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        init(opmode, key, random);
+        initAlgorithmSpecificParameters(params);
+        ensureKeystoreOperationInitialized();
+    }
+
+    @Override
+    protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+            SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
+        init(opmode, key, random);
+        initAlgorithmSpecificParameters(params);
+        ensureKeystoreOperationInitialized();
+    }
+
+    private void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
+        reset();
+        if (!(key instanceof KeyStoreSecretKey)) {
+            throw new InvalidKeyException(
+                    "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
+        }
+        mKey = (KeyStoreSecretKey) key;
+        mRng = random;
+        mIv = null;
+        mFirstOperationInitiated = false;
+
+        if ((opmode != Cipher.ENCRYPT_MODE) && (opmode != Cipher.DECRYPT_MODE)) {
+            throw new UnsupportedOperationException(
+                    "Only ENCRYPT and DECRYPT modes supported. Mode: " + opmode);
+        }
+        mEncrypting = opmode == Cipher.ENCRYPT_MODE;
+    }
+
+    private void reset() {
+        IBinder operationToken = mOperationToken;
+        if (operationToken != null) {
+            mOperationToken = null;
+            mKeyStore.abort(operationToken);
+        }
+        mOperationHandle = null;
+        mMainDataStreamer = null;
+        mAdditionalEntropyForBegin = null;
+    }
+
+    private void ensureKeystoreOperationInitialized() {
+        if (mMainDataStreamer != null) {
+            return;
+        }
+        if (mKey == null) {
+            throw new IllegalStateException("Not initialized");
+        }
+
+        KeymasterArguments keymasterInputArgs = new KeymasterArguments();
+        keymasterInputArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mAlgorithm);
+        keymasterInputArgs.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, mBlockMode);
+        keymasterInputArgs.addInt(KeymasterDefs.KM_TAG_PADDING, mPadding);
+        addAlgorithmSpecificParametersToBegin(keymasterInputArgs);
+
+        KeymasterArguments keymasterOutputArgs = new KeymasterArguments();
+        OperationResult opResult = mKeyStore.begin(
+                mKey.getAlias(),
+                mEncrypting ? KeymasterDefs.KM_PURPOSE_ENCRYPT : KeymasterDefs.KM_PURPOSE_DECRYPT,
+                true, // permit aborting this operation if keystore runs out of resources
+                keymasterInputArgs,
+                mAdditionalEntropyForBegin,
+                keymasterOutputArgs);
+        mAdditionalEntropyForBegin = null;
+        if (opResult == null) {
+            throw new KeyStoreConnectException();
+        } else if (opResult.resultCode != KeyStore.NO_ERROR) {
+            throw KeyStore.getCryptoOperationException(opResult.resultCode);
+        }
+
+        if (opResult.token == null) {
+            throw new CryptoOperationException("Keystore returned null operation token");
+        }
+        mOperationToken = opResult.token;
+        mOperationHandle = opResult.operationHandle;
+        loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
+        mFirstOperationInitiated = true;
+        mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
+                new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
+                        mKeyStore, opResult.token));
+    }
+
+    @Override
+    protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
+        ensureKeystoreOperationInitialized();
+
+        if (inputLen == 0) {
+            return null;
+        }
+
+        byte[] output;
+        try {
+            output = mMainDataStreamer.update(input, inputOffset, inputLen);
+        } catch (KeyStoreException e) {
+            throw KeyStore.getCryptoOperationException(e);
+        }
+
+        if (output.length == 0) {
+            return null;
+        }
+
+        return output;
+    }
+
+    @Override
+    protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
+            int outputOffset) throws ShortBufferException {
+        byte[] outputCopy = engineUpdate(input, inputOffset, inputLen);
+        if (outputCopy == null) {
+            return 0;
+        }
+        int outputAvailable = output.length - outputOffset;
+        if (outputCopy.length > outputAvailable) {
+            throw new ShortBufferException("Output buffer too short. Produced: "
+                    + outputCopy.length + ", available: " + outputAvailable);
+        }
+        System.arraycopy(outputCopy, 0, output, outputOffset, outputCopy.length);
+        return outputCopy.length;
+    }
+
+    @Override
+    protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
+            throws IllegalBlockSizeException, BadPaddingException {
+        ensureKeystoreOperationInitialized();
+
+        byte[] output;
+        try {
+            output = mMainDataStreamer.doFinal(input, inputOffset, inputLen);
+        } catch (KeyStoreException e) {
+            switch (e.getErrorCode()) {
+                case KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH:
+                    throw new IllegalBlockSizeException();
+                case KeymasterDefs.KM_ERROR_INVALID_ARGUMENT:
+                    throw new BadPaddingException();
+                case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED:
+                    throw new AEADBadTagException();
+                default:
+                    throw KeyStore.getCryptoOperationException(e);
+            }
+        }
+
+        reset();
+        return output;
+    }
+
+    @Override
+    protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
+            int outputOffset) throws ShortBufferException, IllegalBlockSizeException,
+            BadPaddingException {
+        byte[] outputCopy = engineDoFinal(input, inputOffset, inputLen);
+        if (outputCopy == null) {
+            return 0;
+        }
+        int outputAvailable = output.length - outputOffset;
+        if (outputCopy.length > outputAvailable) {
+            throw new ShortBufferException("Output buffer too short. Produced: "
+                    + outputCopy.length + ", available: " + outputAvailable);
+        }
+        System.arraycopy(outputCopy, 0, output, outputOffset, outputCopy.length);
+        return outputCopy.length;
+    }
+
+    @Override
+    protected int engineGetBlockSize() {
+        return mBlockSizeBytes;
+    }
+
+    @Override
+    protected byte[] engineGetIV() {
+        return (mIv != null) ? mIv.clone() : null;
+    }
+
+    @Override
+    protected int engineGetOutputSize(int inputLen) {
+        return inputLen + 3 * engineGetBlockSize();
+    }
+
+    @Override
+    protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
+        // This should never be invoked because all algorithms registered with the AndroidKeyStore
+        // provide explicitly specify block mode.
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected void engineSetPadding(String arg0) throws NoSuchPaddingException {
+        // This should never be invoked because all algorithms registered with the AndroidKeyStore
+        // provide explicitly specify padding mode.
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void finalize() throws Throwable {
+        try {
+            IBinder operationToken = mOperationToken;
+            if (operationToken != null) {
+                mKeyStore.abort(operationToken);
+            }
+        } finally {
+            super.finalize();
+        }
+    }
+
+    @Override
+    public Long getOperationHandle() {
+        return mOperationHandle;
+    }
+
+    // The methods below may need to be overridden by subclasses that use algorithm-specific
+    // parameters.
+
+    /**
+     * Returns algorithm-specific parameters used by this {@code CipherSpi} instance or {@code null}
+     * if no algorithm-specific parameters are used.
+     *
+     * <p>This implementation only handles the IV parameter.
+     */
+    @Override
+    protected AlgorithmParameters engineGetParameters() {
+        if (!mIvUsed) {
+            return null;
+        }
+        if ((mIv != null) && (mIv.length > 0)) {
+            try {
+                AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
+                params.init(new IvParameterSpec(mIv));
+                return params;
+            } catch (NoSuchAlgorithmException e) {
+                throw new RuntimeException("Failed to obtain AES AlgorithmParameters", e);
+            } catch (InvalidParameterSpecException e) {
+                throw new RuntimeException(
+                        "Failed to initialize AES AlgorithmParameters with an IV", e);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Invoked by {@code engineInit} to initialize algorithm-specific parameters. These parameters
+     * may need to be stored to be reused after {@code doFinal}.
+     *
+     * <p>The default implementation only handles the IV parameters.
+     *
+     * @param params algorithm parameters.
+     *
+     * @throws InvalidAlgorithmParameterException if some/all of the parameters cannot be
+     *         automatically configured and thus {@code Cipher.init} needs to be invoked with
+     *         explicitly provided parameters.
+     */
+    protected void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
+            throws InvalidAlgorithmParameterException {
+        if (!mIvUsed) {
+            if (params != null) {
+                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
+            }
+            return;
+        }
+
+        // IV is used
+        if (params == null) {
+            if (!mEncrypting) {
+                // IV must be provided by the caller
+                throw new InvalidAlgorithmParameterException(
+                        "IvParameterSpec must be provided when decrypting");
+            }
+            return;
+        }
+        if (!(params instanceof IvParameterSpec)) {
+            throw new InvalidAlgorithmParameterException("Only IvParameterSpec supported");
+        }
+        mIv = ((IvParameterSpec) params).getIV();
+        if (mIv == null) {
+            throw new InvalidAlgorithmParameterException("Null IV in IvParameterSpec");
+        }
+    }
+
+    /**
+     * Invoked by {@code engineInit} to initialize algorithm-specific parameters. These parameters
+     * may need to be stored to be reused after {@code doFinal}.
+     *
+     * <p>The default implementation only handles the IV parameters.
+     *
+     * @param params algorithm parameters.
+     *
+     * @throws InvalidAlgorithmParameterException if some/all of the parameters cannot be
+     *         automatically configured and thus {@code Cipher.init} needs to be invoked with
+     *         explicitly provided parameters.
+     */
+    protected void initAlgorithmSpecificParameters(AlgorithmParameters params)
+            throws InvalidAlgorithmParameterException {
+        if (!mIvUsed) {
+            if (params != null) {
+                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
+            }
+            return;
+        }
+
+        // IV is used
+        if (params == null) {
+            if (!mEncrypting) {
+                // IV must be provided by the caller
+                throw new InvalidAlgorithmParameterException("IV required when decrypting"
+                        + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
+            }
+            return;
+        }
+
+        IvParameterSpec ivSpec;
+        try {
+            ivSpec = params.getParameterSpec(IvParameterSpec.class);
+        } catch (InvalidParameterSpecException e) {
+            if (!mEncrypting) {
+                // IV must be provided by the caller
+                throw new InvalidAlgorithmParameterException("IV required when decrypting"
+                        + ", but not found in parameters: " + params, e);
+            }
+            mIv = null;
+            return;
+        }
+        mIv = ivSpec.getIV();
+        if (mIv == null) {
+            throw new InvalidAlgorithmParameterException("Null IV in AlgorithmParameters");
+        }
+    }
+
+    /**
+     * Invoked by {@code engineInit} to initialize algorithm-specific parameters. These parameters
+     * may need to be stored to be reused after {@code doFinal}.
+     *
+     * <p>The default implementation only handles the IV parameter.
+     *
+     * @throws InvalidKeyException if some/all of the parameters cannot be automatically configured
+     *         and thus {@code Cipher.init} needs to be invoked with explicitly provided parameters.
+     */
+    protected void initAlgorithmSpecificParameters() throws InvalidKeyException {
+        if (!mIvUsed) {
+            return;
+        }
+
+        // IV is used
+        if (!mEncrypting) {
+            throw new InvalidKeyException("IV required when decrypting"
+                    + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
+        }
+    }
+
+    /**
+     * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation.
+     *
+     * <p>The default implementation takes care of the IV.
+     *
+     * @param keymasterArgs keystore/keymaster arguments to be populated with algorithm-specific
+     *        parameters.
+     */
+    protected void addAlgorithmSpecificParametersToBegin(KeymasterArguments keymasterArgs) {
+        if (!mFirstOperationInitiated) {
+            // First begin operation -- see if we need to provide additional entropy for IV
+            // generation.
+            if (mIvUsed) {
+                // IV is needed
+                if ((mIv == null) && (mEncrypting)) {
+                    // TODO: Switch to keymaster-generated IV code below once keymaster supports
+                    // that.
+                    // IV is needed but was not provided by the caller -- generate an IV.
+                    mIv = new byte[mBlockSizeBytes];
+                    SecureRandom rng = (mRng != null) ? mRng : new SecureRandom();
+                    rng.nextBytes(mIv);
+//                    // IV was not provided by the caller and thus will be generated by keymaster.
+//                    // Mix in some additional entropy from the provided SecureRandom.
+//                    if (mRng != null) {
+//                        mAdditionalEntropyForBegin = new byte[mBlockSizeBytes];
+//                        mRng.nextBytes(mAdditionalEntropyForBegin);
+//                    }
+                }
+            }
+        }
+
+        if ((mIvUsed) && (mIv != null)) {
+            keymasterArgs.addBlob(KeymasterDefs.KM_TAG_NONCE, mIv);
+        }
+    }
+
+    /**
+     * Invoked by {@code engineInit} to obtain algorithm-specific parameters from the result of the
+     * Keymaster's {@code begin} operation. Some of these parameters may need to be reused after
+     * {@code doFinal} by {@link #addAlgorithmSpecificParametersToBegin(KeymasterArguments)}.
+     *
+     * <p>The default implementation only takes care of the IV.
+     *
+     * @param keymasterArgs keystore/keymaster arguments returned by KeyStore {@code begin}
+     *        operation.
+     */
+    protected void loadAlgorithmSpecificParametersFromBeginResult(
+            KeymasterArguments keymasterArgs) {
+        // NOTE: Keymaster doesn't always return an IV, even if it's used.
+        byte[] returnedIv = keymasterArgs.getBlob(KeymasterDefs.KM_TAG_NONCE, null);
+        if ((returnedIv != null) && (returnedIv.length == 0)) {
+            returnedIv = null;
+        }
+
+        if (mIvUsed) {
+            if (mIv == null) {
+                mIv = returnedIv;
+            } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
+                throw new CryptoOperationException("IV in use differs from provided IV");
+            }
+        } else {
+            if (returnedIv != null) {
+                throw new CryptoOperationException(
+                        "IV in use despite IV not being used by this transformation");
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/keystore/java/android/security/KeyStoreConnectException.java
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to keystore/java/android/security/KeyStoreConnectException.java
index 272c321..8ed6e04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/keystore/java/android/security/KeyStoreConnectException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
@@ -14,8 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+package android.security;
 
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
+/**
+ * Indicates a communications error with keystore service.
+ *
+ * @hide
+ */
+public class KeyStoreConnectException extends CryptoOperationException {
+    public KeyStoreConnectException() {
+        super("Failed to communicate with keystore service");
+    }
 }
diff --git a/keystore/java/android/security/KeyStoreCryptoOperation.java b/keystore/java/android/security/KeyStoreCryptoOperation.java
new file mode 100644
index 0000000..19abd05
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreCryptoOperation.java
@@ -0,0 +1,31 @@
+/*
+ * 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.security;
+
+/**
+ * Cryptographic operation backed by {@link KeyStore}.
+ *
+ * @hide
+ */
+public interface KeyStoreCryptoOperation {
+    /**
+     * Gets the KeyStore operation handle of this crypto operation.
+     *
+     * @return handle or {@code null} if the KeyStore operation is not in progress.
+     */
+    Long getOperationHandle();
+}
diff --git a/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java
new file mode 100644
index 0000000..1f8b7e4
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java
@@ -0,0 +1,309 @@
+/*
+ * 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.security;
+
+import android.os.IBinder;
+import android.security.keymaster.OperationResult;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Helper for streaming a crypto operation's input and output via {@link KeyStore} service's
+ * {@code update} and {@code finish} operations.
+ *
+ * <p>The helper abstracts away to issues that need to be solved in most code that uses KeyStore's
+ * update and finish operations. Firstly, KeyStore's update operation can consume only a limited
+ * amount of data in one go because the operations are marshalled via Binder. Secondly, the update
+ * operation may consume less data than provided, in which case the caller has to buffer the
+ * remainder for next time. The helper exposes {@link #update(byte[], int, int) update} and
+ * {@link #doFinal(byte[], int, int) doFinal} operations which can be used to conveniently implement
+ * various JCA crypto primitives.
+ *
+ * <p>Bidirectional chunked streaming of data via a KeyStore crypto operation is abstracted away as
+ * a {@link Stream} to avoid having this class deal with operation tokens and occasional additional
+ * parameters to {@code update} and {@code final} operations.
+ *
+ * @hide
+ */
+public class KeyStoreCryptoOperationChunkedStreamer {
+
+    /**
+     * Bidirectional chunked data stream over a KeyStore crypto operation.
+     */
+    public interface Stream {
+        /**
+         * Returns the result of the KeyStore {@code update} operation or null if keystore couldn't
+         * be reached.
+         */
+        OperationResult update(byte[] input);
+
+        /**
+         * Returns the result of the KeyStore {@code finish} operation or null if keystore couldn't
+         * be reached.
+         */
+        OperationResult finish();
+    }
+
+    // Binder buffer is about 1MB, but it's shared between all active transactions of the process.
+    // Thus, it's safer to use a much smaller upper bound.
+    private static final int DEFAULT_MAX_CHUNK_SIZE = 64 * 1024;
+    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+    private final Stream mKeyStoreStream;
+    private final int mMaxChunkSize;
+
+    private byte[] mBuffered = EMPTY_BYTE_ARRAY;
+    private int mBufferedOffset;
+    private int mBufferedLength;
+
+    public KeyStoreCryptoOperationChunkedStreamer(Stream operation) {
+        this(operation, DEFAULT_MAX_CHUNK_SIZE);
+    }
+
+    public KeyStoreCryptoOperationChunkedStreamer(Stream operation, int maxChunkSize) {
+        mKeyStoreStream = operation;
+        mMaxChunkSize = maxChunkSize;
+    }
+
+    public byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException {
+        if (inputLength == 0) {
+            // No input provided
+            return EMPTY_BYTE_ARRAY;
+        }
+
+        ByteArrayOutputStream bufferedOutput = null;
+
+        while (inputLength > 0) {
+            byte[] chunk;
+            int inputBytesInChunk;
+            if ((mBufferedLength + inputLength) > mMaxChunkSize) {
+                // Too much input for one chunk -- extract one max-sized chunk and feed it into the
+                // update operation.
+                inputBytesInChunk = mMaxChunkSize - mBufferedLength;
+                chunk = concat(mBuffered, mBufferedOffset, mBufferedLength,
+                        input, inputOffset, inputBytesInChunk);
+            } else {
+                // All of available input fits into one chunk.
+                if ((mBufferedLength == 0) && (inputOffset == 0)
+                        && (inputLength == input.length)) {
+                    // Nothing buffered and all of input array needs to be fed into the update
+                    // operation.
+                    chunk = input;
+                    inputBytesInChunk = input.length;
+                } else {
+                    // Need to combine buffered data with input data into one array.
+                    inputBytesInChunk = inputLength;
+                    chunk = concat(mBuffered, mBufferedOffset, mBufferedLength,
+                            input, inputOffset, inputBytesInChunk);
+                }
+            }
+            // Update input array references to reflect that some of its bytes are now in mBuffered.
+            inputOffset += inputBytesInChunk;
+            inputLength -= inputBytesInChunk;
+
+            OperationResult opResult = mKeyStoreStream.update(chunk);
+            if (opResult == null) {
+                throw new KeyStoreConnectException();
+            } else if (opResult.resultCode != KeyStore.NO_ERROR) {
+                throw KeyStore.getKeyStoreException(opResult.resultCode);
+            }
+
+            if (opResult.inputConsumed == chunk.length) {
+                // The whole chunk was consumed
+                mBuffered = EMPTY_BYTE_ARRAY;
+                mBufferedOffset = 0;
+                mBufferedLength = 0;
+            } else if (opResult.inputConsumed == 0) {
+                // Nothing was consumed. More input needed.
+                if (inputLength > 0) {
+                    // More input is available, but it wasn't included into the previous chunk
+                    // because the chunk reached its maximum permitted size.
+                    // Shouldn't have happened.
+                    throw new CryptoOperationException("Nothing consumed from max-sized chunk: "
+                            + chunk.length + " bytes");
+                }
+                mBuffered = chunk;
+                mBufferedOffset = 0;
+                mBufferedLength = chunk.length;
+            } else if (opResult.inputConsumed < chunk.length) {
+                // The chunk was consumed only partially -- buffer the rest of the chunk
+                mBuffered = chunk;
+                mBufferedOffset = opResult.inputConsumed;
+                mBufferedLength = chunk.length - opResult.inputConsumed;
+            } else {
+                throw new CryptoOperationException("Consumed more than provided: "
+                        + opResult.inputConsumed + ", provided: " + chunk.length);
+            }
+
+            if ((opResult.output != null) && (opResult.output.length > 0)) {
+                if (inputLength > 0) {
+                    // More output might be produced in this loop -- buffer the current output
+                    if (bufferedOutput == null) {
+                        bufferedOutput = new ByteArrayOutputStream();
+                        try {
+                            bufferedOutput.write(opResult.output);
+                        } catch (IOException e) {
+                            throw new CryptoOperationException("Failed to buffer output", e);
+                        }
+                    }
+                } else {
+                    // No more output will be produced in this loop
+                    if (bufferedOutput == null) {
+                        // No previously buffered output
+                        return opResult.output;
+                    } else {
+                        // There was some previously buffered output
+                        try {
+                            bufferedOutput.write(opResult.output);
+                        } catch (IOException e) {
+                            throw new CryptoOperationException("Failed to buffer output", e);
+                        }
+                        return bufferedOutput.toByteArray();
+                    }
+                }
+            }
+        }
+
+        if (bufferedOutput == null) {
+            // No output produced
+            return EMPTY_BYTE_ARRAY;
+        } else {
+            return bufferedOutput.toByteArray();
+        }
+    }
+
+    public byte[] doFinal(byte[] input, int inputOffset, int inputLength)
+            throws KeyStoreException {
+        if (inputLength == 0) {
+            // No input provided -- simplify the rest of the code
+            input = EMPTY_BYTE_ARRAY;
+            inputOffset = 0;
+        }
+
+        // Flush all buffered input and provided input into keystore/keymaster.
+        byte[] output = update(input, inputOffset, inputLength);
+        output = concat(output, flush());
+
+        OperationResult opResult = mKeyStoreStream.finish();
+        if (opResult == null) {
+            throw new KeyStoreConnectException();
+        } else if (opResult.resultCode != KeyStore.NO_ERROR) {
+            throw KeyStore.getKeyStoreException(opResult.resultCode);
+        }
+
+        return concat(output, opResult.output);
+    }
+
+    /**
+     * Passes all of buffered input into the the KeyStore operation (via the {@code update}
+     * operation) and returns output.
+     */
+    public byte[] flush() throws KeyStoreException {
+        if (mBufferedLength <= 0) {
+            return EMPTY_BYTE_ARRAY;
+        }
+
+        byte[] chunk = subarray(mBuffered, mBufferedOffset, mBufferedLength);
+        mBuffered = EMPTY_BYTE_ARRAY;
+        mBufferedLength = 0;
+        mBufferedOffset = 0;
+
+        OperationResult opResult = mKeyStoreStream.update(chunk);
+        if (opResult == null) {
+            throw new KeyStoreConnectException();
+        } else if (opResult.resultCode != KeyStore.NO_ERROR) {
+            throw KeyStore.getKeyStoreException(opResult.resultCode);
+        }
+
+        if (opResult.inputConsumed < chunk.length) {
+            throw new CryptoOperationException("Keystore failed to consume all input. Provided: "
+                    + chunk.length + ", consumed: " + opResult.inputConsumed);
+        } else if (opResult.inputConsumed > chunk.length) {
+            throw new CryptoOperationException("Keystore consumed more input than provided"
+                    + " . Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed);
+        }
+
+        return (opResult.output != null) ? opResult.output : EMPTY_BYTE_ARRAY;
+    }
+
+    private static byte[] concat(byte[] arr1, byte[] arr2) {
+        if ((arr1 == null) || (arr1.length == 0)) {
+            return arr2;
+        } else if ((arr2 == null) || (arr2.length == 0)) {
+            return arr1;
+        } else {
+            byte[] result = new byte[arr1.length + arr2.length];
+            System.arraycopy(arr1, 0, result, 0, arr1.length);
+            System.arraycopy(arr2, 0, result, arr1.length, arr2.length);
+            return result;
+        }
+    }
+
+    private static byte[] concat(byte[] arr1, int offset1, int len1, byte[] arr2, int offset2,
+            int len2) {
+        if (len1 == 0) {
+            return subarray(arr2, offset2, len2);
+        } else if (len2 == 0) {
+            return subarray(arr1, offset1, len1);
+        } else {
+            byte[] result = new byte[len1 + len2];
+            System.arraycopy(arr1, offset1, result, 0, len1);
+            System.arraycopy(arr2, offset2, result, len1, len2);
+            return result;
+        }
+    }
+
+    private static byte[] subarray(byte[] arr, int offset, int len) {
+        if (len == 0) {
+            return EMPTY_BYTE_ARRAY;
+        }
+        if ((offset == 0) && (len == arr.length)) {
+            return arr;
+        }
+        byte[] result = new byte[len];
+        System.arraycopy(arr, offset, result, 0, len);
+        return result;
+    }
+
+    /**
+     * Main data stream via a KeyStore streaming operation.
+     *
+     * <p>For example, for an encryption operation, this is the stream through which plaintext is
+     * provided and ciphertext is obtained.
+     */
+    public static class MainDataStream implements Stream {
+
+        private final KeyStore mKeyStore;
+        private final IBinder mOperationToken;
+
+        public MainDataStream(KeyStore keyStore, IBinder operationToken) {
+            mKeyStore = keyStore;
+            mOperationToken = operationToken;
+        }
+
+        @Override
+        public OperationResult update(byte[] input) {
+            return mKeyStore.update(mOperationToken, null, input);
+        }
+
+        @Override
+        public OperationResult finish() {
+            return mKeyStore.finish(mOperationToken, null, null);
+        }
+    }
+}
diff --git a/keystore/java/android/security/KeyStoreException.java b/keystore/java/android/security/KeyStoreException.java
new file mode 100644
index 0000000..88e768c
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.security;
+
+/**
+ * KeyStore/keymaster exception with positive error codes coming from the KeyStore and negative
+ * ones from keymaster.
+ *
+ * @hide
+ */
+public class KeyStoreException extends Exception {
+
+    private final int mErrorCode;
+
+    public KeyStoreException(int errorCode, String message) {
+        super(message);
+        mErrorCode = errorCode;
+    }
+
+    public int getErrorCode() {
+        return mErrorCode;
+    }
+}
diff --git a/keystore/java/android/security/KeyStoreHmacSpi.java b/keystore/java/android/security/KeyStoreHmacSpi.java
new file mode 100644
index 0000000..a5864a4
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreHmacSpi.java
@@ -0,0 +1,183 @@
+/*
+ * 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.security;
+
+import android.os.IBinder;
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterDefs;
+import android.security.keymaster.OperationResult;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.MacSpi;
+
+/**
+ * {@link MacSpi} which provides HMAC implementations backed by Android KeyStore.
+ *
+ * @hide
+ */
+public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOperation {
+
+    public static class HmacSHA256 extends KeyStoreHmacSpi {
+        public HmacSHA256() {
+            super(KeyStoreKeyConstraints.Digest.SHA256, 256 / 8);
+        }
+    }
+
+    private final KeyStore mKeyStore = KeyStore.getInstance();
+    private final @KeyStoreKeyConstraints.DigestEnum int mDigest;
+    private final int mMacSizeBytes;
+
+    private String mKeyAliasInKeyStore;
+
+    // The fields below are reset by the engineReset operation.
+    private KeyStoreCryptoOperationChunkedStreamer mChunkedStreamer;
+    private IBinder mOperationToken;
+    private Long mOperationHandle;
+
+    protected KeyStoreHmacSpi(@KeyStoreKeyConstraints.DigestEnum int digest, int macSizeBytes) {
+        mDigest = digest;
+        mMacSizeBytes = macSizeBytes;
+    }
+
+    @Override
+    protected int engineGetMacLength() {
+        return mMacSizeBytes;
+    }
+
+    @Override
+    protected void engineInit(Key key, AlgorithmParameterSpec params) throws InvalidKeyException,
+            InvalidAlgorithmParameterException {
+        if (key == null) {
+            throw new InvalidKeyException("key == null");
+        } else if (!(key instanceof KeyStoreSecretKey)) {
+            throw new InvalidKeyException(
+                    "Only Android KeyStore secret keys supported. Key: " + key);
+        }
+
+        if (params != null) {
+            throw new InvalidAlgorithmParameterException(
+                    "Unsupported algorithm parameters: " + params);
+        }
+
+        mKeyAliasInKeyStore = ((KeyStoreSecretKey) key).getAlias();
+        if (mKeyAliasInKeyStore == null) {
+            throw new InvalidKeyException("Key's KeyStore alias not known");
+        }
+        engineReset();
+        ensureKeystoreOperationInitialized();
+    }
+
+    @Override
+    protected void engineReset() {
+        IBinder operationToken = mOperationToken;
+        if (operationToken != null) {
+            mOperationToken = null;
+            mKeyStore.abort(operationToken);
+        }
+        mOperationHandle = null;
+        mChunkedStreamer = null;
+    }
+
+    private void ensureKeystoreOperationInitialized() {
+        if (mChunkedStreamer != null) {
+            return;
+        }
+        if (mKeyAliasInKeyStore == null) {
+            throw new IllegalStateException("Not initialized");
+        }
+
+        KeymasterArguments keymasterArgs = new KeymasterArguments();
+        keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeyStoreKeyConstraints.Algorithm.HMAC);
+        keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, mDigest);
+
+        OperationResult opResult = mKeyStore.begin(mKeyAliasInKeyStore,
+                KeymasterDefs.KM_PURPOSE_SIGN,
+                true,
+                keymasterArgs,
+                null,
+                new KeymasterArguments());
+        if (opResult == null) {
+            throw new KeyStoreConnectException();
+        } else if (opResult.resultCode != KeyStore.NO_ERROR) {
+            throw KeyStore.getCryptoOperationException(opResult.resultCode);
+        }
+        if (opResult.token == null) {
+            throw new CryptoOperationException("Keystore returned null operation token");
+        }
+        mOperationToken = opResult.token;
+        mOperationHandle = opResult.operationHandle;
+        mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
+                new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
+                        mKeyStore, mOperationToken));
+    }
+
+    @Override
+    protected void engineUpdate(byte input) {
+        engineUpdate(new byte[] {input}, 0, 1);
+    }
+
+    @Override
+    protected void engineUpdate(byte[] input, int offset, int len) {
+        ensureKeystoreOperationInitialized();
+
+        byte[] output;
+        try {
+            output = mChunkedStreamer.update(input, offset, len);
+        } catch (KeyStoreException e) {
+            throw KeyStore.getCryptoOperationException(e);
+        }
+        if ((output != null) && (output.length != 0)) {
+            throw new CryptoOperationException("Update operation unexpectedly produced output");
+        }
+    }
+
+    @Override
+    protected byte[] engineDoFinal() {
+        ensureKeystoreOperationInitialized();
+
+        byte[] result;
+        try {
+            result = mChunkedStreamer.doFinal(null, 0, 0);
+        } catch (KeyStoreException e) {
+            throw KeyStore.getCryptoOperationException(e);
+        }
+
+        engineReset();
+        return result;
+    }
+
+    @Override
+    public void finalize() throws Throwable {
+        try {
+            IBinder operationToken = mOperationToken;
+            if (operationToken != null) {
+                mKeyStore.abort(operationToken);
+            }
+        } finally {
+            super.finalize();
+        }
+    }
+
+    @Override
+    public Long getOperationHandle() {
+        return mOperationHandle;
+    }
+}
diff --git a/keystore/java/android/security/KeyStoreKeyCharacteristics.java b/keystore/java/android/security/KeyStoreKeyCharacteristics.java
new file mode 100644
index 0000000..543b5d8
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreKeyCharacteristics.java
@@ -0,0 +1,68 @@
+/*
+ * 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.security;
+
+import android.annotation.IntDef;
+import android.security.keymaster.KeymasterDefs;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Characteristics of {@code AndroidKeyStore} keys.
+ *
+ * @hide
+ */
+public abstract class KeyStoreKeyCharacteristics {
+    private KeyStoreKeyCharacteristics() {}
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({Origin.GENERATED_INSIDE_TEE, Origin.GENERATED_OUTSIDE_OF_TEE, Origin.IMPORTED})
+    public @interface OriginEnum {}
+
+    /**
+     * Origin of the key.
+     */
+    public static abstract class Origin {
+        private Origin() {}
+
+        /** Key was generated inside a TEE. */
+        public static final int GENERATED_INSIDE_TEE = 1;
+
+        /** Key was generated outside of a TEE. */
+        public static final int GENERATED_OUTSIDE_OF_TEE = 2;
+
+        /** Key was imported. */
+        public static final int IMPORTED = 0;
+
+        /**
+         * @hide
+         */
+        public static @OriginEnum int fromKeymaster(int origin) {
+            switch (origin) {
+                case KeymasterDefs.KM_ORIGIN_HARDWARE:
+                    return GENERATED_INSIDE_TEE;
+                case KeymasterDefs.KM_ORIGIN_SOFTWARE:
+                    return GENERATED_OUTSIDE_OF_TEE;
+                case KeymasterDefs.KM_ORIGIN_IMPORTED:
+                    return IMPORTED;
+                default:
+                    throw new IllegalArgumentException("Unknown origin: " + origin);
+            }
+        }
+    }
+}
diff --git a/keystore/java/android/security/KeyStoreKeyConstraints.java b/keystore/java/android/security/KeyStoreKeyConstraints.java
new file mode 100644
index 0000000..7137a9a
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreKeyConstraints.java
@@ -0,0 +1,707 @@
+/*
+ * 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.security;
+
+import android.annotation.IntDef;
+import android.security.keymaster.KeymasterDefs;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collection;
+import java.util.Locale;
+
+/**
+ * Constraints for {@code AndroidKeyStore} keys.
+ *
+ * @hide
+ */
+public abstract class KeyStoreKeyConstraints {
+    private KeyStoreKeyConstraints() {}
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true,
+            value = {Purpose.ENCRYPT, Purpose.DECRYPT, Purpose.SIGN, Purpose.VERIFY})
+    public @interface PurposeEnum {}
+
+    /**
+     * Purpose of key.
+     */
+    public static abstract class Purpose {
+        private Purpose() {}
+
+        /**
+         * Purpose: encryption.
+         */
+        public static final int ENCRYPT = 1 << 0;
+
+        /**
+         * Purpose: decryption.
+         */
+        public static final int DECRYPT = 1 << 1;
+
+        /**
+         * Purpose: signing.
+         */
+        public static final int SIGN = 1 << 2;
+
+        /**
+         * Purpose: signature verification.
+         */
+        public static final int VERIFY = 1 << 3;
+
+        /**
+         * @hide
+         */
+        public static int toKeymaster(@PurposeEnum int purpose) {
+            switch (purpose) {
+                case ENCRYPT:
+                    return KeymasterDefs.KM_PURPOSE_ENCRYPT;
+                case DECRYPT:
+                    return KeymasterDefs.KM_PURPOSE_DECRYPT;
+                case SIGN:
+                    return KeymasterDefs.KM_PURPOSE_SIGN;
+                case VERIFY:
+                    return KeymasterDefs.KM_PURPOSE_VERIFY;
+                default:
+                    throw new IllegalArgumentException("Unknown purpose: " + purpose);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static @PurposeEnum int fromKeymaster(int purpose) {
+            switch (purpose) {
+                case KeymasterDefs.KM_PURPOSE_ENCRYPT:
+                    return ENCRYPT;
+                case KeymasterDefs.KM_PURPOSE_DECRYPT:
+                    return DECRYPT;
+                case KeymasterDefs.KM_PURPOSE_SIGN:
+                    return SIGN;
+                case KeymasterDefs.KM_PURPOSE_VERIFY:
+                    return VERIFY;
+                default:
+                    throw new IllegalArgumentException("Unknown purpose: " + purpose);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static int[] allToKeymaster(@PurposeEnum int purposes) {
+            int[] result = getSetFlags(purposes);
+            for (int i = 0; i < result.length; i++) {
+                result[i] = toKeymaster(result[i]);
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        public static @PurposeEnum int allFromKeymaster(Collection<Integer> purposes) {
+            @PurposeEnum int result = 0;
+            for (int keymasterPurpose : purposes) {
+                result |= fromKeymaster(keymasterPurpose);
+            }
+            return result;
+        }
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({Algorithm.AES, Algorithm.HMAC})
+    public @interface AlgorithmEnum {}
+
+    /**
+     * Key algorithm.
+     */
+    public static abstract class Algorithm {
+        private Algorithm() {}
+
+        /**
+         * Key algorithm: AES.
+         */
+        public static final int AES = 0;
+
+        /**
+         * Key algorithm: HMAC.
+         */
+        public static final int HMAC = 1;
+
+        /**
+         * @hide
+         */
+        public static int toKeymaster(@AlgorithmEnum int algorithm) {
+            switch (algorithm) {
+                case AES:
+                    return KeymasterDefs.KM_ALGORITHM_AES;
+                case HMAC:
+                    return KeymasterDefs.KM_ALGORITHM_HMAC;
+                default:
+                    throw new IllegalArgumentException("Unknown algorithm: " + algorithm);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static @AlgorithmEnum int fromKeymaster(int algorithm) {
+            switch (algorithm) {
+                case KeymasterDefs.KM_ALGORITHM_AES:
+                    return AES;
+                case KeymasterDefs.KM_ALGORITHM_HMAC:
+                    return HMAC;
+                default:
+                    throw new IllegalArgumentException("Unknown algorithm: " + algorithm);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static String toString(@AlgorithmEnum int algorithm) {
+            switch (algorithm) {
+                case AES:
+                    return "AES";
+                case HMAC:
+                    return "HMAC";
+                default:
+                    throw new IllegalArgumentException("Unknown algorithm: " + algorithm);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static @AlgorithmEnum int fromJCASecretKeyAlgorithm(String algorithm) {
+            if (algorithm == null) {
+                throw new NullPointerException("algorithm == null");
+            } else  if ("AES".equalsIgnoreCase(algorithm)) {
+                return AES;
+            } else if (algorithm.toLowerCase(Locale.US).startsWith("hmac")) {
+                return HMAC;
+            } else {
+                throw new IllegalArgumentException(
+                        "Unsupported secret key algorithm: " + algorithm);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static String toJCASecretKeyAlgorithm(@AlgorithmEnum int algorithm,
+                @DigestEnum Integer digest) {
+            switch (algorithm) {
+                case AES:
+                    return "AES";
+                case HMAC:
+                    if (digest == null) {
+                        throw new IllegalArgumentException("HMAC digest not specified");
+                    }
+                    switch (digest) {
+                        case Digest.SHA256:
+                            return "HmacSHA256";
+                        default:
+                            throw new IllegalArgumentException(
+                                    "Unsupported HMAC digest: " + digest);
+                    }
+                default:
+                    throw new IllegalArgumentException("Unsupported key algorithm: " + algorithm);
+            }
+        }
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true,
+            value = {Padding.NONE, Padding.PKCS7})
+    public @interface PaddingEnum {}
+
+    /**
+     * Padding for signing and encryption.
+     */
+    public static abstract class Padding {
+        private Padding() {}
+
+        /**
+         * No padding.
+         */
+        public static final int NONE = 1 << 0;
+
+        /**
+         * PKCS#7 padding.
+         */
+        public static final int PKCS7 = 1 << 1;
+
+        /**
+         * @hide
+         */
+        public static int toKeymaster(int padding) {
+            switch (padding) {
+                case NONE:
+                    return KeymasterDefs.KM_PAD_NONE;
+                case PKCS7:
+                    return KeymasterDefs.KM_PAD_PKCS7;
+                default:
+                    throw new IllegalArgumentException("Unknown padding: " + padding);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static @PaddingEnum int fromKeymaster(int padding) {
+            switch (padding) {
+                case KeymasterDefs.KM_PAD_NONE:
+                    return NONE;
+                case KeymasterDefs.KM_PAD_PKCS7:
+                    return PKCS7;
+                default:
+                    throw new IllegalArgumentException("Unknown padding: " + padding);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static String toString(@PaddingEnum int padding) {
+            switch (padding) {
+                case NONE:
+                    return "NONE";
+                case PKCS7:
+                    return "PKCS#7";
+                default:
+                    throw new IllegalArgumentException("Unknown padding: " + padding);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static @PaddingEnum int fromJCAPadding(String padding) {
+            String paddingLower = padding.toLowerCase(Locale.US);
+            if ("nopadding".equals(paddingLower)) {
+                return NONE;
+            } else if ("pkcs7padding".equals(paddingLower)) {
+                return PKCS7;
+            } else {
+                throw new IllegalArgumentException("Unknown padding: " + padding);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static int[] allToKeymaster(@PaddingEnum int paddings) {
+            int[] result = getSetFlags(paddings);
+            for (int i = 0; i < result.length; i++) {
+                result[i] = toKeymaster(result[i]);
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        public static @PaddingEnum int allFromKeymaster(Collection<Integer> paddings) {
+            @PaddingEnum int result = 0;
+            for (int keymasterPadding : paddings) {
+                result |= fromKeymaster(keymasterPadding);
+            }
+            return result;
+        }
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true,
+            value = {Digest.NONE, Digest.SHA256})
+    public @interface DigestEnum {}
+
+    /**
+     * Digests that can be used with a key when signing or generating Message Authentication
+     * Codes (MACs).
+     */
+    public static abstract class Digest {
+        private Digest() {}
+
+        /**
+         * No digest: sign/authenticate the raw message.
+         */
+        public static final int NONE = 1 << 0;
+
+        /**
+         * SHA-256 digest.
+         */
+        public static final int SHA256 = 1 << 1;
+
+        /**
+         * @hide
+         */
+        public static String toString(@DigestEnum int digest) {
+            switch (digest) {
+                case NONE:
+                    return "NONE";
+                case SHA256:
+                    return "SHA256";
+                default:
+                    throw new IllegalArgumentException("Unknown digest: " + digest);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static String[] allToString(@DigestEnum int digests) {
+            int[] values = getSetFlags(digests);
+            String[] result = new String[values.length];
+            for (int i = 0; i < values.length; i++) {
+                result[i] = toString(values[i]);
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        public static int toKeymaster(@DigestEnum int digest) {
+            switch (digest) {
+                case NONE:
+                    return KeymasterDefs.KM_DIGEST_NONE;
+                case SHA256:
+                    return KeymasterDefs.KM_DIGEST_SHA_2_256;
+                default:
+                    throw new IllegalArgumentException("Unknown digest: " + digest);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static @DigestEnum int fromKeymaster(int digest) {
+            switch (digest) {
+                case KeymasterDefs.KM_DIGEST_NONE:
+                    return NONE;
+                case KeymasterDefs.KM_DIGEST_SHA_2_256:
+                    return SHA256;
+                default:
+                    throw new IllegalArgumentException("Unknown digest: " + digest);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static int[] allToKeymaster(@DigestEnum int digests) {
+            int[] result = getSetFlags(digests);
+            for (int i = 0; i < result.length; i++) {
+                result[i] = toKeymaster(result[i]);
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        public static @DigestEnum int allFromKeymaster(Collection<Integer> digests) {
+            @DigestEnum int result = 0;
+            for (int keymasterDigest : digests) {
+                result |= fromKeymaster(keymasterDigest);
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        public static @DigestEnum Integer fromJCASecretKeyAlgorithm(String algorithm) {
+            String algorithmLower = algorithm.toLowerCase(Locale.US);
+            if (algorithmLower.startsWith("hmac")) {
+                if ("hmacsha256".equals(algorithmLower)) {
+                    return SHA256;
+                } else {
+                    throw new IllegalArgumentException("Unsupported digest: "
+                            + algorithmLower.substring("hmac".length()));
+                }
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static String toJCASignatureAlgorithmDigest(@DigestEnum int digest) {
+            switch (digest) {
+                case NONE:
+                    return "NONE";
+                case SHA256:
+                    return "SHA256";
+                default:
+                    throw new IllegalArgumentException("Unknown digest: " + digest);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static Integer getOutputSizeBytes(@DigestEnum int digest) {
+            switch (digest) {
+                case NONE:
+                    return null;
+                case SHA256:
+                    return 256 / 8;
+                default:
+                    throw new IllegalArgumentException("Unknown digest: " + digest);
+            }
+        }
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true,
+            value = {BlockMode.ECB, BlockMode.CBC, BlockMode.CTR})
+    public @interface BlockModeEnum {}
+
+    /**
+     * Block modes that can be used when encrypting/decrypting using a key.
+     */
+    public static abstract class BlockMode {
+        private BlockMode() {}
+
+        /** Electronic Codebook (ECB) block mode. */
+        public static final int ECB = 1 << 0;
+
+        /** Cipher Block Chaining (CBC) block mode. */
+        public static final int CBC = 1 << 1;
+
+        /** Counter (CTR) block mode. */
+        public static final int CTR = 1 << 2;
+
+        /**
+         * @hide
+         */
+        public static int toKeymaster(@BlockModeEnum int mode) {
+            switch (mode) {
+                case ECB:
+                    return KeymasterDefs.KM_MODE_ECB;
+                case CBC:
+                    return KeymasterDefs.KM_MODE_CBC;
+                case CTR:
+                    return KeymasterDefs.KM_MODE_CTR;
+                default:
+                    throw new IllegalArgumentException("Unknown block mode: " + mode);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static @BlockModeEnum int fromKeymaster(int mode) {
+            switch (mode) {
+                case KeymasterDefs.KM_MODE_ECB:
+                    return ECB;
+                case KeymasterDefs.KM_MODE_CBC:
+                    return CBC;
+                case KeymasterDefs.KM_MODE_CTR:
+                    return CTR;
+                default:
+                    throw new IllegalArgumentException("Unknown block mode: " + mode);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static int[] allToKeymaster(@BlockModeEnum int modes) {
+            int[] result = getSetFlags(modes);
+            for (int i = 0; i < result.length; i++) {
+                result[i] = toKeymaster(result[i]);
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        public static @BlockModeEnum int allFromKeymaster(Collection<Integer> modes) {
+            @BlockModeEnum int result = 0;
+            for (int keymasterMode : modes) {
+                result |= fromKeymaster(keymasterMode);
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        public static String toString(@BlockModeEnum int mode) {
+            switch (mode) {
+                case ECB:
+                    return "ECB";
+                case CBC:
+                    return "CBC";
+                case CTR:
+                    return "CTR";
+                default:
+                    throw new IllegalArgumentException("Unknown block mode: " + mode);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static @BlockModeEnum int fromJCAMode(String mode) {
+            String modeLower = mode.toLowerCase(Locale.US);
+            if ("ecb".equals(modeLower)) {
+                return ECB;
+            } else if ("cbc".equals(modeLower)) {
+                return CBC;
+            } else if ("ctr".equals(modeLower)) {
+                return CTR;
+            } else {
+                throw new IllegalArgumentException("Unknown block mode: " + mode);
+            }
+        }
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true,
+            value = {UserAuthenticator.LOCK_SCREEN})
+    public @interface UserAuthenticatorEnum {}
+
+    /**
+     * User authenticators which can be used to restrict/protect access to keys.
+     */
+    public static abstract class UserAuthenticator {
+        private UserAuthenticator() {}
+
+        /** Lock screen. */
+        public static final int LOCK_SCREEN = 1 << 0;
+
+        /** Fingerprint reader/sensor. */
+        public static final int FINGERPRINT_READER = 1 << 1;
+
+        /**
+         * @hide
+         */
+        public static int toKeymaster(@UserAuthenticatorEnum int userAuthenticator) {
+            switch (userAuthenticator) {
+                case LOCK_SCREEN:
+                    return KeymasterDefs.HW_AUTH_PASSWORD;
+                case FINGERPRINT_READER:
+                    return KeymasterDefs.HW_AUTH_FINGERPRINT;
+                default:
+                    throw new IllegalArgumentException(
+                            "Unknown user authenticator: " + userAuthenticator);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static @UserAuthenticatorEnum int fromKeymaster(int userAuthenticator) {
+            switch (userAuthenticator) {
+                case KeymasterDefs.HW_AUTH_PASSWORD:
+                    return LOCK_SCREEN;
+                case FINGERPRINT_READER:
+                    return FINGERPRINT_READER;
+                default:
+                    throw new IllegalArgumentException(
+                            "Unknown user authenticator: " + userAuthenticator);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public static int allToKeymaster(@UserAuthenticatorEnum int userAuthenticators) {
+            int result = 0;
+            int userAuthenticator = 1;
+            while (userAuthenticators != 0) {
+                if ((userAuthenticators & 1) != 0) {
+                    result |= toKeymaster(userAuthenticator);
+                }
+                userAuthenticators >>>= 1;
+                userAuthenticator <<= 1;
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        public static @UserAuthenticatorEnum int allFromKeymaster(int userAuthenticators) {
+            @UserAuthenticatorEnum int result = 0;
+            int userAuthenticator = 1;
+            while (userAuthenticators != 0) {
+                if ((userAuthenticators & 1) != 0) {
+                    result |= fromKeymaster(userAuthenticator);
+                }
+                userAuthenticators >>>= 1;
+                userAuthenticator <<= 1;
+            }
+            return result;
+        }
+
+        /**
+         * @hide
+         */
+        public static String toString(@UserAuthenticatorEnum int userAuthenticator) {
+            switch (userAuthenticator) {
+                case LOCK_SCREEN:
+                    return "LOCK_SCREEN";
+                case FINGERPRINT_READER:
+                    return "FINGERPRINT_READER";
+                default:
+                    throw new IllegalArgumentException(
+                            "Unknown user authenticator: " + userAuthenticator);
+            }
+        }
+    }
+
+    private static final int[] EMPTY_INT_ARRAY = new int[0];
+
+    private static int[] getSetFlags(int flags) {
+        if (flags == 0) {
+            return EMPTY_INT_ARRAY;
+        }
+        int result[] = new int[getSetBitCount(flags)];
+        int resultOffset = 0;
+        int flag = 1;
+        while (flags != 0) {
+            if ((flags & 1) != 0) {
+                result[resultOffset] = flag;
+                resultOffset++;
+            }
+            flags >>>= 1;
+            flag <<= 1;
+        }
+        return result;
+    }
+
+    private static int getSetBitCount(int value) {
+        if (value == 0) {
+            return 0;
+        }
+        int result = 0;
+        while (value != 0) {
+            if ((value & 1) != 0) {
+                result++;
+            }
+            value >>>= 1;
+        }
+        return result;
+    }
+}
diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
new file mode 100644
index 0000000..abce32d
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
@@ -0,0 +1,202 @@
+/*
+ * 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.security;
+
+import android.security.keymaster.KeyCharacteristics;
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterDefs;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Date;
+
+import javax.crypto.KeyGeneratorSpi;
+import javax.crypto.SecretKey;
+
+/**
+ * {@link KeyGeneratorSpi} backed by Android KeyStore.
+ *
+ * @hide
+ */
+public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
+
+    public static class AES extends KeyStoreKeyGeneratorSpi {
+        public AES() {
+            super(KeyStoreKeyConstraints.Algorithm.AES, 128);
+        }
+    }
+
+    public static class HmacSHA256 extends KeyStoreKeyGeneratorSpi {
+        public HmacSHA256() {
+            super(KeyStoreKeyConstraints.Algorithm.HMAC,
+                    KeyStoreKeyConstraints.Digest.SHA256,
+                    KeyStoreKeyConstraints.Digest.getOutputSizeBytes(
+                            KeyStoreKeyConstraints.Digest.SHA256) * 8);
+        }
+    }
+
+    private final KeyStore mKeyStore = KeyStore.getInstance();
+    private final @KeyStoreKeyConstraints.AlgorithmEnum int mAlgorithm;
+    private final @KeyStoreKeyConstraints.DigestEnum Integer mDigest;
+    private final int mDefaultKeySizeBits;
+
+    private KeyGeneratorSpec mSpec;
+    private SecureRandom mRng;
+
+    protected KeyStoreKeyGeneratorSpi(
+            @KeyStoreKeyConstraints.AlgorithmEnum int algorithm,
+            int defaultKeySizeBits) {
+        this(algorithm, null, defaultKeySizeBits);
+    }
+
+    protected KeyStoreKeyGeneratorSpi(
+            @KeyStoreKeyConstraints.AlgorithmEnum int algorithm,
+            @KeyStoreKeyConstraints.DigestEnum Integer digest,
+            int defaultKeySizeBits) {
+        mAlgorithm = algorithm;
+        mDigest = digest;
+        mDefaultKeySizeBits = defaultKeySizeBits;
+    }
+
+    @Override
+    protected SecretKey engineGenerateKey() {
+        KeyGeneratorSpec spec = mSpec;
+        if (spec == null) {
+            throw new IllegalStateException("Not initialized");
+        }
+
+        if ((spec.isEncryptionRequired())
+                && (mKeyStore.state() != KeyStore.State.UNLOCKED)) {
+            throw new IllegalStateException(
+                    "Android KeyStore must be in initialized and unlocked state if encryption is"
+                    + " required");
+        }
+
+        KeymasterArguments args = new KeymasterArguments();
+        args.addInt(KeymasterDefs.KM_TAG_ALGORITHM,
+                KeyStoreKeyConstraints.Algorithm.toKeymaster(mAlgorithm));
+        if (mDigest != null) {
+            args.addInt(KeymasterDefs.KM_TAG_DIGEST,
+                    KeyStoreKeyConstraints.Digest.toKeymaster(mDigest));
+            Integer digestOutputSizeBytes =
+                    KeyStoreKeyConstraints.Digest.getOutputSizeBytes(mDigest);
+            if (digestOutputSizeBytes != null) {
+                // TODO: Remove MAC length constraint once Keymaster API no longer requires it.
+                // TODO: Switch to bits instead of bytes, once this is fixed in Keymaster
+                args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, digestOutputSizeBytes);
+            }
+        }
+        if (mAlgorithm == KeyStoreKeyConstraints.Algorithm.HMAC) {
+            if (mDigest == null) {
+                throw new IllegalStateException("Digest algorithm must be specified for key"
+                        + " algorithm " + KeyStoreKeyConstraints.Algorithm.toString(mAlgorithm));
+            }
+        }
+        int keySizeBits = (spec.getKeySize() != null) ? spec.getKeySize() : mDefaultKeySizeBits;
+        args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, keySizeBits);
+        int purposes = spec.getPurposes();
+        for (int keymasterPurpose :
+            KeyStoreKeyConstraints.Purpose.allToKeymaster(purposes)) {
+            args.addInt(KeymasterDefs.KM_TAG_PURPOSE, keymasterPurpose);
+        }
+        for (int keymasterBlockMode :
+            KeyStoreKeyConstraints.BlockMode.allToKeymaster(spec.getBlockModes())) {
+            args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockMode);
+        }
+        for (int keymasterPadding :
+            KeyStoreKeyConstraints.Padding.allToKeymaster(spec.getPaddings())) {
+            args.addInt(KeymasterDefs.KM_TAG_PADDING, keymasterPadding);
+        }
+        if (spec.getUserAuthenticators() == 0) {
+            args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
+        } else {
+            args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
+                    KeyStoreKeyConstraints.UserAuthenticator.allToKeymaster(
+                            spec.getUserAuthenticators()));
+        }
+        if (spec.isInvalidatedOnNewFingerprintEnrolled()) {
+            // TODO: Add the invalidate on fingerprint enrolled constraint once Keymaster supports
+            // that.
+        }
+        if (spec.getUserAuthenticationValidityDurationSeconds() != -1) {
+            args.addInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
+                    spec.getUserAuthenticationValidityDurationSeconds());
+        }
+        args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
+                (spec.getKeyValidityStart() != null)
+                ? spec.getKeyValidityStart() : new Date(0));
+        args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
+                (spec.getKeyValidityForOriginationEnd() != null)
+                ? spec.getKeyValidityForOriginationEnd() : new Date(Long.MAX_VALUE));
+        args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
+                (spec.getKeyValidityForConsumptionEnd() != null)
+                ? spec.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE));
+
+        if (((purposes & KeyStoreKeyConstraints.Purpose.ENCRYPT) != 0)
+            || ((purposes & KeyStoreKeyConstraints.Purpose.DECRYPT) != 0)) {
+            // Permit caller-specified IV. This is needed due to the Cipher abstraction.
+            args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
+        }
+
+        byte[] additionalEntropy = null;
+        SecureRandom rng = mRng;
+        if (rng != null) {
+            additionalEntropy = new byte[(keySizeBits + 7) / 8];
+            rng.nextBytes(additionalEntropy);
+        }
+
+        int flags = spec.getFlags();
+        String keyAliasInKeystore = Credentials.USER_SECRET_KEY + spec.getKeystoreAlias();
+        int errorCode = mKeyStore.generateKey(
+                keyAliasInKeystore, args, additionalEntropy, flags, new KeyCharacteristics());
+        if (errorCode != KeyStore.NO_ERROR) {
+            throw KeyStore.getCryptoOperationException(errorCode);
+        }
+        String keyAlgorithmJCA =
+                KeyStoreKeyConstraints.Algorithm.toJCASecretKeyAlgorithm(mAlgorithm, mDigest);
+        return new KeyStoreSecretKey(keyAliasInKeystore, keyAlgorithmJCA);
+    }
+
+    @Override
+    protected void engineInit(SecureRandom random) {
+        throw new UnsupportedOperationException("Cannot initialize without an "
+                + KeyGeneratorSpec.class.getName() + " parameter");
+    }
+
+    @Override
+    protected void engineInit(AlgorithmParameterSpec params, SecureRandom random)
+            throws InvalidAlgorithmParameterException {
+        if ((params == null) || (!(params instanceof KeyGeneratorSpec))) {
+            throw new InvalidAlgorithmParameterException("Cannot initialize without an "
+                    + KeyGeneratorSpec.class.getName() + " parameter");
+        }
+        KeyGeneratorSpec spec = (KeyGeneratorSpec) params;
+        if (spec.getKeystoreAlias() == null) {
+            throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
+        }
+
+        mSpec = spec;
+        mRng = random;
+    }
+
+    @Override
+    protected void engineInit(int keySize, SecureRandom random) {
+        throw new UnsupportedOperationException("Cannot initialize without a "
+                + KeyGeneratorSpec.class.getName() + " parameter");
+    }
+}
diff --git a/keystore/java/android/security/KeyStoreKeySpec.java b/keystore/java/android/security/KeyStoreKeySpec.java
new file mode 100644
index 0000000..256d9b3
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreKeySpec.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import java.security.spec.KeySpec;
+import java.util.Date;
+
+/**
+ * Information about a key from the <a href="{@docRoot}training/articles/keystore.html">Android
+ * KeyStore</a>.
+ *
+ * @hide
+ */
+public class KeyStoreKeySpec implements KeySpec {
+    private final String mKeystoreAlias;
+    private final int mKeySize;
+    private final @KeyStoreKeyCharacteristics.OriginEnum int mOrigin;
+    private final Date mKeyValidityStart;
+    private final Date mKeyValidityForOriginationEnd;
+    private final Date mKeyValidityForConsumptionEnd;
+    private final @KeyStoreKeyConstraints.PurposeEnum int mPurposes;
+    private final @KeyStoreKeyConstraints.AlgorithmEnum int mAlgorithm;
+    private final @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
+    private final @KeyStoreKeyConstraints.DigestEnum int mDigests;
+    private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+    private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
+    private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mTeeEnforcedUserAuthenticators;
+    private final int mUserAuthenticationValidityDurationSeconds;
+    private final boolean mInvalidatedOnNewFingerprintEnrolled;
+
+    /**
+     * @hide
+     */
+    KeyStoreKeySpec(String keystoreKeyAlias,
+            @KeyStoreKeyCharacteristics.OriginEnum int origin,
+            int keySize,
+            Date keyValidityStart,
+            Date keyValidityForOriginationEnd,
+            Date keyValidityForConsumptionEnd,
+            @KeyStoreKeyConstraints.PurposeEnum int purposes,
+            @KeyStoreKeyConstraints.AlgorithmEnum int algorithm,
+            @KeyStoreKeyConstraints.PaddingEnum int paddings,
+            @KeyStoreKeyConstraints.DigestEnum int digests,
+            @KeyStoreKeyConstraints.BlockModeEnum int blockModes,
+            @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators,
+            @KeyStoreKeyConstraints.UserAuthenticatorEnum int teeEnforcedUserAuthenticators,
+            int userAuthenticationValidityDurationSeconds,
+            boolean invalidatedOnNewFingerprintEnrolled) {
+        mKeystoreAlias = keystoreKeyAlias;
+        mOrigin = origin;
+        mKeySize = keySize;
+        mKeyValidityStart = keyValidityStart;
+        mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
+        mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd;
+        mPurposes = purposes;
+        mAlgorithm = algorithm;
+        mPaddings = paddings;
+        mDigests = digests;
+        mBlockModes = blockModes;
+        mUserAuthenticators = userAuthenticators;
+        mTeeEnforcedUserAuthenticators = teeEnforcedUserAuthenticators;
+        mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
+        mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
+    }
+
+    /**
+     * Gets the entry alias under which the key is stored in the {@code AndroidKeyStore}.
+     */
+    public String getKeystoreAlias() {
+        return mKeystoreAlias;
+    }
+
+    /**
+     * Gets the origin of the key.
+     */
+    public @KeyStoreKeyCharacteristics.OriginEnum int getOrigin() {
+        return mOrigin;
+    }
+
+    /**
+     * Gets the size of the key in bits.
+     */
+    public int getKeySize() {
+        return mKeySize;
+    }
+
+    /**
+     * Gets the time instant before which the key is not yet valid.
+     *
+     * @return instant or {@code null} if not restricted.
+     */
+    public Date getKeyValidityStart() {
+        return mKeyValidityStart;
+    }
+
+    /**
+     * Gets the time instant after which the key is no long valid for decryption and verification.
+     *
+     * @return instant or {@code null} if not restricted.
+     */
+    public Date getKeyValidityForConsumptionEnd() {
+        return mKeyValidityForConsumptionEnd;
+    }
+
+    /**
+     * Gets the time instant after which the key is no long valid for encryption and signing.
+     *
+     * @return instant or {@code null} if not restricted.
+     */
+    public Date getKeyValidityForOriginationEnd() {
+        return mKeyValidityForOriginationEnd;
+    }
+
+    /**
+     * Gets the set of purposes for which the key can be used.
+     */
+    public @KeyStoreKeyConstraints.PurposeEnum int getPurposes() {
+        return mPurposes;
+    }
+
+    /**
+     * Gets the algorithm of the key.
+     */
+    public @KeyStoreKeyConstraints.AlgorithmEnum int getAlgorithm() {
+        return mAlgorithm;
+    }
+
+    /**
+     * Gets the set of block modes with which the key can be used.
+     */
+    public @KeyStoreKeyConstraints.BlockModeEnum int getBlockModes() {
+        return mBlockModes;
+    }
+
+    /**
+     * Gets the set of padding modes with which the key can be used.
+     */
+    public @KeyStoreKeyConstraints.PaddingEnum int getPaddings() {
+        return mPaddings;
+    }
+
+    /**
+     * Gets the set of digest algorithms with which the key can be used.
+     */
+    public @KeyStoreKeyConstraints.DigestEnum int getDigests() {
+        return mDigests;
+    }
+
+    /**
+     * Gets the set of user authenticators which protect access to the key. The key can only be used
+     * iff the user has authenticated to at least one of these user authenticators.
+     *
+     * @return user authenticators or {@code 0} if the key can be used without user authentication.
+     */
+    public @KeyStoreKeyConstraints.UserAuthenticatorEnum int getUserAuthenticators() {
+        return mUserAuthenticators;
+    }
+
+    /**
+     * Gets the set of user authenticators for which the TEE enforces access restrictions for this
+     * key. This is a subset of the user authentications returned by
+     * {@link #getUserAuthenticators()}.
+     */
+    public @KeyStoreKeyConstraints.UserAuthenticatorEnum int getTeeEnforcedUserAuthenticators() {
+        return mTeeEnforcedUserAuthenticators;
+    }
+
+    /**
+     * Gets the duration of time (seconds) for which the key can be used after the user
+     * successfully authenticates to one of the associated user authenticators.
+     *
+     * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
+     *         is required for every use of the key.
+     */
+    public int getUserAuthenticationValidityDurationSeconds() {
+        return mUserAuthenticationValidityDurationSeconds;
+    }
+
+    /**
+     * Returns {@code true} if this key will be permanently invalidated once a new fingerprint is
+     * enrolled. This constraint only has effect if fingerprint reader is one of the user
+     * authenticators protecting access to this key.
+     *
+     * @see #getUserAuthenticators()
+     */
+    public boolean isInvalidatedOnNewFingerprintEnrolled() {
+        return mInvalidatedOnNewFingerprintEnrolled;
+    }
+}
diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java
index 2eeb6ad..0b2f9b6 100644
--- a/keystore/java/android/security/KeyStoreParameter.java
+++ b/keystore/java/android/security/KeyStoreParameter.java
@@ -18,8 +18,10 @@
 
 import android.content.Context;
 
+import java.security.Key;
 import java.security.KeyPairGenerator;
 import java.security.KeyStore.ProtectionParameter;
+import java.util.Date;
 
 /**
  * This provides the optional parameters that can be specified for
@@ -43,9 +45,45 @@
  */
 public final class KeyStoreParameter implements ProtectionParameter {
     private int mFlags;
+    private final Date mKeyValidityStart;
+    private final Date mKeyValidityForOriginationEnd;
+    private final Date mKeyValidityForConsumptionEnd;
+    private final @KeyStoreKeyConstraints.PurposeEnum int mPurposes;
+    private final @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
+    private final @KeyStoreKeyConstraints.DigestEnum Integer mDigests;
+    private final @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+    private final @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
+    private final int mUserAuthenticationValidityDurationSeconds;
+    private final boolean mInvalidatedOnNewFingerprintEnrolled;
 
-    private KeyStoreParameter(int flags) {
+    private KeyStoreParameter(int flags,
+            Date keyValidityStart,
+            Date keyValidityForOriginationEnd,
+            Date keyValidityForConsumptionEnd,
+            @KeyStoreKeyConstraints.PurposeEnum int purposes,
+            @KeyStoreKeyConstraints.PaddingEnum int paddings,
+            @KeyStoreKeyConstraints.DigestEnum Integer digests,
+            @KeyStoreKeyConstraints.BlockModeEnum int blockModes,
+            @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators,
+            int userAuthenticationValidityDurationSeconds,
+            boolean invalidatedOnNewFingerprintEnrolled) {
+        if ((userAuthenticationValidityDurationSeconds < 0)
+                && (userAuthenticationValidityDurationSeconds != -1)) {
+            throw new IllegalArgumentException(
+                    "userAuthenticationValidityDurationSeconds must not be negative");
+        }
+
         mFlags = flags;
+        mKeyValidityStart = keyValidityStart;
+        mKeyValidityForOriginationEnd = keyValidityForOriginationEnd;
+        mKeyValidityForConsumptionEnd = keyValidityForConsumptionEnd;
+        mPurposes = purposes;
+        mPaddings = paddings;
+        mDigests = digests;
+        mBlockModes = blockModes;
+        mUserAuthenticators = userAuthenticators;
+        mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
+        mInvalidatedOnNewFingerprintEnrolled = invalidatedOnNewFingerprintEnrolled;
     }
 
     /**
@@ -64,6 +102,130 @@
     }
 
     /**
+     * Gets the time instant before which the key is not yet valid.
+     *
+     * @return instant or {@code null} if not restricted.
+     * @hide
+     */
+    public Date getKeyValidityStart() {
+        return mKeyValidityStart;
+    }
+
+    /**
+     * Gets the time instant after which the key is no long valid for decryption and verification.
+     *
+     * @return instant or {@code null} if not restricted.
+     *
+     * @hide
+     */
+    public Date getKeyValidityForConsumptionEnd() {
+        return mKeyValidityForConsumptionEnd;
+    }
+
+    /**
+     * Gets the time instant after which the key is no long valid for encryption and signing.
+     *
+     * @return instant or {@code null} if not restricted.
+     *
+     * @hide
+     */
+    public Date getKeyValidityForOriginationEnd() {
+        return mKeyValidityForOriginationEnd;
+    }
+
+    /**
+     * Gets the set of purposes for which the key can be used.
+     *
+     * @hide
+     */
+    public @KeyStoreKeyConstraints.PurposeEnum int getPurposes() {
+        return mPurposes;
+    }
+
+    /**
+     * Gets the set of padding schemes to which the key is restricted.
+     *
+     * @hide
+     */
+    public @KeyStoreKeyConstraints.PaddingEnum int getPaddings() {
+        return mPaddings;
+    }
+
+    /**
+     * Gets the set of digests to which the key is restricted.
+     *
+     * @throws IllegalStateException if this restriction has not been specified.
+     *
+     * @see #isDigestsSpecified()
+     *
+     * @hide
+     */
+    public @KeyStoreKeyConstraints.DigestEnum int getDigests() {
+        if (mDigests == null) {
+            throw new IllegalStateException("Digests not specified");
+        }
+        return mDigests;
+    }
+
+    /**
+     * Returns {@code true} if digest restrictions have been specified.
+     *
+     * @see #getDigests()
+     *
+     * @hide
+     */
+    public boolean isDigestsSpecified() {
+        return mDigests != null;
+    }
+
+    /**
+     * Gets the set of block modes to which the key is restricted.
+     *
+     * @hide
+     */
+    public @KeyStoreKeyConstraints.BlockModeEnum int getBlockModes() {
+        return mBlockModes;
+    }
+
+    /**
+     * Gets the set of user authenticators which protect access to this key. The key can only be
+     * used iff the user has authenticated to at least one of these user authenticators.
+     *
+     * @return user authenticators or {@code 0} if the key can be used without user authentication.
+     *
+     * @hide
+     */
+    public @KeyStoreKeyConstraints.UserAuthenticatorEnum int getUserAuthenticators() {
+        return mUserAuthenticators;
+    }
+
+    /**
+     * Gets the duration of time (seconds) for which this key can be used after the user
+     * successfully authenticates to one of the associated user authenticators.
+     *
+     * @return duration in seconds or {@code -1} if not restricted. {@code 0} means authentication
+     *         is required for every use of the key.
+     *
+     * @hide
+     */
+    public int getUserAuthenticationValidityDurationSeconds() {
+        return mUserAuthenticationValidityDurationSeconds;
+    }
+
+    /**
+     * Returns {@code true} if this key must be permanently invalidated once a new fingerprint is
+     * enrolled. This constraint only has effect if fingerprint reader is one of the user
+     * authenticators protecting access to this key.
+     *
+     * @see #getUserAuthenticators()
+     *
+     * @hide
+     */
+    public boolean isInvalidatedOnNewFingerprintEnrolled() {
+        return mInvalidatedOnNewFingerprintEnrolled;
+    }
+
+    /**
      * Builder class for {@link KeyStoreParameter} objects.
      * <p>
      * This will build protection parameters for use with the
@@ -82,6 +244,16 @@
      */
     public final static class Builder {
         private int mFlags;
+        private Date mKeyValidityStart;
+        private Date mKeyValidityForOriginationEnd;
+        private Date mKeyValidityForConsumptionEnd;
+        private @KeyStoreKeyConstraints.PurposeEnum int mPurposes;
+        private @KeyStoreKeyConstraints.PaddingEnum int mPaddings;
+        private @KeyStoreKeyConstraints.DigestEnum Integer mDigests;
+        private @KeyStoreKeyConstraints.BlockModeEnum int mBlockModes;
+        private @KeyStoreKeyConstraints.UserAuthenticatorEnum int mUserAuthenticators;
+        private int mUserAuthenticationValidityDurationSeconds = -1;
+        private boolean mInvalidatedOnNewFingerprintEnrolled;
 
         /**
          * Creates a new instance of the {@code Builder} with the given
@@ -113,13 +285,189 @@
         }
 
         /**
-         * Builds the instance of the {@code KeyPairGeneratorSpec}.
+         * Sets the time instant before which the key is not yet valid.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityEnd(Date)
+         *
+         * @hide
+         */
+        public Builder setKeyValidityStart(Date startDate) {
+            mKeyValidityStart = startDate;
+            return this;
+        }
+
+        /**
+         * Sets the time instant after which the key is no longer valid.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityStart(Date)
+         * @see #setKeyValidityForConsumptionEnd(Date)
+         * @see #setKeyValidityForOriginationEnd(Date)
+         *
+         * @hide
+         */
+        public Builder setKeyValidityEnd(Date endDate) {
+            setKeyValidityForOriginationEnd(endDate);
+            setKeyValidityForConsumptionEnd(endDate);
+            return this;
+        }
+
+        /**
+         * Sets the time instant after which the key is no longer valid for encryption and signing.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityForConsumptionEnd(Date)
+         *
+         * @hide
+         */
+        public Builder setKeyValidityForOriginationEnd(Date endDate) {
+            mKeyValidityForOriginationEnd = endDate;
+            return this;
+        }
+
+        /**
+         * Sets the time instant after which the key is no longer valid for decryption and
+         * verification.
+         *
+         * <b>By default, the key is valid at any instant.
+         *
+         * @see #setKeyValidityForOriginationEnd(Date)
+         *
+         * @hide
+         */
+        public Builder setKeyValidityForConsumptionEnd(Date endDate) {
+            mKeyValidityForConsumptionEnd = endDate;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only for the provided set of purposes.
+         *
+         * <p>This restriction must be specified. There is no default.
+         *
+         * @hide
+         */
+        public Builder setPurposes(@KeyStoreKeyConstraints.PurposeEnum int purposes) {
+            mPurposes = purposes;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only with the provided padding schemes. Attempts to use
+         * the key with any other padding will be rejected.
+         *
+         * <p>This restriction must be specified for keys which are used for encryption/decryption.
+         *
+         * @hide
+         */
+        public Builder setPaddings(@KeyStoreKeyConstraints.PaddingEnum int paddings) {
+            mPaddings = paddings;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only with the provided digests when generating signatures
+         * or HMACs. Attempts to use the key with any other digest will be rejected.
+         *
+         * <p>For HMAC keys, the default is to restrict to the digest specified in
+         * {@link Key#getAlgorithm()}. For asymmetric signing keys this constraint must be specified
+         * because there is no default.
+         *
+         * @hide
+         */
+        public Builder setDigests(@KeyStoreKeyConstraints.DigestEnum int digests) {
+            mDigests = digests;
+            return this;
+        }
+
+        /**
+         * Restricts the key to being used only with the provided block modes. Attempts to use the
+         * key with any other block modes will be rejected.
+         *
+         * <p>This restriction must be specified for symmetric encryption/decryption keys.
+         *
+         * @hide
+         */
+        public Builder setBlockModes(@KeyStoreKeyConstraints.BlockModeEnum int blockModes) {
+            mBlockModes = blockModes;
+            return this;
+        }
+
+        /**
+         * Sets the user authenticators which protect access to this key. The key can only be used
+         * iff the user has authenticated to at least one of these user authenticators.
+         *
+         * <p>By default, the key can be used without user authentication.
+         *
+         * @param userAuthenticators user authenticators or {@code 0} if this key can be accessed
+         *        without user authentication.
+         *
+         * @see #setUserAuthenticationValidityDurationSeconds(int)
+         *
+         * @hide
+         */
+        public Builder setUserAuthenticators(
+                @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators) {
+            mUserAuthenticators = userAuthenticators;
+            return this;
+        }
+
+        /**
+         * Sets the duration of time (seconds) for which this key can be used after the user
+         * successfully authenticates to one of the associated user authenticators.
+         *
+         * <p>By default, the user needs to authenticate for every use of the key.
+         *
+         * @param seconds duration in seconds or {@code 0} if the user needs to authenticate for
+         *        every use of the key.
+         *
+         * @see #setUserAuthenticators(int)
+         *
+         * @hide
+         */
+        public Builder setUserAuthenticationValidityDurationSeconds(int seconds) {
+            mUserAuthenticationValidityDurationSeconds = seconds;
+            return this;
+        }
+
+        /**
+         * Sets whether this key must be invalidated (permanently) whenever a new fingerprint is
+         * enrolled. This only has effect if fingerprint reader is one of the user authenticators
+         * protecting access to the key.
+         *
+         * <p>By default, enrolling a new fingerprint does not invalidate the key.
+         *
+         * @see #setUserAuthenticators(Set)
+         *
+         * @hide
+         */
+        public Builder setInvalidatedOnNewFingerprintEnrolled(boolean invalidated) {
+            mInvalidatedOnNewFingerprintEnrolled = invalidated;
+            return this;
+        }
+
+        /**
+         * Builds the instance of the {@code KeyStoreParameter}.
          *
          * @throws IllegalArgumentException if a required field is missing
-         * @return built instance of {@code KeyPairGeneratorSpec}
+         * @return built instance of {@code KeyStoreParameter}
          */
         public KeyStoreParameter build() {
-            return new KeyStoreParameter(mFlags);
+            return new KeyStoreParameter(mFlags,
+                    mKeyValidityStart,
+                    mKeyValidityForOriginationEnd,
+                    mKeyValidityForConsumptionEnd,
+                    mPurposes,
+                    mPaddings,
+                    mDigests,
+                    mBlockModes,
+                    mUserAuthenticators,
+                    mUserAuthenticationValidityDurationSeconds,
+                    mInvalidatedOnNewFingerprintEnrolled);
         }
     }
 }
diff --git a/keystore/java/android/security/KeyStoreSecretKey.java b/keystore/java/android/security/KeyStoreSecretKey.java
new file mode 100644
index 0000000..7f0e3d3
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreSecretKey.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import javax.crypto.SecretKey;
+
+/**
+ * {@link SecretKey} backed by keystore.
+ *
+ * @hide
+ */
+public class KeyStoreSecretKey implements SecretKey {
+    private final String mAlias;
+    private final String mAlgorithm;
+
+    public KeyStoreSecretKey(String alias, String algorithm) {
+        mAlias = alias;
+        mAlgorithm = algorithm;
+    }
+
+    String getAlias() {
+        return mAlias;
+    }
+
+    @Override
+    public String getAlgorithm() {
+        return mAlgorithm;
+    }
+
+    @Override
+    public String getFormat() {
+        // This key does not export its key material
+        return null;
+    }
+
+    @Override
+    public byte[] getEncoded() {
+        // This key does not export its key material
+        return null;
+    }
+}
diff --git a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
new file mode 100644
index 0000000..8bf228a
--- /dev/null
+++ b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
@@ -0,0 +1,178 @@
+/*
+ * 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.security;
+
+import android.security.keymaster.KeyCharacteristics;
+import android.security.keymaster.KeymasterDefs;
+
+import java.security.InvalidKeyException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.util.Date;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactorySpi;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * {@link SecretKeyFactorySpi} backed by Android KeyStore.
+ *
+ * @hide
+ */
+public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
+
+    private final KeyStore mKeyStore = KeyStore.getInstance();
+
+    @Override
+    protected KeySpec engineGetKeySpec(SecretKey key,
+            @SuppressWarnings("rawtypes") Class keySpecClass) throws InvalidKeySpecException {
+        if (keySpecClass == null) {
+            throw new InvalidKeySpecException("keySpecClass == null");
+        }
+        if (!(key instanceof KeyStoreSecretKey)) {
+            throw new InvalidKeySpecException("Only Android KeyStore secret keys supported: " +
+                    ((key != null) ? key.getClass().getName() : "null"));
+        }
+        if (SecretKeySpec.class.isAssignableFrom(keySpecClass)) {
+            throw new InvalidKeySpecException(
+                    "Key material export of Android KeyStore keys is not supported");
+        }
+        if (!KeyStoreKeySpec.class.equals(keySpecClass)) {
+            throw new InvalidKeySpecException("Unsupported key spec: " + keySpecClass.getName());
+        }
+        String keyAliasInKeystore = ((KeyStoreSecretKey) key).getAlias();
+        String entryAlias;
+        if (keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)) {
+            entryAlias = keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length());
+        } else {
+            throw new InvalidKeySpecException("Invalid key alias: " + keyAliasInKeystore);
+        }
+
+        KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
+        int errorCode =
+                mKeyStore.getKeyCharacteristics(keyAliasInKeystore, null, null, keyCharacteristics);
+        if (errorCode != KeyStore.NO_ERROR) {
+            throw new InvalidKeySpecException("Failed to obtain information about key."
+                    + " Keystore error: " + errorCode);
+        }
+
+        @KeyStoreKeyCharacteristics.OriginEnum Integer origin;
+        int keySize;
+        @KeyStoreKeyConstraints.PurposeEnum int purposes;
+        @KeyStoreKeyConstraints.AlgorithmEnum int algorithm;
+        @KeyStoreKeyConstraints.PaddingEnum int paddings;
+        @KeyStoreKeyConstraints.DigestEnum int digests;
+        @KeyStoreKeyConstraints.BlockModeEnum int blockModes;
+        @KeyStoreKeyConstraints.UserAuthenticatorEnum int userAuthenticators;
+        @KeyStoreKeyConstraints.UserAuthenticatorEnum int teeEnforcedUserAuthenticators;
+        try {
+            origin = KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_ORIGIN);
+            if (origin == null) {
+                throw new InvalidKeySpecException("Key origin not available");
+            }
+            origin = KeyStoreKeyCharacteristics.Origin.fromKeymaster(origin);
+            Integer keySizeInteger =
+                    KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_KEY_SIZE);
+            if (keySizeInteger == null) {
+                throw new InvalidKeySpecException("Key size not available");
+            }
+            keySize = keySizeInteger;
+            purposes = KeyStoreKeyConstraints.Purpose.allFromKeymaster(
+                    KeymasterUtils.getInts(keyCharacteristics, KeymasterDefs.KM_TAG_PURPOSE));
+            Integer alg = KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_ALGORITHM);
+            if (alg == null) {
+                throw new InvalidKeySpecException("Key algorithm not available");
+            }
+            algorithm = KeyStoreKeyConstraints.Algorithm.fromKeymaster(alg);
+            paddings = KeyStoreKeyConstraints.Padding.allFromKeymaster(
+                    KeymasterUtils.getInts(keyCharacteristics, KeymasterDefs.KM_TAG_PADDING));
+            digests = KeyStoreKeyConstraints.Digest.allFromKeymaster(
+                    KeymasterUtils.getInts(keyCharacteristics, KeymasterDefs.KM_TAG_DIGEST));
+            blockModes = KeyStoreKeyConstraints.BlockMode.allFromKeymaster(
+                    KeymasterUtils.getInts(keyCharacteristics, KeymasterDefs.KM_TAG_BLOCK_MODE));
+
+            @KeyStoreKeyConstraints.UserAuthenticatorEnum
+            int swEnforcedKeymasterUserAuthenticators =
+                    keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
+            @KeyStoreKeyConstraints.UserAuthenticatorEnum
+            int hwEnforcedKeymasterUserAuthenticators =
+                    keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
+            @KeyStoreKeyConstraints.UserAuthenticatorEnum
+            int keymasterUserAuthenticators =
+                    swEnforcedKeymasterUserAuthenticators | hwEnforcedKeymasterUserAuthenticators;
+            userAuthenticators = KeyStoreKeyConstraints.UserAuthenticator.allFromKeymaster(
+                    keymasterUserAuthenticators);
+            teeEnforcedUserAuthenticators =
+                    KeyStoreKeyConstraints.UserAuthenticator.allFromKeymaster(
+                            hwEnforcedKeymasterUserAuthenticators);
+        } catch (IllegalArgumentException e) {
+            throw new InvalidKeySpecException("Unsupported key characteristic", e);
+        }
+
+        Date keyValidityStart =
+                KeymasterUtils.getDate(keyCharacteristics, KeymasterDefs.KM_TAG_ACTIVE_DATETIME);
+        if ((keyValidityStart != null) && (keyValidityStart.getTime() <= 0)) {
+            keyValidityStart = null;
+        }
+        Date keyValidityForOriginationEnd = KeymasterUtils.getDate(keyCharacteristics,
+                KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME);
+        if ((keyValidityForOriginationEnd != null)
+                && (keyValidityForOriginationEnd.getTime() == Long.MAX_VALUE)) {
+            keyValidityForOriginationEnd = null;
+        }
+        Date keyValidityForConsumptionEnd = KeymasterUtils.getDate(keyCharacteristics,
+                KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME);
+        if ((keyValidityForConsumptionEnd != null)
+                && (keyValidityForConsumptionEnd.getTime() == Long.MAX_VALUE)) {
+            keyValidityForConsumptionEnd = null;
+        }
+        Integer userAuthenticationValidityDurationSeconds =
+                KeymasterUtils.getInt(keyCharacteristics, KeymasterDefs.KM_TAG_AUTH_TIMEOUT);
+
+        // TODO: Populate the value below from key characteristics once Keymaster is ready.
+        boolean invalidatedOnNewFingerprintEnrolled = false;
+
+        return new KeyStoreKeySpec(entryAlias,
+                origin,
+                keySize,
+                keyValidityStart,
+                keyValidityForOriginationEnd,
+                keyValidityForConsumptionEnd,
+                purposes,
+                algorithm,
+                paddings,
+                digests,
+                blockModes,
+                userAuthenticators,
+                teeEnforcedUserAuthenticators,
+                ((userAuthenticationValidityDurationSeconds != null)
+                        ? userAuthenticationValidityDurationSeconds : -1),
+                invalidatedOnNewFingerprintEnrolled);
+    }
+
+    @Override
+    protected SecretKey engineGenerateSecret(KeySpec keySpec) throws InvalidKeySpecException {
+        throw new UnsupportedOperationException(
+                "Key import into Android KeyStore is not supported");
+    }
+
+    @Override
+    protected SecretKey engineTranslateKey(SecretKey key) throws InvalidKeyException {
+        throw new UnsupportedOperationException(
+                "Key import into Android KeyStore is not supported");
+    }
+}
diff --git a/keystore/java/android/security/KeymasterUtils.java b/keystore/java/android/security/KeymasterUtils.java
new file mode 100644
index 0000000..3143d4d
--- /dev/null
+++ b/keystore/java/android/security/KeymasterUtils.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 android.security;
+
+import android.security.keymaster.KeyCharacteristics;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @hide
+ */
+public abstract class KeymasterUtils {
+    private KeymasterUtils() {}
+
+    public static Integer getInt(KeyCharacteristics keyCharacteristics, int tag) {
+        if (keyCharacteristics.hwEnforced.containsTag(tag)) {
+            return keyCharacteristics.hwEnforced.getInt(tag, -1);
+        } else if (keyCharacteristics.swEnforced.containsTag(tag)) {
+            return keyCharacteristics.swEnforced.getInt(tag, -1);
+        } else {
+            return null;
+        }
+    }
+
+    public static List<Integer> getInts(KeyCharacteristics keyCharacteristics, int tag) {
+        List<Integer> result = new ArrayList<Integer>();
+        result.addAll(keyCharacteristics.hwEnforced.getInts(tag));
+        result.addAll(keyCharacteristics.swEnforced.getInts(tag));
+        return result;
+    }
+
+    public static Date getDate(KeyCharacteristics keyCharacteristics, int tag) {
+        Date result = keyCharacteristics.hwEnforced.getDate(tag, null);
+        if (result == null) {
+            result = keyCharacteristics.swEnforced.getDate(tag, null);
+        }
+        return result;
+    }
+
+    public static boolean getBoolean(KeyCharacteristics keyCharacteristics, int tag) {
+        if (keyCharacteristics.hwEnforced.containsTag(tag)) {
+            return keyCharacteristics.hwEnforced.getBoolean(tag, false);
+        } else {
+            return keyCharacteristics.swEnforced.getBoolean(tag, false);
+        }
+    }
+}
diff --git a/keystore/java/android/security/NewFingerprintEnrolledException.java b/keystore/java/android/security/NewFingerprintEnrolledException.java
new file mode 100644
index 0000000..6da4a2a
--- /dev/null
+++ b/keystore/java/android/security/NewFingerprintEnrolledException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.security;
+
+/**
+ * Indicates that a cryptographic operation could not be performed because the key used by the
+ * operation is permanently invalid because a new fingerprint was enrolled.
+ *
+ * @hide
+ */
+public class NewFingerprintEnrolledException extends CryptoOperationException {
+
+    /**
+     * Constructs a new {@code NewFingerprintEnrolledException} without detail message and cause.
+     */
+    public NewFingerprintEnrolledException() {
+        super("Invalid key: new fingerprint enrolled");
+    }
+
+    /**
+     * Constructs a new {@code NewFingerprintEnrolledException} with the provided detail message and
+     * no cause.
+     */
+    public NewFingerprintEnrolledException(String message) {
+        super(message);
+    }
+}
diff --git a/keystore/java/android/security/UserNotAuthenticatedException.java b/keystore/java/android/security/UserNotAuthenticatedException.java
new file mode 100644
index 0000000..e6342ef
--- /dev/null
+++ b/keystore/java/android/security/UserNotAuthenticatedException.java
@@ -0,0 +1,49 @@
+/*
+ * 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.security;
+
+/**
+ * Indicates that a cryptographic operation could not be performed because the user has not been
+ * authenticated recently enough.
+ *
+ * @hide
+ */
+public class UserNotAuthenticatedException extends CryptoOperationException {
+
+    /**
+     * Constructs a new {@code UserNotAuthenticatedException} without detail message and cause.
+     */
+    public UserNotAuthenticatedException() {
+        super("User not authenticated");
+    }
+
+    /**
+     * Constructs a new {@code UserNotAuthenticatedException} with the provided detail message and
+     * no cause.
+     */
+    public UserNotAuthenticatedException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new {@code UserNotAuthenticatedException} with the provided detail message and
+     * cause.
+     */
+    public UserNotAuthenticatedException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/keystore/tests/src/android/security/AndroidKeyStoreTest.java b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
index 9775e64..7a88dee 100644
--- a/keystore/tests/src/android/security/AndroidKeyStoreTest.java
+++ b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
@@ -2127,7 +2127,7 @@
         assertEquals("The keystore size should match expected", 2, mKeyStore.size());
         assertAliases(new String[] { TEST_ALIAS_2, TEST_ALIAS_3 });
 
-        assertTrue(mAndroidKeyStore.delKey(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3));
+        assertTrue(mAndroidKeyStore.delete(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3));
 
         assertEquals("The keystore size should match expected", 1, mKeyStore.size());
         assertAliases(new String[] { TEST_ALIAS_2 });
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index f0b07a6..c9a140c 100644
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -25,6 +25,7 @@
 import android.security.keymaster.ExportResult;
 import android.security.keymaster.KeyCharacteristics;
 import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterBlob;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keymaster.OperationResult;
 import android.test.ActivityUnitTestCase;
@@ -711,14 +712,13 @@
         args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
         args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
         args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
+        args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
         args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, 2048);
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_ID, null);
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_DATA, null);
-        args.addBlob(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT,
-                RSAKeyGenParameterSpec.F4.toByteArray());
+        args.addLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT,
+                RSAKeyGenParameterSpec.F4.longValue());
 
         KeyCharacteristics outCharacteristics = new KeyCharacteristics();
-        int result = mKeyStore.generateKey(name, args, 0, outCharacteristics);
+        int result = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
         assertEquals("generateRsaKey should succeed", KeyStore.NO_ERROR, result);
         return outCharacteristics;
     }
@@ -727,6 +727,25 @@
         generateRsaKey("test");
         mKeyStore.delete("test");
     }
+
+    public void testGenerateRsaWithEntropy() throws Exception {
+        byte[] entropy = new byte[] {1,2,3,4,5};
+        String name = "test";
+        KeymasterArguments args = new KeymasterArguments();
+        args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
+        args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
+        args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
+        args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
+        args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
+        args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, 2048);
+        args.addLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT,
+                RSAKeyGenParameterSpec.F4.longValue());
+
+        KeyCharacteristics outCharacteristics = new KeyCharacteristics();
+        int result = mKeyStore.generateKey(name, args, entropy, 0, outCharacteristics);
+        assertEquals("generateKey should succeed", KeyStore.NO_ERROR, result);
+    }
+
     public void testGenerateAndDelete() throws Exception {
         generateRsaKey("test");
         assertTrue("delete should succeed", mKeyStore.delete("test"));
@@ -744,6 +763,7 @@
 
     public void testAppId() throws Exception {
         String name = "test";
+        byte[] id = new byte[] {0x01, 0x02, 0x03};
         KeymasterArguments args = new KeymasterArguments();
         args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
         args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
@@ -751,20 +771,20 @@
         args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
         args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, 2048);
         args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_ID, new byte[] {0x01, 0x02, 0x03});
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_DATA, null);
-        args.addBlob(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT,
-                RSAKeyGenParameterSpec.F4.toByteArray());
+        args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
+        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_ID, id);
+        args.addLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT,
+                RSAKeyGenParameterSpec.F4.longValue());
 
         KeyCharacteristics outCharacteristics = new KeyCharacteristics();
-        int result = mKeyStore.generateKey(name, args, 0, outCharacteristics);
+        int result = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
         assertEquals("generateRsaKey should succeed", KeyStore.NO_ERROR, result);
         assertEquals("getKeyCharacteristics should fail without application ID",
                 KeymasterDefs.KM_ERROR_INVALID_KEY_BLOB,
                 mKeyStore.getKeyCharacteristics(name, null, null, outCharacteristics));
         assertEquals("getKeyCharacteristics should succeed with application ID",
                 KeyStore.NO_ERROR,
-                mKeyStore.getKeyCharacteristics(name, new byte[] {0x01, 0x02, 0x03}, null,
+                mKeyStore.getKeyCharacteristics(name, new KeymasterBlob(id), null,
                     outCharacteristics));
     }
 
@@ -789,19 +809,16 @@
         args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_OCB);
         args.addInt(KeymasterDefs.KM_TAG_CHUNK_LENGTH, 4096);
         args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, 16);
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_ID, null);
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_DATA, null);
+        args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
 
         KeyCharacteristics outCharacteristics = new KeyCharacteristics();
-        int rc = mKeyStore.generateKey(name, args, 0, outCharacteristics);
+        int rc = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
         assertEquals("Generate should succeed", KeyStore.NO_ERROR, rc);
 
         KeymasterArguments out = new KeymasterArguments();
         args = new KeymasterArguments();
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_ID, null);
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_DATA, null);
         OperationResult result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT,
-                true, args, out);
+                true, args, null, out);
         IBinder token = result.token;
         assertEquals("Begin should succeed", KeyStore.NO_ERROR, result.resultCode);
         result = mKeyStore.update(token, null, new byte[] {0x01, 0x02, 0x03, 0x04});
@@ -825,13 +842,14 @@
         args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
         args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, mode);
         args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, size);
+        args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
         return mKeyStore.importKey(name, args, KeymasterDefs.KM_KEY_FORMAT_RAW, key, 0,
                 new KeyCharacteristics());
     }
     private byte[] doOperation(String name, int purpose, byte[] in, KeymasterArguments beginArgs) {
         KeymasterArguments out = new KeymasterArguments();
         OperationResult result = mKeyStore.begin(name, purpose,
-                true, beginArgs, out);
+                true, beginArgs, null, out);
         assertEquals("Begin should succeed", KeyStore.NO_ERROR, result.resultCode);
         IBinder token = result.token;
         result = mKeyStore.update(token, null, in);
@@ -888,28 +906,52 @@
         args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_OCB);
         args.addInt(KeymasterDefs.KM_TAG_CHUNK_LENGTH, 4096);
         args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, 16);
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_ID, null);
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_DATA, null);
+        args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
 
         KeyCharacteristics outCharacteristics = new KeyCharacteristics();
-        int rc = mKeyStore.generateKey(name, args, 0, outCharacteristics);
+        int rc = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
         assertEquals("Generate should succeed", KeyStore.NO_ERROR, rc);
 
         KeymasterArguments out = new KeymasterArguments();
         args = new KeymasterArguments();
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_ID, null);
-        args.addBlob(KeymasterDefs.KM_TAG_APPLICATION_DATA, null);
         OperationResult result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT,
-                true, args, out);
+                true, args, null, out);
         assertEquals("Begin should succeed", KeyStore.NO_ERROR, result.resultCode);
         IBinder first = result.token;
         // Implementation detail: softkeymaster supports 16 concurrent operations
         for (int i = 0; i < 16; i++) {
-            result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT, true, args, out);
+            result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT, true, args, null,
+                    out);
             assertEquals("Begin should succeed", KeyStore.NO_ERROR, result.resultCode);
         }
         // At this point the first operation should be pruned.
         assertEquals("Operation should be pruned", KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE,
                 mKeyStore.update(first, null, new byte[] {0x01}).resultCode);
     }
+
+    public void testAuthNeeded() throws Exception {
+        String name = "test";
+        KeymasterArguments args = new KeymasterArguments();
+        args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
+        args.addInt(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
+        args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
+        args.addInt(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
+        args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, 256);
+        args.addInt(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_OCB);
+        args.addInt(KeymasterDefs.KM_TAG_CHUNK_LENGTH, 4096);
+        args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, 16);
+        args.addInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 1);
+
+        KeyCharacteristics outCharacteristics = new KeyCharacteristics();
+        int rc = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
+        KeymasterArguments out = new KeymasterArguments();
+        assertEquals("Generate should succeed", KeyStore.NO_ERROR, rc);
+        OperationResult result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT,
+                true, args, null, out);
+        assertEquals("Begin should succeed", KeyStore.NO_ERROR, result.resultCode);
+        IBinder token = result.token;
+        result = mKeyStore.update(token, null, new byte[] {0x01, 0x02, 0x03, 0x04});
+        assertEquals("Update should require authorization",
+                KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED, result.resultCode);
+    }
 }
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index 227de3b..9300794 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -478,7 +478,8 @@
 }
 
 int write_tarfile(const String8& packageName, const String8& domain,
-        const String8& rootpath, const String8& filepath, BackupDataWriter* writer)
+        const String8& rootpath, const String8& filepath, off_t* outSize,
+        BackupDataWriter* writer)
 {
     // In the output stream everything is stored relative to the root
     const char* relstart = filepath.string() + rootpath.length();
@@ -488,6 +489,7 @@
     // If relpath is empty, it means this is the top of one of the standard named
     // domain directories, so we should just skip it
     if (relpath.length() == 0) {
+        *outSize = 0;
         return 0;
     }
 
@@ -517,12 +519,25 @@
         return err;
     }
 
+    // very large files need a pax extended size header
+    if (s.st_size > 077777777777LL) {
+        needExtended = true;
+    }
+
     String8 fullname;   // for pax later on
     String8 prefix;
 
     const int isdir = S_ISDIR(s.st_mode);
     if (isdir) s.st_size = 0;   // directories get no actual data in the tar stream
 
+    // Report the size, including a rough tar overhead estimation: 512 bytes for the
+    // overall tar file-block header, plus 2 blocks if using the pax extended format,
+    // plus the raw content size rounded up to a multiple of 512.
+    *outSize = 512 + (needExtended ? 1024 : 0) + 512*((s.st_size + 511)/512);
+
+    // Measure case: we've returned the size; now return without moving data
+    if (!writer) return 0;
+
     // !!! TODO: use mmap when possible to avoid churning the buffer cache
     // !!! TODO: this will break with symlinks; need to use readlink(2)
     int fd = open(filepath.string(), O_RDONLY);
@@ -560,10 +575,6 @@
     snprintf(buf + 116, 8, "0%lo", (unsigned long)s.st_gid);
 
     // [ 124 :  12 ] file size in bytes
-    if (s.st_size > 077777777777LL) {
-        // very large files need a pax extended size header
-        needExtended = true;
-    }
     snprintf(buf + 124, 12, "%011llo", (isdir) ? 0LL : s.st_size);
 
     // [ 136 :  12 ] last mod time as a UTC time_t
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index 852204a..eb520b4 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -234,7 +234,7 @@
 bool ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
     enterRegionMode();
     mClipRegion.op(region, op);
-    setClipRectToRegionBounds();
+    onClipRegionUpdated();
     return true;
 }
 
@@ -263,6 +263,9 @@
 bool ClipArea::rectangleModeClipRectWithTransform(const Rect& r,
         const mat4* transform, SkRegion::Op op) {
 
+    // TODO: we should be able to handle kReplace_Op efficiently without
+    // going through RegionMode and later falling back into RectangleMode.
+
     if (op != SkRegion::kIntersect_Op) {
         enterRegionMode();
         return regionModeClipRectWithTransform(r, transform, op);
@@ -324,15 +327,16 @@
  */
 
 void ClipArea::enterRegionMode() {
-    if (mMode != kModeRegion) {
-        if (mMode == kModeRectangle) {
+    Mode oldMode = mMode;
+    mMode = kModeRegion;
+    if (oldMode != kModeRegion) {
+        if (oldMode == kModeRectangle) {
             mClipRegion.setRect(mClipRect.left, mClipRect.top,
                     mClipRect.right, mClipRect.bottom);
         } else {
             mClipRegion = mRectangleList.convertToRegion(createViewportRegion());
-            setClipRectToRegionBounds();
+            onClipRegionUpdated();
         }
-        mMode = kModeRegion;
     }
 }
 
@@ -342,7 +346,7 @@
     SkRegion transformedRectRegion;
     regionFromPath(transformedRect, transformedRectRegion);
     mClipRegion.op(transformedRectRegion, op);
-    setClipRectToRegionBounds();
+    onClipRegionUpdated();
     return true;
 }
 
@@ -352,12 +356,13 @@
             transform, op);
 }
 
-void ClipArea::setClipRectToRegionBounds() {
+void ClipArea::onClipRegionUpdated() {
     if (!mClipRegion.isEmpty()) {
         mClipRect.set(mClipRegion.getBounds());
 
         if (mClipRegion.isRect()) {
             mClipRegion.setEmpty();
+            enterRectangleMode();
         }
     } else {
         mClipRect.setEmpty();
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index 16e6df9..e284af0 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -144,7 +144,7 @@
             float bottom, const mat4* transform, SkRegion::Op op);
 
     void ensureClipRegion();
-    void setClipRectToRegionBounds();
+    void onClipRegionUpdated();
     bool clipRegionOp(float left, float top, float right, float bottom,
             SkRegion::Op op);
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 2a673f4..8757e15 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -484,7 +484,7 @@
 }
 
 void DisplayListRenderer::setDrawFilter(SkDrawFilter* filter) {
-    mDrawFilter.reset(filter);
+    mDrawFilter.reset(SkSafeRef(filter));
 }
 
 void DisplayListRenderer::insertReorderBarrier(bool enableReorder) {
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 48ecd69..53fd1ad 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -296,8 +296,9 @@
         // so that we don't need to modify the paint every time we access it.
         SkTLazy<SkPaint> filteredPaint;
         if (mDrawFilter.get()) {
-            paint = filteredPaint.init();
+            filteredPaint.set(*paint);
             mDrawFilter->filter(filteredPaint.get(), SkDrawFilter::kPaint_Type);
+            paint = filteredPaint.get();
         }
 
         // compute the hash key for the paint and check the cache.
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 6bef7c7..56380db 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -46,51 +46,11 @@
 // blur inputs smaller than this constant will bypass renderscript
 #define RS_MIN_INPUT_CUTOFF 10000
 
-#define USE_GLOPS true
-
 ///////////////////////////////////////////////////////////////////////////////
 // TextSetupFunctor
 ///////////////////////////////////////////////////////////////////////////////
-void TextSetupFunctor::setup(GLenum glyphFormat) {
-    renderer->setupDraw();
-    renderer->setupDrawTextGamma(paint);
-    renderer->setupDrawDirtyRegionsDisabled();
-    renderer->setupDrawWithTexture(glyphFormat == GL_ALPHA);
-    switch (glyphFormat) {
-        case GL_ALPHA: {
-            renderer->setupDrawAlpha8Color(paint->getColor(), alpha);
-            break;
-        }
-        case GL_RGBA: {
-            float floatAlpha = alpha / 255.0f;
-            renderer->setupDrawColor(floatAlpha, floatAlpha, floatAlpha, floatAlpha);
-            break;
-        }
-        default: {
-#if DEBUG_FONT_RENDERER
-            ALOGD("TextSetupFunctor: called with unknown glyph format %x", glyphFormat);
-#endif
-            break;
-        }
-    }
-    renderer->setupDrawColorFilter(paint->getColorFilter());
-    renderer->setupDrawShader(paint->getShader());
-    renderer->setupDrawBlending(paint);
-    renderer->setupDrawProgram();
-    renderer->setupDrawModelView(kModelViewMode_Translate, false,
-            0.0f, 0.0f, 0.0f, 0.0f, pureTranslate);
-    // Calling setupDrawTexture with the name 0 will enable the
-    // uv attributes and increase the texture unit count
-    // texture binding will be performed by the font renderer as
-    // needed
-    renderer->setupDrawTexture(0);
-    renderer->setupDrawPureColorUniforms();
-    renderer->setupDrawColorFilterUniforms(paint->getColorFilter());
-    renderer->setupDrawShaderUniforms(paint->getShader(), pureTranslate);
-    renderer->setupDrawTextGammaUniforms();
-}
 
-void TextSetupFunctor::draw(CacheTexture& texture, bool linearFiltering) {
+void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) {
     int textureFillFlags = static_cast<int>(texture.getFormat() == GL_ALPHA
             ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
     if (linearFiltering) {
@@ -508,11 +468,6 @@
 void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) {
     if (!mFunctor) return;
 
-#if !USE_GLOPS
-    Caches& caches = mFunctor->renderer->getCaches();
-    RenderState& renderState = mFunctor->renderer->renderState();
-#endif
-
     bool first = true;
     bool forceRebind = false;
     for (uint32_t i = 0; i < cacheTextures.size(); i++) {
@@ -520,37 +475,12 @@
         if (texture->canDraw()) {
             if (first) {
                 checkTextureUpdate();
-#if !USE_GLOPS
-                mFunctor->setup(texture->getFormat());
-
-                renderState.meshState().bindQuadIndicesBuffer();
-
-                // If returns true, a VBO was bound and we must
-                // rebind our vertex attrib pointers even if
-                // they have the same values as the current pointers
-                forceRebind = renderState.meshState().unbindMeshBuffer();
-
-                caches.textureState().activateTexture(0);
-#endif
                 first = false;
                 mDrawn = true;
             }
-#if USE_GLOPS
+
             mFunctor->draw(*texture, mLinearFiltering);
-#endif
 
-#if !USE_GLOPS
-            caches.textureState().bindTexture(texture->getTextureId());
-            texture->setLinearFiltering(mLinearFiltering);
-
-            TextureVertex* mesh = texture->mesh();
-            MeshState& meshState = renderState.meshState();
-            meshState.bindPositionVertexPointer(forceRebind, &mesh[0].x);
-            meshState.bindTexCoordsVertexPointer(forceRebind, &mesh[0].u);
-
-            glDrawElements(GL_TRIANGLES, texture->meshElementCount(),
-                    GL_UNSIGNED_SHORT, texture->indices());
-#endif
             texture->resetMesh();
             forceRebind = false;
         }
@@ -689,7 +619,7 @@
     return image;
 }
 
-void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor) {
+void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor) {
     checkInit();
 
     mDrawn = false;
@@ -717,7 +647,7 @@
 
 bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const char *text,
         uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y,
-        const float* positions, Rect* bounds, TextSetupFunctor* functor, bool forceFinish) {
+        const float* positions, Rect* bounds, TextDrawFunctor* functor, bool forceFinish) {
     if (!mCurrentFont) {
         ALOGE("No font set");
         return false;
@@ -735,7 +665,7 @@
 
 bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text,
         uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path,
-        float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor) {
+        float hOffset, float vOffset, Rect* bounds, TextDrawFunctor* functor) {
     if (!mCurrentFont) {
         ALOGE("No font set");
         return false;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 0603389..dfb107c 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -46,9 +46,9 @@
 
 class OpenGLRenderer;
 
-class TextSetupFunctor {
+class TextDrawFunctor {
 public:
-    TextSetupFunctor(OpenGLRenderer* renderer, float x, float y, bool pureTranslate,
+    TextDrawFunctor(OpenGLRenderer* renderer, float x, float y, bool pureTranslate,
             int alpha, SkXfermode::Mode mode, const SkPaint* paint)
         : renderer(renderer)
         , x(x)
@@ -59,8 +59,6 @@
         , paint(paint) {
     }
 
-    void setup(GLenum glyphFormat);
-
     void draw(CacheTexture& texture, bool linearFiltering);
 
     OpenGLRenderer* renderer;
@@ -92,12 +90,12 @@
     // bounds is an out parameter
     bool renderPosText(const SkPaint* paint, const Rect* clip, const char *text,
             uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions,
-            Rect* bounds, TextSetupFunctor* functor, bool forceFinish = true);
+            Rect* bounds, TextDrawFunctor* functor, bool forceFinish = true);
 
     // bounds is an out parameter
     bool renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text,
             uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path,
-            float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor);
+            float hOffset, float vOffset, Rect* bounds, TextDrawFunctor* functor);
 
     struct DropShadow {
         uint32_t width;
@@ -135,7 +133,7 @@
     void flushAllAndInvalidate();
 
     void checkInit();
-    void initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor);
+    void initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor);
     void finishRender();
 
     void issueDrawCommand(Vector<CacheTexture*>& cacheTextures);
@@ -176,7 +174,7 @@
 
     bool mUploadTexture;
 
-    TextSetupFunctor* mFunctor;
+    TextDrawFunctor* mFunctor;
     const Rect* mClip;
     Rect* mBounds;
     bool mDrawn;
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 0a46014..9ca6bc6 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -586,6 +586,12 @@
     mDescription.hasColors = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kColor;
     mDescription.hasVertexAlpha = mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::kAlpha;
 
+    // Enable debug highlight when what we're about to draw is tested against
+    // the stencil buffer and if stencil highlight debugging is on
+    mDescription.hasDebugHighlight = !mCaches.debugOverdraw
+            && mCaches.debugStencilClip == Caches::kStencilShowHighlight
+            && mRenderState.stencil().isTestEnabled();
+
     // serialize shader info into ShaderData
     GLuint textureUnit = mOutGlop->fill.texture.texture ? 1 : 0;
     SkiaShader::store(mCaches, mShader, mOutGlop->transform.modelView,
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 7df61f27..65be9e1 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -16,8 +16,12 @@
 #include "JankTracker.h"
 
 #include <algorithm>
+#include <cutils/ashmem.h>
+#include <cutils/log.h>
 #include <cstdio>
+#include <errno.h>
 #include <inttypes.h>
+#include <sys/mman.h>
 
 namespace android {
 namespace uirenderer {
@@ -63,11 +67,114 @@
         = FrameInfoFlags::kWindowLayoutChanged
         | FrameInfoFlags::kSurfaceCanvas;
 
+// The bucketing algorithm controls so to speak
+// If a frame is <= to this it goes in bucket 0
+static const uint32_t kBucketMinThreshold = 7;
+// If a frame is > this, start counting in increments of 2ms
+static const uint32_t kBucket2msIntervals = 32;
+// If a frame is > this, start counting in increments of 4ms
+static const uint32_t kBucket4msIntervals = 48;
+
+// This will be called every frame, performance sensitive
+// Uses bit twiddling to avoid branching while achieving the packing desired
+static uint32_t frameCountIndexForFrameTime(nsecs_t frameTime, uint32_t max) {
+    uint32_t index = static_cast<uint32_t>(ns2ms(frameTime));
+    // If index > kBucketMinThreshold mask will be 0xFFFFFFFF as a result
+    // of negating 1 (twos compliment, yaay) else mask will be 0
+    uint32_t mask = -(index > kBucketMinThreshold);
+    // If index > threshold, this will essentially perform:
+    // amountAboveThreshold = index - threshold;
+    // index = threshold + (amountAboveThreshold / 2)
+    // However if index is <= this will do nothing. It will underflow, do
+    // a right shift by 0 (no-op), then overflow back to the original value
+    index = ((index - kBucket4msIntervals) >> (index > kBucket4msIntervals))
+            + kBucket4msIntervals;
+    index = ((index - kBucket2msIntervals) >> (index > kBucket2msIntervals))
+            + kBucket2msIntervals;
+    // If index was < minThreshold at the start of all this it's going to
+    // be a pretty garbage value right now. However, mask is 0 so we'll end
+    // up with the desired result of 0.
+    index = (index - kBucketMinThreshold) & mask;
+    return index < max ? index : max;
+}
+
+// Only called when dumping stats, less performance sensitive
+static uint32_t frameTimeForFrameCountIndex(uint32_t index) {
+    index = index + kBucketMinThreshold;
+    if (index > kBucket2msIntervals) {
+        index += (index - kBucket2msIntervals);
+    }
+    if (index > kBucket4msIntervals) {
+        // This works because it was already doubled by the above if
+        // 1 is added to shift slightly more towards the middle of the bucket
+        index += (index - kBucket4msIntervals) + 1;
+    }
+    return index;
+}
+
 JankTracker::JankTracker(nsecs_t frameIntervalNanos) {
+    // By default this will use malloc memory. It may be moved later to ashmem
+    // if there is shared space for it and a request comes in to do that.
+    mData = new ProfileData;
     reset();
     setFrameInterval(frameIntervalNanos);
 }
 
+JankTracker::~JankTracker() {
+    freeData();
+}
+
+void JankTracker::freeData() {
+    if (mIsMapped) {
+        munmap(mData, sizeof(ProfileData));
+    } else {
+        delete mData;
+    }
+    mIsMapped = false;
+    mData = nullptr;
+}
+
+void JankTracker::switchStorageToAshmem(int ashmemfd) {
+    int regionSize = ashmem_get_size_region(ashmemfd);
+    if (regionSize < static_cast<int>(sizeof(ProfileData))) {
+        ALOGW("Ashmem region is too small! Received %d, required %u",
+                regionSize, static_cast<unsigned int>(sizeof(ProfileData)));
+        return;
+    }
+    ProfileData* newData = reinterpret_cast<ProfileData*>(
+            mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE,
+            MAP_SHARED, ashmemfd, 0));
+    if (newData == MAP_FAILED) {
+        int err = errno;
+        ALOGW("Failed to move profile data to ashmem fd %d, error = %d",
+                ashmemfd, err);
+        return;
+    }
+
+    // The new buffer may have historical data that we want to build on top of
+    // But let's make sure we don't overflow Just In Case
+    uint32_t divider = 0;
+    if (newData->totalFrameCount > (1 << 24)) {
+        divider = 4;
+    }
+    for (size_t i = 0; i < mData->jankTypeCounts.size(); i++) {
+        newData->jankTypeCounts[i] >>= divider;
+        newData->jankTypeCounts[i] += mData->jankTypeCounts[i];
+    }
+    for (size_t i = 0; i < mData->frameCounts.size(); i++) {
+        newData->frameCounts[i] >>= divider;
+        newData->frameCounts[i] += mData->frameCounts[i];
+    }
+    newData->jankFrameCount >>= divider;
+    newData->jankFrameCount += mData->jankFrameCount;
+    newData->totalFrameCount >>= divider;
+    newData->totalFrameCount += mData->totalFrameCount;
+
+    freeData();
+    mData = newData;
+    mIsMapped = true;
+}
+
 void JankTracker::setFrameInterval(nsecs_t frameInterval) {
     mFrameInterval = frameInterval;
     mThresholds[kMissedVsync] = 1;
@@ -92,16 +199,15 @@
 }
 
 void JankTracker::addFrame(const FrameInfo& frame) {
-    mTotalFrameCount++;
+    mData->totalFrameCount++;
     // Fast-path for jank-free frames
     int64_t totalDuration =
             frame[FrameInfoIndex::kFrameCompleted] - frame[FrameInfoIndex::kIntendedVsync];
-    uint32_t framebucket = std::min(
-            static_cast<typeof mFrameCounts.size()>(ns2ms(totalDuration)),
-            mFrameCounts.size());
+    uint32_t framebucket = frameCountIndexForFrameTime(
+            totalDuration, mData->frameCounts.size());
     // Keep the fast path as fast as possible.
     if (CC_LIKELY(totalDuration < mFrameInterval)) {
-        mFrameCounts[framebucket]++;
+        mData->frameCounts[framebucket]++;
         return;
     }
 
@@ -109,47 +215,52 @@
         return;
     }
 
-    mFrameCounts[framebucket]++;
-    mJankFrameCount++;
+    mData->frameCounts[framebucket]++;
+    mData->jankFrameCount++;
 
     for (int i = 0; i < NUM_BUCKETS; i++) {
         int64_t delta = frame[COMPARISONS[i].end] - frame[COMPARISONS[i].start];
         if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) {
-            mBuckets[i].count++;
+            mData->jankTypeCounts[i]++;
         }
     }
 }
 
-void JankTracker::dump(int fd) {
-    FILE* file = fdopen(fd, "a");
-    fprintf(file, "\nFrame stats:");
-    fprintf(file, "\n  Total frames rendered: %u", mTotalFrameCount);
-    fprintf(file, "\n  Janky frames: %u (%.2f%%)", mJankFrameCount,
-            (float) mJankFrameCount / (float) mTotalFrameCount * 100.0f);
-    fprintf(file, "\n  90th percentile: %ums", findPercentile(90));
-    fprintf(file, "\n  95th percentile: %ums", findPercentile(95));
-    fprintf(file, "\n  99th percentile: %ums", findPercentile(99));
-    for (int i = 0; i < NUM_BUCKETS; i++) {
-        fprintf(file, "\n   Number %s: %u", JANK_TYPE_NAMES[i], mBuckets[i].count);
+void JankTracker::dumpBuffer(const void* buffer, size_t bufsize, int fd) {
+    if (bufsize < sizeof(ProfileData)) {
+        return;
     }
-    fprintf(file, "\n");
-    fflush(file);
+    const ProfileData* data = reinterpret_cast<const ProfileData*>(buffer);
+    dumpData(data, fd);
+}
+
+void JankTracker::dumpData(const ProfileData* data, int fd) {
+    dprintf(fd, "\nTotal frames rendered: %u", data->totalFrameCount);
+    dprintf(fd, "\nJanky frames: %u (%.2f%%)", data->jankFrameCount,
+            (float) data->jankFrameCount / (float) data->totalFrameCount * 100.0f);
+    dprintf(fd, "\n90th percentile: %ums", findPercentile(data, 90));
+    dprintf(fd, "\n95th percentile: %ums", findPercentile(data, 95));
+    dprintf(fd, "\n99th percentile: %ums", findPercentile(data, 99));
+    for (int i = 0; i < NUM_BUCKETS; i++) {
+        dprintf(fd, "\nNumber %s: %u", JANK_TYPE_NAMES[i], data->jankTypeCounts[i]);
+    }
+    dprintf(fd, "\n");
 }
 
 void JankTracker::reset() {
-    mBuckets.fill({0});
-    mFrameCounts.fill(0);
-    mTotalFrameCount = 0;
-    mJankFrameCount = 0;
+    mData->jankTypeCounts.fill(0);
+    mData->frameCounts.fill(0);
+    mData->totalFrameCount = 0;
+    mData->jankFrameCount = 0;
 }
 
-uint32_t JankTracker::findPercentile(int percentile) {
-    int pos = percentile * mTotalFrameCount / 100;
-    int remaining = mTotalFrameCount - pos;
-    for (int i = mFrameCounts.size() - 1; i >= 0; i--) {
-        remaining -= mFrameCounts[i];
+uint32_t JankTracker::findPercentile(const ProfileData* data, int percentile) {
+    int pos = percentile * data->totalFrameCount / 100;
+    int remaining = data->totalFrameCount - pos;
+    for (int i = data->frameCounts.size() - 1; i >= 0; i--) {
+        remaining -= data->frameCounts[i];
         if (remaining <= 0) {
-            return i;
+            return frameTimeForFrameCountIndex(i);
         }
     }
     return 0;
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index ae339ec..4783001 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -20,6 +20,8 @@
 #include "renderthread/TimeLord.h"
 #include "utils/RingBuffer.h"
 
+#include <cutils/compiler.h>
+
 #include <array>
 #include <memory>
 
@@ -37,33 +39,45 @@
     NUM_BUCKETS,
 };
 
-struct JankBucket {
-    // Number of frames that hit this bucket
-    uint32_t count;
+// Try to keep as small as possible, should match ASHMEM_SIZE in
+// GraphicsStatsService.java
+struct ProfileData {
+    std::array<uint32_t, NUM_BUCKETS> jankTypeCounts;
+    // See comments on kBucket* constants for what this holds
+    std::array<uint32_t, 57> frameCounts;
+
+    uint32_t totalFrameCount;
+    uint32_t jankFrameCount;
 };
 
 // TODO: Replace DrawProfiler with this
 class JankTracker {
 public:
     JankTracker(nsecs_t frameIntervalNanos);
-
-    void setFrameInterval(nsecs_t frameIntervalNanos);
+    ~JankTracker();
 
     void addFrame(const FrameInfo& frame);
 
-    void dump(int fd);
+    void dump(int fd) { dumpData(mData, fd); }
     void reset();
 
+    void switchStorageToAshmem(int ashmemfd);
+
+    uint32_t findPercentile(int p) { return findPercentile(mData, p); }
+
+    ANDROID_API static void dumpBuffer(const void* buffer, size_t bufsize, int fd);
+
 private:
-    uint32_t findPercentile(int p);
+    void freeData();
+    void setFrameInterval(nsecs_t frameIntervalNanos);
 
-    std::array<JankBucket, NUM_BUCKETS> mBuckets;
+    static uint32_t findPercentile(const ProfileData* data, int p);
+    static void dumpData(const ProfileData* data, int fd);
+
     std::array<int64_t, NUM_BUCKETS> mThresholds;
-    std::array<uint32_t, 128> mFrameCounts;
-
     int64_t mFrameInterval;
-    uint32_t mTotalFrameCount;
-    uint32_t mJankFrameCount;
+    ProfileData* mData;
+    bool mIsMapped = false;
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 3781969..aa722d0 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -57,8 +57,6 @@
     #define EVENT_LOGD(...)
 #endif
 
-#define USE_GLOPS true
-
 namespace android {
 namespace uirenderer {
 
@@ -82,8 +80,6 @@
     // *set* draw modifiers to be 0
     memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
     mDrawModifiers.mOverrideLayerAlpha = 1.0f;
-
-    memcpy(mMeshVertices, kUnitQuadVertices, sizeof(kUnitQuadVertices));
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
@@ -846,122 +842,42 @@
 }
 
 void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
-    if (USE_GLOPS) {
-        bool snap = !layer->getForceFilter()
-                && layer->getWidth() == (uint32_t) rect.getWidth()
-                && layer->getHeight() == (uint32_t) rect.getHeight();
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
-                .setFillTextureLayer(*layer, getLayerAlpha(layer))
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewMapUnitToRectOptionalSnap(snap, rect)
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-    }
-
-    float alpha = getLayerAlpha(layer);
-    setupDraw();
-    if (layer->getRenderTarget() == GL_TEXTURE_2D) {
-        setupDrawWithTexture();
-    } else {
-        setupDrawWithExternalTexture();
-    }
-    setupDrawTextureTransform();
-    setupDrawColor(alpha, alpha, alpha, alpha);
-    setupDrawColorFilter(layer->getColorFilter());
-    setupDrawBlending(layer);
-    setupDrawProgram();
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(layer->getColorFilter());
-    if (layer->getRenderTarget() == GL_TEXTURE_2D) {
-        setupDrawTexture(layer->getTextureId());
-    } else {
-        setupDrawExternalTexture(layer->getTextureId());
-    }
-    if (currentTransform()->isPureTranslate()
-            && !layer->getForceFilter()
+    bool snap = !layer->getForceFilter()
             && layer->getWidth() == (uint32_t) rect.getWidth()
-            && layer->getHeight() == (uint32_t) rect.getHeight()) {
-        const float x = floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
-        const float y = floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
-
-        layer->setFilter(GL_NEAREST);
-        setupDrawModelView(kModelViewMode_TranslateAndScale, false,
-                x, y, x + rect.getWidth(), y + rect.getHeight(), true);
-    } else {
-        layer->setFilter(GL_LINEAR);
-        setupDrawModelView(kModelViewMode_TranslateAndScale, false,
-                rect.left, rect.top, rect.right, rect.bottom);
-    }
-    setupDrawTextureTransformUniforms(layer->getTexTransform());
-    setupDrawMesh(&mMeshVertices[0].x, &mMeshVertices[0].u);
-
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
+            && layer->getHeight() == (uint32_t) rect.getHeight();
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
+            .setFillTextureLayer(*layer, getLayerAlpha(layer))
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewMapUnitToRectOptionalSnap(snap, rect)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
     if (layer->isTextureLayer()) {
         EVENT_LOGD("composeTextureLayerRect");
-        resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
         drawTextureLayer(layer, rect);
-        resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
     } else {
         EVENT_LOGD("composeHardwareLayerRect");
 
-        if (USE_GLOPS) {
-            Blend::ModeOrderSwap modeUsage = swap ?
-                    Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap;
-            const Matrix4& transform = swap ? Matrix4::identity() : *currentTransform();
-            bool snap = !swap
-                    && layer->getWidth() == static_cast<uint32_t>(rect.getWidth())
-                    && layer->getHeight() == static_cast<uint32_t>(rect.getHeight());
-            Glop glop;
-            GlopBuilder(mRenderState, mCaches, &glop)
-                    .setMeshTexturedUvQuad(nullptr, layer->texCoords)
-                    .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), modeUsage)
-                    .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
-                    .setModelViewMapUnitToRectOptionalSnap(snap, rect)
-                    .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                    .build();
-            renderGlop(glop);
-            return;
-        }
-
-        const Rect& texCoords = layer->texCoords;
-        resetDrawTextureTexCoords(texCoords.left, texCoords.top,
-                texCoords.right, texCoords.bottom);
-
-        float x = rect.left;
-        float y = rect.top;
-        bool simpleTransform = currentTransform()->isPureTranslate()
-                && layer->getWidth() == (uint32_t) rect.getWidth()
-                && layer->getHeight() == (uint32_t) rect.getHeight();
-
-        if (simpleTransform) {
-            // When we're swapping, the layer is already in screen coordinates
-            if (!swap) {
-                x = floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
-                y = floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
-            }
-
-            layer->setFilter(GL_NEAREST, true);
-        } else {
-            layer->setFilter(GL_LINEAR, true);
-        }
-
-        SkPaint layerPaint;
-        layerPaint.setAlpha(getLayerAlpha(layer) * 255);
-        layerPaint.setXfermodeMode(layer->getMode());
-        layerPaint.setColorFilter(layer->getColorFilter());
-
-        bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f;
-        drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
-                layer->getTextureId(), &layerPaint, blend,
-                &mMeshVertices[0].x, &mMeshVertices[0].u,
-                GL_TRIANGLE_STRIP, kUnitQuadCount, swap, swap || simpleTransform);
-
-        resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+        Blend::ModeOrderSwap modeUsage = swap ?
+                Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap;
+        const Matrix4& transform = swap ? Matrix4::identity() : *currentTransform();
+        bool snap = !swap
+                && layer->getWidth() == static_cast<uint32_t>(rect.getWidth())
+                && layer->getHeight() == static_cast<uint32_t>(rect.getHeight());
+        Glop glop;
+        GlopBuilder(mRenderState, mCaches, &glop)
+                .setMeshTexturedUvQuad(nullptr, layer->texCoords)
+                .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), modeUsage)
+                .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
+                .setModelViewMapUnitToRectOptionalSnap(snap, rect)
+                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+                .build();
+        renderGlop(glop);
     }
 }
 
@@ -1077,69 +993,8 @@
     const float texY = 1.0f / float(layer->getHeight());
     const float height = rect.getHeight();
 
-    if (USE_GLOPS) {
-        TextureVertex quadVertices[count * 4];
-        //std::unique_ptr<TextureVertex[]> quadVertices(new TextureVertex[count * 4]);
-        TextureVertex* mesh = &quadVertices[0];
-        for (size_t i = 0; i < count; i++) {
-            const android::Rect* r = &rects[i];
-
-            const float u1 = r->left * texX;
-            const float v1 = (height - r->top) * texY;
-            const float u2 = r->right * texX;
-            const float v2 = (height - r->bottom) * texY;
-
-            // TODO: Reject quads outside of the clip
-            TextureVertex::set(mesh++, r->left, r->top, u1, v1);
-            TextureVertex::set(mesh++, r->right, r->top, u2, v1);
-            TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
-            TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
-        }
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedIndexedQuads(&quadVertices[0], count * 6)
-                .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewOffsetRectSnap(0, 0, rect)
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
-        return;
-    }
-
-    const float alpha = getLayerAlpha(layer);
-
-    setupDraw();
-
-    // We must get (and therefore bind) the region mesh buffer
-    // after we setup drawing in case we need to mess with the
-    // stencil buffer in setupDraw()
-    TextureVertex* mesh = mCaches.getRegionMesh();
-    uint32_t numQuads = 0;
-
-    setupDrawWithTexture();
-    setupDrawColor(alpha, alpha, alpha, alpha);
-    setupDrawColorFilter(layer->getColorFilter());
-    setupDrawBlending(layer);
-    setupDrawProgram();
-    setupDrawDirtyRegionsDisabled();
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(layer->getColorFilter());
-    setupDrawTexture(layer->getTextureId());
-    if (currentTransform()->isPureTranslate()) {
-        const float x = floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
-        const float y = floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
-
-        layer->setFilter(GL_NEAREST);
-        setupDrawModelView(kModelViewMode_Translate, false,
-                x, y, x + rect.getWidth(), y + rect.getHeight(), true);
-    } else {
-        layer->setFilter(GL_LINEAR);
-        setupDrawModelView(kModelViewMode_Translate, false,
-                rect.left, rect.top, rect.right, rect.bottom);
-    }
-    setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
-
+    TextureVertex quadVertices[count * 4];
+    TextureVertex* mesh = &quadVertices[0];
     for (size_t i = 0; i < count; i++) {
         const android::Rect* r = &rects[i];
 
@@ -1153,21 +1008,16 @@
         TextureVertex::set(mesh++, r->right, r->top, u2, v1);
         TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
         TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
-
-        numQuads++;
-
-        if (numQuads >= kMaxNumberOfQuads) {
-            DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
-                    GL_UNSIGNED_SHORT, nullptr));
-            numQuads = 0;
-            mesh = mCaches.getRegionMesh();
-        }
     }
-
-    if (numQuads > 0) {
-        DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
-                GL_UNSIGNED_SHORT, nullptr));
-    }
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedIndexedQuads(&quadVertices[0], count * 6)
+            .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewOffsetRectSnap(0, 0, rect)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
 
 #if DEBUG_LAYERS_AS_REGIONS
     drawRegionRectsDebug(layer->region);
@@ -1246,21 +1096,6 @@
     }
 }
 
-void OpenGLRenderer::issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount) {
-    GLsizei elementsCount = quadsCount * 6;
-    while (elementsCount > 0) {
-        GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
-
-        setupDrawIndexedVertices(&mesh[0].x);
-        glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr);
-
-        elementsCount -= drawCount;
-        // Though there are 4 vertices in a quad, we use 6 indices per
-        // quad to draw with GL_TRIANGLES
-        mesh += (drawCount / 6) * 4;
-    }
-}
-
 void OpenGLRenderer::clearLayerRegions() {
     const size_t quadCount = mLayers.size();
     if (quadCount == 0) return;
@@ -1288,34 +1123,19 @@
             Vertex::set(vertex++, bounds.right, bounds.bottom);
         }
         // We must clear the list of dirty rects before we
-        // call setupDraw() to prevent stencil setup to do
-        // the same thing again
+        // call clearLayerRegions() in renderGlop to prevent
+        // stencil setup from doing the same thing again
         mLayers.clear();
 
-        if (USE_GLOPS) {
-            Glop glop;
-            GlopBuilder(mRenderState, mCaches, &glop)
-                    .setMeshIndexedQuads(&mesh[0], quadCount)
-                    .setFillClear()
-                    .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
-                    .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getClipRect()))
-                    .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                    .build();
-            renderGlop(glop, false);
-        } else {
-            SkPaint clearPaint;
-            clearPaint.setXfermodeMode(SkXfermode::kClear_Mode);
-
-            setupDraw(false);
-            setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
-            setupDrawBlending(&clearPaint, true);
-            setupDrawProgram();
-            setupDrawPureColorUniforms();
-            setupDrawModelView(kModelViewMode_Translate, false,
-                    0.0f, 0.0f, 0.0f, 0.0f, true);
-
-            issueIndexedQuadDraw(&mesh[0], quadCount);
-        }
+        Glop glop;
+        GlopBuilder(mRenderState, mCaches, &glop)
+                .setMeshIndexedQuads(&mesh[0], quadCount)
+                .setFillClear()
+                .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+                .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getClipRect()))
+                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+                .build();
+        renderGlop(glop, false);
 
         if (scissorChanged) mRenderState.scissor().setEnabled(true);
     } else {
@@ -1496,35 +1316,16 @@
     mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom,
             scissorBox.getWidth(), scissorBox.getHeight());
 
-    if (USE_GLOPS) {
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshIndexedQuads(&rectangleVertices[0], rectangleVertices.size() / 4)
-                .setFillBlack()
-                .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
-                .setModelViewOffsetRect(0, 0, scissorBox)
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    const SkPaint* paint = nullptr;
-    setupDraw();
-    setupDrawNoTexture();
-    setupDrawColor(0, 0xff * currentSnapshot()->alpha);
-    setupDrawShader(getShader(paint));
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint);
-    setupDrawProgram();
-    setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(kModelViewMode_Translate, false,
-            0.0f, 0.0f, 0.0f, 0.0f, true);
-    setupDrawColorUniforms(getShader(paint));
-    setupDrawShaderUniforms(getShader(paint));
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-
-    issueIndexedQuadDraw(&rectangleVertices[0], rectangleVertices.size() / 4);
+    Glop glop;
+    Vertex* vertices = &rectangleVertices[0];
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshIndexedQuads(vertices, rectangleVertices.size() / 4)
+            .setFillBlack()
+            .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+            .setModelViewOffsetRect(0, 0, scissorBox)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::setStencilFromClip() {
@@ -1664,355 +1465,6 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// Drawing commands
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::setupDraw(bool clearLayer) {
-    // TODO: It would be best if we could do this before quickRejectSetupScissor()
-    //       changes the scissor test state
-    if (clearLayer) clearLayerRegions();
-    // Make sure setScissor & setStencil happen at the beginning of
-    // this method
-    if (mState.getDirtyClip()) {
-        if (mRenderState.scissor().isEnabled()) {
-            setScissorFromClip();
-        }
-
-        setStencilFromClip();
-    }
-
-    mDescription.reset();
-
-    mSetShaderColor = false;
-    mColorSet = false;
-    mColor.a = mColor.r = mColor.g = mColor.b = 0.0f;
-    mTextureUnit = 0;
-    mTrackDirtyRegions = true;
-
-    // Enable debug highlight when what we're about to draw is tested against
-    // the stencil buffer and if stencil highlight debugging is on
-    mDescription.hasDebugHighlight = !mCaches.debugOverdraw
-            && mCaches.debugStencilClip == Caches::kStencilShowHighlight
-            && mRenderState.stencil().isTestEnabled();
-}
-
-void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
-    mDescription.hasTexture = true;
-    mDescription.hasAlpha8Texture = isAlpha8;
-}
-
-void OpenGLRenderer::setupDrawWithTextureAndColor(bool isAlpha8) {
-    mDescription.hasTexture = true;
-    mDescription.hasColors = true;
-    mDescription.hasAlpha8Texture = isAlpha8;
-}
-
-void OpenGLRenderer::setupDrawWithExternalTexture() {
-    mDescription.hasExternalTexture = true;
-}
-
-void OpenGLRenderer::setupDrawNoTexture() {
-    mRenderState.meshState().disableTexCoordsVertexArray();
-}
-
-void OpenGLRenderer::setupDrawVertexAlpha(bool useShadowAlphaInterp) {
-    mDescription.hasVertexAlpha = true;
-    mDescription.useShadowAlphaInterp = useShadowAlphaInterp;
-}
-
-void OpenGLRenderer::setupDrawColor(int color, int alpha) {
-    mColor.a = alpha / 255.0f;
-    mColor.r = mColor.a * ((color >> 16) & 0xFF) / 255.0f;
-    mColor.g = mColor.a * ((color >>  8) & 0xFF) / 255.0f;
-    mColor.b = mColor.a * ((color      ) & 0xFF) / 255.0f;
-    mColorSet = true;
-    mSetShaderColor = mDescription.setColorModulate(mColor.a);
-}
-
-void OpenGLRenderer::setupDrawAlpha8Color(int color, int alpha) {
-    mColor.a = alpha / 255.0f;
-    mColor.r = mColor.a * ((color >> 16) & 0xFF) / 255.0f;
-    mColor.g = mColor.a * ((color >>  8) & 0xFF) / 255.0f;
-    mColor.b = mColor.a * ((color      ) & 0xFF) / 255.0f;
-    mColorSet = true;
-    mSetShaderColor = mDescription.setAlpha8ColorModulate(mColor.r, mColor.g, mColor.b, mColor.a);
-}
-
-void OpenGLRenderer::setupDrawTextGamma(const SkPaint* paint) {
-    mCaches.fontRenderer->describe(mDescription, paint);
-}
-
-void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) {
-    mColor.a = a;
-    mColor.r = r;
-    mColor.g = g;
-    mColor.b = b;
-    mColorSet = true;
-    mSetShaderColor = mDescription.setColorModulate(a);
-}
-
-void OpenGLRenderer::setupDrawShader(const SkShader* shader) {
-    if (shader != nullptr) {
-        SkiaShader::describe(&mCaches, mDescription, mCaches.extensions(), *shader);
-    }
-}
-
-void OpenGLRenderer::setupDrawColorFilter(const SkColorFilter* filter) {
-    if (filter == nullptr) {
-        return;
-    }
-
-    SkXfermode::Mode mode;
-    if (filter->asColorMode(nullptr, &mode)) {
-        mDescription.colorOp = ProgramDescription::kColorBlend;
-        mDescription.colorMode = mode;
-    } else if (filter->asColorMatrix(nullptr)) {
-        mDescription.colorOp = ProgramDescription::kColorMatrix;
-    }
-}
-
-void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) {
-    if (mColorSet && mode == SkXfermode::kClear_Mode) {
-        mColor.a = 1.0f;
-        mColor.r = mColor.g = mColor.b = 0.0f;
-        mSetShaderColor = mDescription.modulate = true;
-    }
-}
-
-void OpenGLRenderer::setupDrawBlending(const Layer* layer, bool swapSrcDst) {
-    SkXfermode::Mode mode = layer->getMode();
-    // When the blending mode is kClear_Mode, we need to use a modulate color
-    // argb=1,0,0,0
-    accountForClear(mode);
-    // TODO: check shader blending, once we have shader drawing support for layers.
-    bool blend = layer->isBlend()
-            || getLayerAlpha(layer) < 1.0f
-            || (mColorSet && mColor.a < 1.0f)
-            || PaintUtils::isBlendedColorFilter(layer->getColorFilter());
-    chooseBlending(blend, mode, mDescription, swapSrcDst);
-}
-
-void OpenGLRenderer::setupDrawBlending(const SkPaint* paint, bool blend, bool swapSrcDst) {
-    SkXfermode::Mode mode = getXfermodeDirect(paint);
-    // When the blending mode is kClear_Mode, we need to use a modulate color
-    // argb=1,0,0,0
-    accountForClear(mode);
-    blend |= (mColorSet && mColor.a < 1.0f)
-            || (getShader(paint) && !getShader(paint)->isOpaque())
-            || PaintUtils::isBlendedColorFilter(getColorFilter(paint));
-    chooseBlending(blend, mode, mDescription, swapSrcDst);
-}
-
-void OpenGLRenderer::setupDrawProgram() {
-    mCaches.setProgram(mDescription);
-    if (mDescription.hasRoundRectClip) {
-        // TODO: avoid doing this repeatedly, stashing state pointer in program
-        const RoundRectClipState* state = writableSnapshot()->roundRectClipState;
-        const Rect& innerRect = state->innerRect;
-        glUniform4f(mCaches.program().getUniform("roundRectInnerRectLTRB"),
-                innerRect.left, innerRect.top,
-                innerRect.right, innerRect.bottom);
-        glUniformMatrix4fv(mCaches.program().getUniform("roundRectInvTransform"),
-                1, GL_FALSE, &state->matrix.data[0]);
-
-        // add half pixel to round out integer rect space to cover pixel centers
-        float roundedOutRadius = state->radius + 0.5f;
-        glUniform1f(mCaches.program().getUniform("roundRectRadius"),
-                roundedOutRadius);
-    }
-}
-
-void OpenGLRenderer::setupDrawDirtyRegionsDisabled() {
-    mTrackDirtyRegions = false;
-}
-
-void OpenGLRenderer::setupDrawModelView(ModelViewMode mode, bool offset,
-        float left, float top, float right, float bottom, bool ignoreTransform) {
-    mModelViewMatrix.loadTranslate(left, top, 0.0f);
-    if (mode == kModelViewMode_TranslateAndScale) {
-        mModelViewMatrix.scale(right - left, bottom - top, 1.0f);
-    }
-
-    bool dirty = right - left > 0.0f && bottom - top > 0.0f;
-    const Matrix4& transformMatrix = ignoreTransform ? Matrix4::identity() : *currentTransform();
-
-    mCaches.program().set(currentSnapshot()->getOrthoMatrix(),
-            mModelViewMatrix, transformMatrix, offset);
-    if (dirty && mTrackDirtyRegions) {
-        if (!ignoreTransform) {
-            dirtyLayer(left, top, right, bottom, *currentTransform());
-        } else {
-            dirtyLayer(left, top, right, bottom);
-        }
-    }
-}
-
-void OpenGLRenderer::setupDrawColorUniforms(bool hasShader) {
-    if ((mColorSet && !hasShader) || (hasShader && mSetShaderColor)) {
-        mCaches.program().setColor(mColor);
-    }
-}
-
-void OpenGLRenderer::setupDrawPureColorUniforms() {
-    if (mSetShaderColor) {
-        mCaches.program().setColor(mColor);
-    }
-}
-
-void OpenGLRenderer::setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform) {
-    if (shader == nullptr) {
-        return;
-    }
-
-    if (ignoreTransform) {
-        // if ignoreTransform=true was passed to setupDrawModelView, undo currentTransform()
-        // because it was built into modelView / the geometry, and the description needs to
-        // compensate.
-        mat4 modelViewWithoutTransform;
-        modelViewWithoutTransform.loadInverse(*currentTransform());
-        modelViewWithoutTransform.multiply(mModelViewMatrix);
-        mModelViewMatrix.load(modelViewWithoutTransform);
-    }
-
-    SkiaShader::setupProgram(&mCaches, mModelViewMatrix, &mTextureUnit,
-            mCaches.extensions(), *shader);
-}
-
-void OpenGLRenderer::setupDrawColorFilterUniforms(const SkColorFilter* filter) {
-    if (nullptr == filter) {
-        return;
-    }
-
-    SkColor color;
-    SkXfermode::Mode mode;
-    if (filter->asColorMode(&color, &mode)) {
-        const int alpha = SkColorGetA(color);
-        const GLfloat a = alpha / 255.0f;
-        const GLfloat r = a * SkColorGetR(color) / 255.0f;
-        const GLfloat g = a * SkColorGetG(color) / 255.0f;
-        const GLfloat b = a * SkColorGetB(color) / 255.0f;
-        glUniform4f(mCaches.program().getUniform("colorBlend"), r, g, b, a);
-        return;
-    }
-
-    SkScalar srcColorMatrix[20];
-    if (filter->asColorMatrix(srcColorMatrix)) {
-
-        float colorMatrix[16];
-        memcpy(colorMatrix, srcColorMatrix, 4 * sizeof(float));
-        memcpy(&colorMatrix[4], &srcColorMatrix[5], 4 * sizeof(float));
-        memcpy(&colorMatrix[8], &srcColorMatrix[10], 4 * sizeof(float));
-        memcpy(&colorMatrix[12], &srcColorMatrix[15], 4 * sizeof(float));
-
-        // Skia uses the range [0..255] for the addition vector, but we need
-        // the [0..1] range to apply the vector in GLSL
-        float colorVector[4];
-        colorVector[0] = srcColorMatrix[4] / 255.0f;
-        colorVector[1] = srcColorMatrix[9] / 255.0f;
-        colorVector[2] = srcColorMatrix[14] / 255.0f;
-        colorVector[3] = srcColorMatrix[19] / 255.0f;
-
-        glUniformMatrix4fv(mCaches.program().getUniform("colorMatrix"), 1,
-                GL_FALSE, colorMatrix);
-        glUniform4fv(mCaches.program().getUniform("colorMatrixVector"), 1, colorVector);
-        return;
-    }
-
-    // it is an error if we ever get here
-}
-
-void OpenGLRenderer::setupDrawTextGammaUniforms() {
-    mCaches.fontRenderer->setupProgram(mDescription, mCaches.program());
-}
-
-void OpenGLRenderer::setupDrawSimpleMesh() {
-    bool force = mRenderState.meshState().bindMeshBuffer();
-    mRenderState.meshState().bindPositionVertexPointer(force, nullptr);
-    mRenderState.meshState().unbindIndicesBuffer();
-}
-
-void OpenGLRenderer::setupDrawTexture(GLuint texture) {
-    if (texture) mCaches.textureState().bindTexture(texture);
-    mTextureUnit++;
-    mRenderState.meshState().enableTexCoordsVertexArray();
-}
-
-void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) {
-    mCaches.textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
-    mTextureUnit++;
-    mRenderState.meshState().enableTexCoordsVertexArray();
-}
-
-void OpenGLRenderer::setupDrawTextureTransform() {
-    mDescription.hasTextureTransform = true;
-}
-
-void OpenGLRenderer::setupDrawTextureTransformUniforms(mat4& transform) {
-    glUniformMatrix4fv(mCaches.program().getUniform("mainTextureTransform"), 1,
-            GL_FALSE, &transform.data[0]);
-}
-
-void OpenGLRenderer::setupDrawMesh(const GLvoid* vertices,
-        const GLvoid* texCoords, GLuint vbo) {
-    bool force = false;
-    if (!vertices || vbo) {
-        force = mRenderState.meshState().bindMeshBuffer(vbo);
-    } else {
-        force = mRenderState.meshState().unbindMeshBuffer();
-    }
-
-    mRenderState.meshState().bindPositionVertexPointer(force, vertices);
-    if (mCaches.program().texCoords >= 0) {
-        mRenderState.meshState().bindTexCoordsVertexPointer(force, texCoords);
-    }
-
-    mRenderState.meshState().unbindIndicesBuffer();
-}
-
-void OpenGLRenderer::setupDrawMesh(const GLvoid* vertices,
-        const GLvoid* texCoords, const GLvoid* colors) {
-    bool force = mRenderState.meshState().unbindMeshBuffer();
-    GLsizei stride = sizeof(ColorTextureVertex);
-
-    mRenderState.meshState().bindPositionVertexPointer(force, vertices, stride);
-    if (mCaches.program().texCoords >= 0) {
-        mRenderState.meshState().bindTexCoordsVertexPointer(force, texCoords, stride);
-    }
-    int slot = mCaches.program().getAttrib("colors");
-    if (slot >= 0) {
-        glEnableVertexAttribArray(slot);
-        glVertexAttribPointer(slot, 4, GL_FLOAT, GL_FALSE, stride, colors);
-    }
-
-    mRenderState.meshState().unbindIndicesBuffer();
-}
-
-void OpenGLRenderer::setupDrawMeshIndices(const GLvoid* vertices,
-        const GLvoid* texCoords, GLuint vbo) {
-    bool force = false;
-    // If vbo is != 0 we want to treat the vertices parameter as an offset inside
-    // a VBO. However, if vertices is set to NULL and vbo == 0 then we want to
-    // use the default VBO found in RenderState
-    if (!vertices || vbo) {
-        force = mRenderState.meshState().bindMeshBuffer(vbo);
-    } else {
-        force = mRenderState.meshState().unbindMeshBuffer();
-    }
-    mRenderState.meshState().bindQuadIndicesBuffer();
-
-    mRenderState.meshState().bindPositionVertexPointer(force, vertices);
-    if (mCaches.program().texCoords >= 0) {
-        mRenderState.meshState().bindTexCoordsVertexPointer(force, texCoords);
-    }
-}
-
-void OpenGLRenderer::setupDrawIndexedVertices(GLvoid* vertices) {
-    bool force = mRenderState.meshState().unbindMeshBuffer();
-    mRenderState.meshState().bindQuadIndicesBuffer();
-    mRenderState.meshState().bindPositionVertexPointer(force, vertices, kVertexStride);
-}
-
-///////////////////////////////////////////////////////////////////////////////
 // Drawing
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -2047,30 +1499,6 @@
     }
 }
 
-void OpenGLRenderer::drawAlphaBitmap(Texture* texture, const SkPaint* paint) {
-    float x = 0;
-    float y = 0;
-
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-
-    bool ignoreTransform = false;
-    if (currentTransform()->isPureTranslate()) {
-        x = floorf(currentTransform()->getTranslateX() + 0.5f);
-        y = floorf(currentTransform()->getTranslateY() + 0.5f);
-        ignoreTransform = true;
-
-        texture->setFilter(GL_NEAREST, true);
-    } else {
-        texture->setFilter(PaintUtils::getFilter(paint), true);
-    }
-
-    // No need to check for a UV mapper on the texture object, only ARGB_8888
-    // bitmaps get packed in the atlas
-    drawAlpha8TextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
-            paint, (GLvoid*) nullptr, (GLvoid*) kMeshTextureOffset,
-            GL_TRIANGLE_STRIP, kUnitQuadCount, ignoreTransform);
-}
-
 /**
  * Important note: this method is intended to draw batches of bitmaps and
  * will not set the scissor enable or dirty the current layer, if any.
@@ -2084,45 +1512,22 @@
 
     const AutoTexture autoCleanup(texture);
 
-    if (USE_GLOPS) {
-        // TODO: remove layer dirty in multi-draw callers
-        // TODO: snap doesn't need to touch transform, only texture filter.
-        bool snap = pureTranslate;
-        const float x = floorf(bounds.left + 0.5f);
-        const float y = floorf(bounds.top + 0.5f);
-        int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
-                ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedMesh(vertices, bitmapCount * 6)
-                .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
-                .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(0, 0, bounds.getWidth(), bounds.getHeight()))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    mCaches.textureState().activateTexture(0);
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(pureTranslate ? GL_NEAREST : PaintUtils::getFilter(paint), true);
-
+    // TODO: remove layer dirty in multi-draw callers
+    // TODO: snap doesn't need to touch transform, only texture filter.
+    bool snap = pureTranslate;
     const float x = floorf(bounds.left + 0.5f);
     const float y = floorf(bounds.top + 0.5f);
-    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
-        drawAlpha8TextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
-                texture->id, paint, &vertices[0].x, &vertices[0].u,
-                GL_TRIANGLES, bitmapCount * 6, true,
-                kModelViewMode_Translate, false);
-    } else {
-        drawTextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
-                texture->id, paint, texture->blend, &vertices[0].x, &vertices[0].u,
-                GL_TRIANGLES, bitmapCount * 6, false, true, 0,
-                kModelViewMode_Translate, false);
-    }
-
-    mDirty = true;
+    int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
+            ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedMesh(vertices, bitmapCount * 6)
+            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+            .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(0, 0, bounds.getWidth(), bounds.getHeight()))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
@@ -2135,28 +1540,17 @@
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
 
-    if (USE_GLOPS) {
-        int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
-                ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedUnitQuad(texture->uvMapper)
-                .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
-        drawAlphaBitmap(texture, paint);
-    } else {
-        drawTextureRect(texture, paint);
-    }
-
-    mDirty = true;
+    int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
+            ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedUnitQuad(texture->uvMapper)
+            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
@@ -2233,56 +1627,19 @@
     }
     const AutoTexture autoCleanup(texture);
 
-    if (USE_GLOPS) {
-        /*
-         * TODO: handle alpha_8 textures correctly by applying paint color, but *not*
-         * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh.
-         */
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshColoredTexturedMesh(mesh.get(), elementCount)
-                .setFillTexturePaint(*texture, static_cast<int>(TextureFillFlags::kNone), paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    mCaches.textureState().activateTexture(0);
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(PaintUtils::getFilter(paint), true);
-
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-
-
-    dirtyLayer(left, top, right, bottom, *currentTransform());
-
-    float a = alpha / 255.0f;
-    setupDraw();
-    setupDrawWithTextureAndColor();
-    setupDrawColor(a, a, a, a);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint, true);
-    setupDrawProgram();
-    setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(kModelViewMode_Translate, false, 0, 0, 0, 0);
-    setupDrawTexture(texture->id);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawMesh(&mesh[0].x, &mesh[0].u, &mesh[0].r);
-
-    glDrawArrays(GL_TRIANGLES, 0, elementCount);
-
-    int slot = mCaches.program().getAttrib("colors");
-    if (slot >= 0) {
-        glDisableVertexAttribArray(slot);
-    }
-
-    mDirty = true;
+    /*
+     * TODO: handle alpha_8 textures correctly by applying paint color, but *not*
+     * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh.
+     */
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshColoredTexturedMesh(mesh.get(), elementCount)
+            .setFillTexturePaint(*texture, static_cast<int>(TextureFillFlags::kNone), paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst, const SkPaint* paint) {
@@ -2294,80 +1651,22 @@
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
 
-    if (USE_GLOPS) {
-        Rect uv(fmax(0.0f, src.left / texture->width),
-                fmax(0.0f, src.top / texture->height),
-                fmin(1.0f, src.right / texture->width),
-                fmin(1.0f, src.bottom / texture->height));
+    Rect uv(fmax(0.0f, src.left / texture->width),
+            fmax(0.0f, src.top / texture->height),
+            fmin(1.0f, src.right / texture->width),
+            fmin(1.0f, src.bottom / texture->height));
 
-        int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
-                ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedUvQuad(texture->uvMapper, uv)
-                .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewMapUnitToRectSnap(dst)
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    mCaches.textureState().activateTexture(0);
-
-    const float width = texture->width;
-    const float height = texture->height;
-
-    float u1 = fmax(0.0f, src.left / width);
-    float v1 = fmax(0.0f, src.top / height);
-    float u2 = fmin(1.0f, src.right / width);
-    float v2 = fmin(1.0f, src.bottom / height);
-
-    getMapper(texture).map(u1, v1, u2, v2);
-
-    mRenderState.meshState().unbindMeshBuffer();
-    resetDrawTextureTexCoords(u1, v1, u2, v2);
-
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-
-    float scaleX = (dst.right - dst.left) / (src.right - src.left);
-    float scaleY = (dst.bottom - dst.top) / (src.bottom - src.top);
-
-    bool scaled = scaleX != 1.0f || scaleY != 1.0f;
-    bool ignoreTransform = false;
-
-    if (CC_LIKELY(currentTransform()->isPureTranslate())) {
-        float x = floorf(dst.left + currentTransform()->getTranslateX() + 0.5f);
-        float y = floorf(dst.top + currentTransform()->getTranslateY() + 0.5f);
-
-        dst.right = x + (dst.right - dst.left);
-        dst.bottom = y + (dst.bottom - dst.top);
-
-        dst.left = x;
-        dst.top = y;
-
-        texture->setFilter(scaled ? PaintUtils::getFilter(paint) : GL_NEAREST, true);
-        ignoreTransform = true;
-    } else {
-        texture->setFilter(PaintUtils::getFilter(paint), true);
-    }
-
-    if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
-        drawAlpha8TextureMesh(dst.left, dst.top, dst.right, dst.bottom,
-                texture->id, paint,
-                &mMeshVertices[0].x, &mMeshVertices[0].u,
-                GL_TRIANGLE_STRIP, kUnitQuadCount, ignoreTransform);
-    } else {
-        drawTextureMesh(dst.left, dst.top, dst.right, dst.bottom,
-                texture->id, paint, texture->blend,
-                &mMeshVertices[0].x, &mMeshVertices[0].u,
-                GL_TRIANGLE_STRIP, kUnitQuadCount, false, ignoreTransform);
-    }
-
-    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
-
-    mDirty = true;
+    int textureFillFlags = static_cast<int>((bitmap->colorType() == kAlpha_8_SkColorType)
+            ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedUvQuad(texture->uvMapper, uv)
+            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewMapUnitToRectSnap(dst)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh,
@@ -2380,66 +1679,20 @@
     Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
     if (!texture) return;
 
-    if (USE_GLOPS) {
-        // 9 patches are built for stretching - always filter
-        int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter);
-        if (bitmap->colorType() == kAlpha_8_SkColorType) {
-            textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture;
-        }
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshPatchQuads(*mesh)
-                .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewOffsetRectSnap(left, top, Rect(0, 0, right - left, bottom - top)) // TODO: get minimal bounds from patch
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
+    // 9 patches are built for stretching - always filter
+    int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter);
+    if (bitmap->colorType() == kAlpha_8_SkColorType) {
+        textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture;
     }
-
-    mCaches.textureState().activateTexture(0);
-    const AutoTexture autoCleanup(texture);
-
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(GL_LINEAR, true);
-
-    const bool pureTranslate = currentTransform()->isPureTranslate();
-    // Mark the current layer dirty where we are going to draw the patch
-    if (hasLayer() && mesh->hasEmptyQuads) {
-        const float offsetX = left + currentTransform()->getTranslateX();
-        const float offsetY = top + currentTransform()->getTranslateY();
-        const size_t count = mesh->quads.size();
-        for (size_t i = 0; i < count; i++) {
-            const Rect& bounds = mesh->quads.itemAt(i);
-            if (CC_LIKELY(pureTranslate)) {
-                const float x = floorf(bounds.left + offsetX + 0.5f);
-                const float y = floorf(bounds.top + offsetY + 0.5f);
-                dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight());
-            } else {
-                dirtyLayer(left + bounds.left, top + bounds.top,
-                        left + bounds.right, top + bounds.bottom, *currentTransform());
-            }
-        }
-    }
-
-    bool ignoreTransform = false;
-    if (CC_LIKELY(pureTranslate)) {
-        const float x = floorf(left + currentTransform()->getTranslateX() + 0.5f);
-        const float y = floorf(top + currentTransform()->getTranslateY() + 0.5f);
-
-        right = x + right - left;
-        bottom = y + bottom - top;
-        left = x;
-        top = y;
-        ignoreTransform = true;
-    }
-    drawIndexedTextureMesh(left, top, right, bottom, texture->id, paint,
-            texture->blend, (GLvoid*) mesh->positionOffset, (GLvoid*) mesh->textureOffset,
-            GL_TRIANGLES, mesh->indexCount, false, ignoreTransform,
-            mCaches.patchCache.getMeshBuffer(), kModelViewMode_Translate, !mesh->hasEmptyQuads);
-
-    mDirty = true;
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshPatchQuads(*mesh)
+            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewOffsetRectSnap(left, top, Rect(0, 0, right - left, bottom - top)) // TODO: get minimal bounds from patch
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 /**
@@ -2454,33 +1707,21 @@
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
 
-    if (USE_GLOPS) {
-        // TODO: get correct bounds from caller
-        // 9 patches are built for stretching - always filter
-        int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter);
-        if (bitmap->colorType() == kAlpha_8_SkColorType) {
-            textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture;
-        }
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedIndexedQuads(vertices, elementCount)
-                .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
-                .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
+    // TODO: get correct bounds from caller
+    // 9 patches are built for stretching - always filter
+    int textureFillFlags = static_cast<int>(TextureFillFlags::kForceFilter);
+    if (bitmap->colorType() == kAlpha_8_SkColorType) {
+        textureFillFlags |= TextureFillFlags::kIsAlphaMaskTexture;
     }
-
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(GL_LINEAR, true);
-
-    drawIndexedTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, paint,
-            texture->blend, &vertices[0].x, &vertices[0].u,
-            GL_TRIANGLES, elementCount, false, true, 0, kModelViewMode_Translate, false);
-
-    mDirty = true;
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedIndexedQuads(vertices, elementCount)
+            .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+            .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY,
@@ -2491,72 +1732,17 @@
         return;
     }
 
-    if (USE_GLOPS) {
-        bool fudgeOffset = displayFlags & kVertexBuffer_Offset;
-        bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp;
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshVertexBuffer(vertexBuffer, shadowInterp)
-                .setFillPaint(*paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset)
-                .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    const VertexBuffer::MeshFeatureFlags meshFeatureFlags = vertexBuffer.getMeshFeatureFlags();
-    Rect bounds(vertexBuffer.getBounds());
-    bounds.translate(translateX, translateY);
-    dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform());
-
-    int color = paint->getColor();
-    bool isAA = meshFeatureFlags & VertexBuffer::kAlpha;
-
-    setupDraw();
-    setupDrawNoTexture();
-    if (isAA) setupDrawVertexAlpha((displayFlags & kVertexBuffer_ShadowInterp));
-    setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawShader(getShader(paint));
-    setupDrawBlending(paint, isAA);
-    setupDrawProgram();
-    setupDrawModelView(kModelViewMode_Translate, (displayFlags & kVertexBuffer_Offset),
-            translateX, translateY, 0, 0);
-    setupDrawColorUniforms(getShader(paint));
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawShaderUniforms(getShader(paint));
-
-    const void* vertices = vertexBuffer.getBuffer();
-    mRenderState.meshState().unbindMeshBuffer();
-    mRenderState.meshState().bindPositionVertexPointer(true, vertices,
-            isAA ? kAlphaVertexStride : kVertexStride);
-    mRenderState.meshState().resetTexCoordsVertexPointer();
-
-    int alphaSlot = -1;
-    if (isAA) {
-        void* alphaCoords = ((GLbyte*) vertices) + kVertexAlphaOffset;
-        alphaSlot = mCaches.program().getAttrib("vtxAlpha");
-        // TODO: avoid enable/disable in back to back uses of the alpha attribute
-        glEnableVertexAttribArray(alphaSlot);
-        glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, kAlphaVertexStride, alphaCoords);
-    }
-
-    if (meshFeatureFlags & VertexBuffer::kIndices) {
-        mRenderState.meshState().unbindIndicesBuffer();
-        glDrawElements(GL_TRIANGLE_STRIP, vertexBuffer.getIndexCount(),
-                GL_UNSIGNED_SHORT, vertexBuffer.getIndices());
-    } else {
-        mRenderState.meshState().unbindIndicesBuffer();
-        glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount());
-    }
-
-    if (isAA) {
-        glDisableVertexAttribArray(alphaSlot);
-    }
-
-    mDirty = true;
+    bool fudgeOffset = displayFlags & kVertexBuffer_Offset;
+    bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp;
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshVertexBuffer(vertexBuffer, shadowInterp)
+            .setFillPaint(*paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset)
+            .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 /**
@@ -2811,40 +1997,15 @@
     const float sx = x - texture->left + textShadow.dx;
     const float sy = y - texture->top + textShadow.dy;
 
-    if (USE_GLOPS) {
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedUnitQuad(nullptr)
-                .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * currentSnapshot()->alpha;
-    if (getShader(paint)) {
-        textShadow.color = SK_ColorWHITE;
-    }
-
-    setupDraw();
-    setupDrawWithTexture(true);
-    setupDrawAlpha8Color(textShadow.color, shadowAlpha < 255 ? shadowAlpha : alpha);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawShader(getShader(paint));
-    setupDrawBlending(paint, true);
-    setupDrawProgram();
-    setupDrawModelView(kModelViewMode_TranslateAndScale, false,
-            sx, sy, sx + texture->width, sy + texture->height);
-    setupDrawTexture(texture->id);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawShaderUniforms(getShader(paint));
-    setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset);
-
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedUnitQuad(nullptr)
+            .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
@@ -2896,7 +2057,7 @@
     const Rect& clip(pureTranslate ? writableSnapshot()->getClipRect() : writableSnapshot()->getLocalClip());
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
-    TextSetupFunctor functor(this, x, y, pureTranslate, alpha, mode, paint);
+    TextDrawFunctor functor(this, x, y, pureTranslate, alpha, mode, paint);
     if (fontRenderer.renderPosText(paint, &clip, text, 0, bytesCount, count, x, y,
             positions, hasLayer() ? &bounds : nullptr, &functor)) {
         dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform());
@@ -3048,7 +2209,7 @@
     Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
     bool status;
-    TextSetupFunctor functor(this, x, y, pureTranslate, alpha, mode, paint);
+    TextDrawFunctor functor(this, x, y, pureTranslate, alpha, mode, paint);
 
     // don't call issuedrawcommand, do it at end of batch
     bool forceFinish = (drawOpMode != DrawOpMode::kDefer);
@@ -3090,7 +2251,7 @@
     int alpha;
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
-    TextSetupFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint);
+    TextDrawFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint);
 
     const Rect* clip = &writableSnapshot()->getLocalClip();
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
@@ -3157,56 +2318,15 @@
             DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
                     composeLayerRect(layer, layer->regionRect));
         } else if (layer->mesh) {
-            if (USE_GLOPS) {
-                Glop glop;
-                GlopBuilder(mRenderState, mCaches, &glop)
-                        .setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
-                        .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
-                        .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                        .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
-                        .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                        .build();
-                DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
-            } else {
-                const float a = getLayerAlpha(layer);
-                setupDraw();
-                setupDrawWithTexture();
-                setupDrawColor(a, a, a, a);
-                setupDrawColorFilter(layer->getColorFilter());
-                setupDrawBlending(layer);
-                setupDrawProgram();
-                setupDrawPureColorUniforms();
-                setupDrawColorFilterUniforms(layer->getColorFilter());
-                setupDrawTexture(layer->getTextureId());
-                if (CC_LIKELY(currentTransform()->isPureTranslate())) {
-                    int tx = (int) floorf(x + currentTransform()->getTranslateX() + 0.5f);
-                    int ty = (int) floorf(y + currentTransform()->getTranslateY() + 0.5f);
-
-                    layer->setFilter(GL_NEAREST);
-                    setupDrawModelView(kModelViewMode_Translate, false, tx, ty,
-                            tx + layer->layer.getWidth(), ty + layer->layer.getHeight(), true);
-                } else {
-                    layer->setFilter(GL_LINEAR);
-                    setupDrawModelView(kModelViewMode_Translate, false, x, y,
-                            x + layer->layer.getWidth(), y + layer->layer.getHeight());
-                }
-
-                TextureVertex* mesh = &layer->mesh[0];
-                GLsizei elementsCount = layer->meshElementCount;
-
-                while (elementsCount > 0) {
-                    GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
-
-                    setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
-                    DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
-                            glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr));
-
-                    elementsCount -= drawCount;
-                    // Though there are 4 vertices in a quad, we use 6 indices per
-                    // quad to draw with GL_TRIANGLES
-                    mesh += (drawCount / 6) * 4;
-                }
-            }
+            Glop glop;
+            GlopBuilder(mRenderState, mCaches, &glop)
+                    .setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
+                    .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
+                    .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+                    .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
+                    .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+                    .build();
+            DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
 #if DEBUG_LAYERS_AS_REGIONS
             drawRegionRectsDebug(layer->region);
 #endif
@@ -3256,40 +2376,15 @@
         return;
     }
 
-    if (USE_GLOPS) {
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshTexturedUnitQuad(nullptr)
-                .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-                .setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-
-    setupDraw();
-    setupDrawWithTexture(true);
-    setupDrawAlpha8Color(paint->getColor(), alpha);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawShader(getShader(paint));
-    setupDrawBlending(paint, true);
-    setupDrawProgram();
-    setupDrawModelView(kModelViewMode_TranslateAndScale, false,
-            x, y, x + texture->width, y + texture->height);
-    setupDrawTexture(texture->id);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawShaderUniforms(getShader(paint));
-    setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset);
-
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshTexturedUnitQuad(nullptr)
+            .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+            .setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 // Same values used by Skia
@@ -3417,249 +2512,30 @@
         return;
     }
 
-    if (USE_GLOPS) {
-        const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshIndexedQuads(&mesh[0], count / 4)
-                .setFillPaint(*paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
-                .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    int color = paint->getColor();
-    // If a shader is set, preserve only the alpha
-    if (getShader(paint)) {
-        color |= 0x00ffffff;
-    }
-
-    setupDraw();
-    setupDrawNoTexture();
-    setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
-    setupDrawShader(getShader(paint));
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint);
-    setupDrawProgram();
-    setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(kModelViewMode_Translate, false,
-            0.0f, 0.0f, 0.0f, 0.0f, ignoreTransform);
-    setupDrawColorUniforms(getShader(paint));
-    setupDrawShaderUniforms(getShader(paint));
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-
-    if (dirty && hasLayer()) {
-        dirtyLayer(left, top, right, bottom, *currentTransform());
-    }
-
-    issueIndexedQuadDraw(&mesh[0], count / 4);
-
-    mDirty = true;
+    const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshIndexedQuads(&mesh[0], count / 4)
+            .setFillPaint(*paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
+            .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
         const SkPaint* paint, bool ignoreTransform) {
-
-    if (USE_GLOPS) {
-        const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
-        Glop glop;
-        GlopBuilder(mRenderState, mCaches, &glop)
-                .setMeshUnitQuad()
-                .setFillPaint(*paint, currentSnapshot()->alpha)
-                .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
-                .setModelViewMapUnitToRect(Rect(left, top, right, bottom))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
-                .build();
-        renderGlop(glop);
-        return;
-    }
-
-    int color = paint->getColor();
-    // If a shader is set, preserve only the alpha
-    if (getShader(paint)) {
-        color |= 0x00ffffff;
-    }
-
-    setupDraw();
-    setupDrawNoTexture();
-    setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
-    setupDrawShader(getShader(paint));
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint);
-    setupDrawProgram();
-    setupDrawModelView(kModelViewMode_TranslateAndScale, false,
-            left, top, right, bottom, ignoreTransform);
-    setupDrawColorUniforms(getShader(paint));
-    setupDrawShaderUniforms(getShader(paint), ignoreTransform);
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawSimpleMesh();
-
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
-}
-
-void OpenGLRenderer::drawTextureRect(Texture* texture, const SkPaint* paint) {
-    texture->setWrap(GL_CLAMP_TO_EDGE, true);
-
-    GLvoid* vertices = (GLvoid*) nullptr;
-    GLvoid* texCoords = (GLvoid*) kMeshTextureOffset;
-
-    if (texture->uvMapper) {
-        vertices = &mMeshVertices[0].x;
-        texCoords = &mMeshVertices[0].u;
-
-        Rect uvs(0.0f, 0.0f, 1.0f, 1.0f);
-        texture->uvMapper->map(uvs);
-
-        resetDrawTextureTexCoords(uvs.left, uvs.top, uvs.right, uvs.bottom);
-    }
-
-    if (CC_LIKELY(currentTransform()->isPureTranslate())) {
-        const float x = floorf(currentTransform()->getTranslateX() + 0.5f);
-        const float y = floorf(currentTransform()->getTranslateY() + 0.5f);
-
-        texture->setFilter(GL_NEAREST, true);
-        drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
-                paint, texture->blend, vertices, texCoords,
-                GL_TRIANGLE_STRIP, kUnitQuadCount, false, true);
-    } else {
-        texture->setFilter(PaintUtils::getFilter(paint), true);
-        drawTextureMesh(0, 0, texture->width, texture->height, texture->id, paint,
-                texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, kUnitQuadCount);
-    }
-
-    if (texture->uvMapper) {
-        resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
-    }
-}
-
-void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
-        GLuint texture, const SkPaint* paint, bool blend,
-        GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-        bool swapSrcDst, bool ignoreTransform, GLuint vbo,
-        ModelViewMode modelViewMode, bool dirty) {
-
-    int a;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &a, &mode);
-    const float alpha = a / 255.0f;
-
-    setupDraw();
-    setupDrawWithTexture();
-    setupDrawColor(alpha, alpha, alpha, alpha);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint, blend, swapSrcDst);
-    setupDrawProgram();
-    if (!dirty) setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform);
-    setupDrawTexture(texture);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawMesh(vertices, texCoords, vbo);
-
-    glDrawArrays(drawMode, 0, elementsCount);
-}
-
-void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right, float bottom,
-        GLuint texture, const SkPaint* paint, bool blend,
-        GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-        bool swapSrcDst, bool ignoreTransform, GLuint vbo,
-        ModelViewMode modelViewMode, bool dirty) {
-
-    int a;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &a, &mode);
-    const float alpha = a / 255.0f;
-
-    setupDraw();
-    setupDrawWithTexture();
-    setupDrawColor(alpha, alpha, alpha, alpha);
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawBlending(paint, blend, swapSrcDst);
-    setupDrawProgram();
-    if (!dirty) setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform);
-    setupDrawTexture(texture);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawMeshIndices(vertices, texCoords, vbo);
-
-    glDrawElements(drawMode, elementsCount, GL_UNSIGNED_SHORT, nullptr);
-}
-
-void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom,
-        GLuint texture, const SkPaint* paint,
-        GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-        bool ignoreTransform, ModelViewMode modelViewMode, bool dirty) {
-
-    int color = paint != nullptr ? paint->getColor() : 0;
-    int alpha;
-    SkXfermode::Mode mode;
-    getAlphaAndMode(paint, &alpha, &mode);
-
-    setupDraw();
-    setupDrawWithTexture(true);
-    if (paint != nullptr) {
-        setupDrawAlpha8Color(color, alpha);
-    }
-    setupDrawColorFilter(getColorFilter(paint));
-    setupDrawShader(getShader(paint));
-    setupDrawBlending(paint, true);
-    setupDrawProgram();
-    if (!dirty) setupDrawDirtyRegionsDisabled();
-    setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform);
-    setupDrawTexture(texture);
-    setupDrawPureColorUniforms();
-    setupDrawColorFilterUniforms(getColorFilter(paint));
-    setupDrawShaderUniforms(getShader(paint), ignoreTransform);
-    setupDrawMesh(vertices, texCoords);
-
-    glDrawArrays(drawMode, 0, elementsCount);
-}
-
-void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
-        ProgramDescription& description, bool swapSrcDst) {
-
-    if (currentSnapshot()->roundRectClipState != nullptr /*&& !mSkipOutlineClip*/) {
-        blend = true;
-        mDescription.hasRoundRectClip = true;
-    }
-    mSkipOutlineClip = true;
-
-    blend = blend || mode != SkXfermode::kSrcOver_Mode;
-
-    if (blend) {
-        // These blend modes are not supported by OpenGL directly and have
-        // to be implemented using shaders. Since the shader will perform
-        // the blending, turn blending off here
-        // If the blend mode cannot be implemented using shaders, fall
-        // back to the default SrcOver blend mode instead
-        if (CC_UNLIKELY(mode > SkXfermode::kScreen_Mode)) {
-            if (CC_UNLIKELY(mCaches.extensions().hasFramebufferFetch())) {
-                description.framebufferMode = mode;
-                description.swapSrcDst = swapSrcDst;
-
-                mRenderState.blend().disable();
-                return;
-            } else {
-                mode = SkXfermode::kSrcOver_Mode;
-            }
-        }
-        mRenderState.blend().enable(mode,
-                swapSrcDst ? Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap);
-    } else {
-        mRenderState.blend().disable();
-    }
-}
-
-void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
-    TextureVertex* v = &mMeshVertices[0];
-    TextureVertex::setUV(v++, u1, v1);
-    TextureVertex::setUV(v++, u2, v1);
-    TextureVertex::setUV(v++, u1, v2);
-    TextureVertex::setUV(v++, u2, v2);
+    const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
+    Glop glop;
+    GlopBuilder(mRenderState, mCaches, &glop)
+            .setMeshUnitQuad()
+            .setFillPaint(*paint, currentSnapshot()->alpha)
+            .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
+            .setModelViewMapUnitToRect(Rect(left, top, right, bottom))
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+            .build();
+    renderGlop(glop);
 }
 
 void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha,
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index f4acad0..5f8960a 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -65,7 +65,7 @@
 struct Glop;
 class RenderState;
 class RenderNode;
-class TextSetupFunctor;
+class TextDrawFunctor;
 class VertexBuffer;
 
 struct DrawModifiers {
@@ -727,15 +727,6 @@
     void drawShape(float left, float top, PathTexture* texture, const SkPaint* paint);
 
     /**
-     * Draws the specified texture as an alpha bitmap. Alpha bitmaps obey
-     * different compositing rules.
-     *
-     * @param texture The texture to draw with
-     * @param paint The paint to render with
-     */
-    void drawAlphaBitmap(Texture* texture, const SkPaint* paint);
-
-    /**
      * Renders a strip of polygons with the specified paint, used for tessellated geometry.
      *
      * @param vertexBuffer The VertexBuffer to be drawn
@@ -762,60 +753,6 @@
     void drawConvexPath(const SkPath& path, const SkPaint* paint);
 
     /**
-     * Draws a textured rectangle with the specified texture.
-     *
-     * @param texture The texture to use
-     * @param paint The paint containing the alpha, blending mode, etc.
-     */
-    void drawTextureRect(Texture* texture, const SkPaint* paint);
-
-    /**
-     * Draws a textured mesh with the specified texture. If the indices are omitted,
-     * the mesh is drawn as a simple quad. The mesh pointers become offsets when a
-     * VBO is bound.
-     *
-     * @param left The left coordinate of the rectangle
-     * @param top The top coordinate of the rectangle
-     * @param right The right coordinate of the rectangle
-     * @param bottom The bottom coordinate of the rectangle
-     * @param texture The texture name to map onto the rectangle
-     * @param paint The paint containing the alpha, blending mode, colorFilter, etc.
-     * @param blend True if the texture contains an alpha channel
-     * @param vertices The vertices that define the mesh
-     * @param texCoords The texture coordinates of each vertex
-     * @param elementsCount The number of elements in the mesh, required by indices
-     * @param swapSrcDst Whether or not the src and dst blending operations should be swapped
-     * @param ignoreTransform True if the current transform should be ignored
-     * @param vbo The VBO used to draw the mesh
-     * @param modelViewMode Defines whether the model view matrix should be scaled
-     * @param dirty True if calling this method should dirty the current layer
-     */
-    void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture,
-            const SkPaint* paint, bool blend,
-            GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-            bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0,
-            ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale, bool dirty = true);
-
-    void drawIndexedTextureMesh(float left, float top, float right, float bottom, GLuint texture,
-            const SkPaint* paint, bool blend,
-            GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-            bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0,
-            ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale, bool dirty = true);
-
-    void drawAlpha8TextureMesh(float left, float top, float right, float bottom,
-            GLuint texture, const SkPaint* paint,
-            GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
-            bool ignoreTransform, ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale,
-            bool dirty = true);
-
-    /**
-     * Draws the specified list of vertices as quads using indexed GL_TRIANGLES.
-     * If the number of vertices to draw exceeds the number of indices we have
-     * pre-allocated, this method will generate several glDrawElements() calls.
-     */
-    void issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount);
-
-    /**
      * Draws text underline and strike-through if needed.
      *
      * @param text The text to decor
@@ -873,78 +810,6 @@
      */
     bool canSkipText(const SkPaint* paint) const;
 
-    /**
-     * Enable or disable blending as necessary. This function sets the appropriate
-     * blend function based on the specified xfermode.
-     */
-    inline void chooseBlending(bool blend, SkXfermode::Mode mode, ProgramDescription& description,
-            bool swapSrcDst = false);
-
-    /**
-     * Invoked before any drawing operation. This sets required state.
-     */
-    void setupDraw(bool clear = true);
-
-    /**
-     * Various methods to setup OpenGL rendering.
-     */
-    void setupDrawWithTexture(bool isAlpha8 = false);
-    void setupDrawWithTextureAndColor(bool isAlpha8 = false);
-    void setupDrawWithExternalTexture();
-    void setupDrawNoTexture();
-    void setupDrawVertexAlpha(bool useShadowAlphaInterp);
-    void setupDrawColor(int color, int alpha);
-    void setupDrawColor(float r, float g, float b, float a);
-    void setupDrawAlpha8Color(int color, int alpha);
-    void setupDrawTextGamma(const SkPaint* paint);
-    void setupDrawShader(const SkShader* shader);
-    void setupDrawColorFilter(const SkColorFilter* filter);
-    void setupDrawBlending(const Layer* layer, bool swapSrcDst = false);
-    void setupDrawBlending(const SkPaint* paint, bool blend = true, bool swapSrcDst = false);
-    void setupDrawProgram();
-    void setupDrawDirtyRegionsDisabled();
-
-    /**
-     * Setup the current program matrices based upon the nature of the geometry.
-     *
-     * @param mode If kModelViewMode_Translate, the geometry must be translated by the left and top
-     * parameters. If kModelViewMode_TranslateAndScale, the geometry that exists in the (0,0, 1,1)
-     * space must be scaled up and translated to fill the quad provided in (l,t,r,b). These
-     * transformations are stored in the modelView matrix and uploaded to the shader.
-     *
-     * @param offset Set to true if the the matrix should be fudged (translated) slightly to
-     * disambiguate geometry pixel positioning. See Vertex::GeometryFudgeFactor().
-     *
-     * @param ignoreTransform Set to true if l,t,r,b coordinates already in layer space,
-     * currentTransform() will be ignored. (e.g. when drawing clip in layer coordinates to stencil,
-     * or when simple translation has been extracted)
-     */
-    void setupDrawModelView(ModelViewMode mode, bool offset,
-            float left, float top, float right, float bottom, bool ignoreTransform = false);
-    void setupDrawColorUniforms(bool hasShader);
-    void setupDrawPureColorUniforms();
-
-    /**
-     * Setup uniforms for the current shader.
-     *
-     * @param shader SkShader on the current paint.
-     *
-     * @param ignoreTransform Set to true to ignore the transform in shader.
-     */
-    void setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform = false);
-    void setupDrawColorFilterUniforms(const SkColorFilter* paint);
-    void setupDrawSimpleMesh();
-    void setupDrawTexture(GLuint texture);
-    void setupDrawExternalTexture(GLuint texture);
-    void setupDrawTextureTransform();
-    void setupDrawTextureTransformUniforms(mat4& transform);
-    void setupDrawTextGammaUniforms();
-    void setupDrawMesh(const GLvoid* vertices, const GLvoid* texCoords = nullptr, GLuint vbo = 0);
-    void setupDrawMesh(const GLvoid* vertices, const GLvoid* texCoords, const GLvoid* colors);
-    void setupDrawMeshIndices(const GLvoid* vertices, const GLvoid* texCoords, GLuint vbo = 0);
-    void setupDrawIndexedVertices(GLvoid* vertices);
-    void accountForClear(SkXfermode::Mode mode);
-
     bool updateLayer(Layer* layer, bool inFrame);
     void updateLayers();
     void flushLayers();
@@ -993,22 +858,6 @@
     inline Snapshot* writableSnapshot() { return mState.writableSnapshot(); }
     inline const Snapshot* currentSnapshot() const { return mState.currentSnapshot(); }
 
-    /**
-     * Model-view matrix used to position/size objects
-     *
-     * Stores operation-local modifications to the draw matrix that aren't incorporated into the
-     * currentTransform().
-     *
-     * If generated with kModelViewMode_Translate, mModelViewMatrix will reflect an x/y offset,
-     * e.g. the offset in drawLayer(). If generated with kModelViewMode_TranslateAndScale,
-     * mModelViewMatrix will reflect a translation and scale, e.g. the translation and scale
-     * required to make VBO 0 (a rect of (0,0,1,1)) scaled to match the x,y offset, and width/height
-     * of a bitmap.
-     *
-     * Used as input to SkiaShader transformation.
-     */
-    mat4 mModelViewMatrix;
-
     // State used to define the clipping region
     Rect mTilingClip;
     // Is the target render surface opaque
@@ -1016,9 +865,6 @@
     // Is a frame currently being rendered
     bool mFrameStarted;
 
-    // Used to draw textured quads
-    TextureVertex mMeshVertices[4];
-
     // Default UV mapper
     const UvMapper mUvMapper;
 
@@ -1031,21 +877,6 @@
     // List of layers to update at the beginning of a frame
     Vector< sp<Layer> > mLayerUpdates;
 
-    // The following fields are used to setup drawing
-    // Used to describe the shaders to generate
-    ProgramDescription mDescription;
-    // Color description
-    bool mColorSet;
-    FloatColor mColor;
-    // Indicates that the shader should get a color
-    bool mSetShaderColor;
-    // Current texture unit
-    GLuint mTextureUnit;
-    // Track dirty regions, true by default
-    bool mTrackDirtyRegions;
-    // Indicate whether we are drawing an opaque frame
-    bool mOpaqueFrame;
-
     // See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in
     // Properties.h
     bool mScissorOptimizationDisabled;
@@ -1070,7 +901,7 @@
     std::vector<std::unique_ptr<SkPath>> mTempPaths;
 
     friend class Layer;
-    friend class TextSetupFunctor;
+    friend class TextDrawFunctor;
     friend class DrawBitmapOp;
     friend class DrawPatchOp;
 
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index 9509c48..30d3f41 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -197,6 +197,7 @@
             case SkPath::kLine_Verb:
                 arrayForDirection.add((Vector2){pts[1].x(), pts[1].y()});
                 break;
+            case SkPath::kConic_Verb:
             case SkPath::kQuad_Verb:
                 arrayForDirection.add((Vector2){pts[1].x(), pts[1].y()});
                 arrayForDirection.add((Vector2){pts[2].x(), pts[2].y()});
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 2fcf7f3..ecf8b6b 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -47,15 +47,6 @@
     return !(n & (n - 1));
 }
 
-static inline void bindUniformColor(int slot, uint32_t color) {
-    const float a = ((color >> 24) & 0xff) / 255.0f;
-    glUniform4f(slot,
-            a * ((color >> 16) & 0xff) / 255.0f,
-            a * ((color >>  8) & 0xff) / 255.0f,
-            a * ((color      ) & 0xff) / 255.0f,
-            a);
-}
-
 static inline void bindUniformColor(int slot, FloatColor color) {
     glUniform4fv(slot, 1, reinterpret_cast<const float*>(&color));
 }
@@ -83,229 +74,11 @@
     screenSpace.multiply(modelViewMatrix);
 }
 
-// Returns true if one is a bitmap and the other is a gradient
-static bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) {
-    return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType)
-            || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType);
-}
-
-SkiaShaderType SkiaShader::getType(const SkShader& shader) {
-    // First check for a gradient shader.
-    switch (shader.asAGradient(nullptr)) {
-        case SkShader::kNone_GradientType:
-            // Not a gradient shader. Fall through to check for other types.
-            break;
-        case SkShader::kLinear_GradientType:
-        case SkShader::kRadial_GradientType:
-        case SkShader::kSweep_GradientType:
-            return kGradient_SkiaShaderType;
-        default:
-            // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
-            return kNone_SkiaShaderType;
-    }
-
-    // The shader is not a gradient. Check for a bitmap shader.
-    if (shader.asABitmap(nullptr, nullptr, nullptr) == SkShader::kDefault_BitmapType) {
-        return kBitmap_SkiaShaderType;
-    }
-
-    // Check for a ComposeShader.
-    SkShader::ComposeRec rec;
-    if (shader.asACompose(&rec)) {
-        const SkiaShaderType shaderAType = getType(*rec.fShaderA);
-        const SkiaShaderType shaderBType = getType(*rec.fShaderB);
-
-        // Compose is only supported if one is a bitmap and the other is a
-        // gradient. Otherwise, return None to skip.
-        if (!bitmapAndGradient(shaderAType, shaderBType)) {
-            return kNone_SkiaShaderType;
-        }
-        return kCompose_SkiaShaderType;
-    }
-
-    if (shader.asACustomShader(nullptr)) {
-        return kLayer_SkiaShaderType;
-    }
-
-    return kNone_SkiaShaderType;
-}
-
-typedef void (*describeProc)(Caches* caches, ProgramDescription& description,
-        const Extensions& extensions, const SkShader& shader);
-
-describeProc gDescribeProc[] = {
-    InvalidSkiaShader::describe,
-    SkiaBitmapShader::describe,
-    SkiaGradientShader::describe,
-    SkiaComposeShader::describe,
-    SkiaLayerShader::describe,
-};
-
-typedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-
-setupProgramProc gSetupProgramProc[] = {
-    InvalidSkiaShader::setupProgram,
-    SkiaBitmapShader::setupProgram,
-    SkiaGradientShader::setupProgram,
-    SkiaComposeShader::setupProgram,
-    SkiaLayerShader::setupProgram,
-};
-
-void SkiaShader::describe(Caches* caches, ProgramDescription& description,
-        const Extensions& extensions, const SkShader& shader) {
-    gDescribeProc[getType(shader)](caches, description, extensions, shader);
-}
-
-void SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
-
-    gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
-// Layer shader
+// gradient shader matrix helpers
 ///////////////////////////////////////////////////////////////////////////////
 
-void SkiaLayerShader::describe(Caches*, ProgramDescription& description,
-        const Extensions&, const SkShader& shader) {
-    description.hasBitmap = true;
-}
-
-void SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions&, const SkShader& shader) {
-    Layer* layer;
-    if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
-        LOG_ALWAYS_FATAL("SkiaLayerShader::setupProgram called on the wrong type of shader!");
-    }
-
-    GLuint textureSlot = (*textureUnit)++;
-    caches->textureState().activateTexture(textureSlot);
-
-    const float width = layer->getWidth();
-    const float height = layer->getHeight();
-
-    mat4 textureTransform;
-    computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
-            modelViewMatrix);
-
-
-    // Uniforms
-    layer->bindTexture();
-    layer->setWrap(GL_CLAMP_TO_EDGE);
-    layer->setFilter(GL_LINEAR);
-
-    Program& program = caches->program();
-    glUniform1i(program.getUniform("bitmapSampler"), textureSlot);
-    glUniformMatrix4fv(program.getUniform("textureTransform"), 1,
-            GL_FALSE, &textureTransform.data[0]);
-    glUniform2f(program.getUniform("textureDimension"), 1.0f / width, 1.0f / height);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Bitmap shader
-///////////////////////////////////////////////////////////////////////////////
-
-struct BitmapShaderInfo {
-    float width;
-    float height;
-    GLenum wrapS;
-    GLenum wrapT;
-    Texture* texture;
-};
-
-static bool bitmapShaderHelper(Caches* caches, ProgramDescription* description,
-        BitmapShaderInfo* shaderInfo,
-        const Extensions& extensions,
-        const SkBitmap& bitmap, SkShader::TileMode tileModes[2]) {
-    Texture* texture = caches->textureCache.get(&bitmap);
-    if (!texture) return false;
-
-    const float width = texture->width;
-    const float height = texture->height;
-    GLenum wrapS, wrapT;
-
-    if (description) {
-        description->hasBitmap = true;
-    }
-    // The driver does not support non-power of two mirrored/repeated
-    // textures, so do it ourselves
-    if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
-            (tileModes[0] != SkShader::kClamp_TileMode ||
-             tileModes[1] != SkShader::kClamp_TileMode)) {
-        if (description) {
-            description->isBitmapNpot = true;
-            description->bitmapWrapS = gTileModes[tileModes[0]];
-            description->bitmapWrapT = gTileModes[tileModes[1]];
-        }
-        wrapS = GL_CLAMP_TO_EDGE;
-        wrapT = GL_CLAMP_TO_EDGE;
-    } else {
-        wrapS = gTileModes[tileModes[0]];
-        wrapT = gTileModes[tileModes[1]];
-    }
-
-    if (shaderInfo) {
-        shaderInfo->width = width;
-        shaderInfo->height = height;
-        shaderInfo->wrapS = wrapS;
-        shaderInfo->wrapT = wrapT;
-        shaderInfo->texture = texture;
-    }
-    return true;
-}
-
-void SkiaBitmapShader::describe(Caches* caches, ProgramDescription& description,
-        const Extensions& extensions, const SkShader& shader) {
-    SkBitmap bitmap;
-    SkShader::TileMode xy[2];
-    if (shader.asABitmap(&bitmap, nullptr, xy) != SkShader::kDefault_BitmapType) {
-        LOG_ALWAYS_FATAL("SkiaBitmapShader::describe called with a different kind of shader!");
-    }
-    bitmapShaderHelper(caches, &description, nullptr, extensions, bitmap, xy);
-}
-
-void SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
-    SkBitmap bitmap;
-    SkShader::TileMode xy[2];
-    if (shader.asABitmap(&bitmap, nullptr, xy) != SkShader::kDefault_BitmapType) {
-        LOG_ALWAYS_FATAL("SkiaBitmapShader::setupProgram called with a different kind of shader!");
-    }
-
-    GLuint textureSlot = (*textureUnit)++;
-    caches->textureState().activateTexture(textureSlot);
-
-    BitmapShaderInfo shaderInfo;
-    if (!bitmapShaderHelper(caches, nullptr, &shaderInfo, extensions, bitmap, xy)) {
-        return;
-    }
-
-    Program& program = caches->program();
-    Texture* texture = shaderInfo.texture;
-
-    const AutoTexture autoCleanup(texture);
-
-    mat4 textureTransform;
-    computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
-            modelViewMatrix);
-
-    // Uniforms
-    bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT);
-    texture->setFilter(GL_LINEAR);
-
-    glUniform1i(program.getUniform("bitmapSampler"), textureSlot);
-    glUniformMatrix4fv(program.getUniform("textureTransform"), 1,
-            GL_FALSE, &textureTransform.data[0]);
-    glUniform2f(program.getUniform("textureDimension"), 1.0f / shaderInfo.width,
-            1.0f / shaderInfo.height);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Linear gradient shader
-///////////////////////////////////////////////////////////////////////////////
-
-static void toUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
+static void toLinearUnitMatrix(const SkPoint pts[2], SkMatrix* matrix) {
     SkVector vec = pts[1] - pts[0];
     const float mag = vec.length();
     const float inv = mag ? 1.0f / mag : 0;
@@ -316,10 +89,6 @@
     matrix->postScale(inv, inv);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Circular gradient shader
-///////////////////////////////////////////////////////////////////////////////
-
 static void toCircularUnitMatrix(const float x, const float y, const float radius,
         SkMatrix* matrix) {
     const float inv = 1.0f / radius;
@@ -327,10 +96,6 @@
     matrix->postScale(inv, inv);
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Sweep gradient shader
-///////////////////////////////////////////////////////////////////////////////
-
 static void toSweepUnitMatrix(const float x, const float y, SkMatrix* matrix) {
     matrix->setTranslate(-x, -y);
 }
@@ -343,137 +108,6 @@
     return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
 }
 
-void SkiaGradientShader::describe(Caches*, ProgramDescription& description,
-        const Extensions& extensions, const SkShader& shader) {
-    SkShader::GradientInfo gradInfo;
-    gradInfo.fColorCount = 0;
-    gradInfo.fColors = nullptr;
-    gradInfo.fColorOffsets = nullptr;
-
-    switch (shader.asAGradient(&gradInfo)) {
-        case SkShader::kLinear_GradientType:
-            description.gradientType = ProgramDescription::kGradientLinear;
-            break;
-        case SkShader::kRadial_GradientType:
-            description.gradientType = ProgramDescription::kGradientCircular;
-            break;
-        case SkShader::kSweep_GradientType:
-            description.gradientType = ProgramDescription::kGradientSweep;
-            break;
-        default:
-            // Do nothing. This shader is unsupported.
-            return;
-    }
-    description.hasGradient = true;
-    description.isSimpleGradient = isSimpleGradient(gradInfo);
-}
-
-void SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions&, const SkShader& shader) {
-    // SkShader::GradientInfo.fColorCount is an in/out parameter. As input, it tells asAGradient
-    // how much space has been allocated for fColors and fColorOffsets.  10 was chosen
-    // arbitrarily, but should be >= 2.
-    // As output, it tells the number of actual colors/offsets in the gradient.
-    const int COLOR_COUNT = 10;
-    SkAutoSTMalloc<COLOR_COUNT, SkColor> colorStorage(COLOR_COUNT);
-    SkAutoSTMalloc<COLOR_COUNT, SkScalar> positionStorage(COLOR_COUNT);
-
-    SkShader::GradientInfo gradInfo;
-    gradInfo.fColorCount = COLOR_COUNT;
-    gradInfo.fColors = colorStorage.get();
-    gradInfo.fColorOffsets = positionStorage.get();
-
-    SkShader::GradientType gradType = shader.asAGradient(&gradInfo);
-
-    Program& program = caches->program();
-    if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
-        if (gradInfo.fColorCount > COLOR_COUNT) {
-            // There was not enough room in our arrays for all the colors and offsets. Try again,
-            // now that we know the true number of colors.
-            gradInfo.fColors = colorStorage.reset(gradInfo.fColorCount);
-            gradInfo.fColorOffsets = positionStorage.reset(gradInfo.fColorCount);
-
-            shader.asAGradient(&gradInfo);
-        }
-        GLuint textureSlot = (*textureUnit)++;
-        caches->textureState().activateTexture(textureSlot);
-
-#ifndef SK_SCALAR_IS_FLOAT
-    #error Need to convert gradInfo.fColorOffsets to float!
-#endif
-        Texture* texture = caches->gradientCache.get(gradInfo.fColors, gradInfo.fColorOffsets,
-                gradInfo.fColorCount);
-
-        // Uniforms
-        bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]);
-        glUniform1i(program.getUniform("gradientSampler"), textureSlot);
-    } else {
-        bindUniformColor(program.getUniform("startColor"), gradInfo.fColors[0]);
-        bindUniformColor(program.getUniform("endColor"), gradInfo.fColors[1]);
-    }
-
-    caches->dither.setupProgram(program, textureUnit);
-
-    SkMatrix unitMatrix;
-    switch (gradType) {
-        case SkShader::kLinear_GradientType:
-            toUnitMatrix(gradInfo.fPoint, &unitMatrix);
-            break;
-        case SkShader::kRadial_GradientType:
-            toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
-                    gradInfo.fRadius[0], &unitMatrix);
-            break;
-        case SkShader::kSweep_GradientType:
-            toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Invalid SkShader gradient type %d", gradType);
-    }
-
-    mat4 screenSpace;
-    computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix);
-    glUniformMatrix4fv(program.getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Compose shader
-///////////////////////////////////////////////////////////////////////////////
-
-void SkiaComposeShader::describe(Caches* caches, ProgramDescription& description,
-        const Extensions& extensions, const SkShader& shader) {
-    SkShader::ComposeRec rec;
-    if (!shader.asACompose(&rec)) {
-        LOG_ALWAYS_FATAL("SkiaComposeShader::describe called on the wrong shader type!");
-    }
-    SkiaShader::describe(caches, description, extensions, *rec.fShaderA);
-    SkiaShader::describe(caches, description, extensions, *rec.fShaderB);
-    if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) {
-        description.isBitmapFirst = true;
-    }
-    if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) {
-        // TODO: Support other modes.
-        description.shadersMode = SkXfermode::kSrcOver_Mode;
-    }
-}
-
-void SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
-        GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
-    SkShader::ComposeRec rec;
-    if (!shader.asACompose(&rec)) {
-        LOG_ALWAYS_FATAL("SkiaComposeShader::setupProgram called on the wrong shader type!");
-    }
-
-    // Apply this compose shader's local transform and pass it down to
-    // the child shaders. They will in turn apply their local transform
-    // to this matrix.
-    mat4 transform;
-    computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(),
-            modelViewMatrix);
-
-    SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA);
-    SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Store / apply
 ///////////////////////////////////////////////////////////////////////////////
@@ -491,7 +125,7 @@
         case SkShader::kLinear_GradientType:
             description->gradientType = ProgramDescription::kGradientLinear;
 
-            toUnitMatrix(gradInfo.fPoint, &unitMatrix);
+            toLinearUnitMatrix(gradInfo.fPoint, &unitMatrix);
             break;
         case SkShader::kRadial_GradientType:
             description->gradientType = ProgramDescription::kGradientCircular;
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 2962441c..5b8aa86 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -87,77 +87,12 @@
 
 class SkiaShader {
 public:
-    static SkiaShaderType getType(const SkShader& shader);
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader);
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-
-    // new SkiaShader interaction model - store into ShaderData, and apply to Caches/Program/GL
     static void store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix,
             GLuint* textureUnit, ProgramDescription* description,
             SkiaShaderData* outData);
     static void apply(Caches& caches, const SkiaShaderData& data);
 };
 
-class InvalidSkiaShader {
-public:
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader) {
-        // This shader is unsupported. Skip it.
-    }
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
-        // This shader is unsupported. Skip it.
-    }
-
-};
-/**
- * A shader that draws a layer.
- */
-class SkiaLayerShader {
-public:
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader);
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-}; // class SkiaLayerShader
-
-/**
- * A shader that draws a bitmap.
- */
-class SkiaBitmapShader {
-public:
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader);
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-
-
-}; // class SkiaBitmapShader
-
-/**
- * A shader that draws one of three types of gradient, depending on shader param.
- */
-class SkiaGradientShader {
-public:
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader);
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-};
-
-/**
- * A shader that draws two shaders, composited with an xfermode.
- */
-class SkiaComposeShader {
-public:
-    static void describe(Caches* caches, ProgramDescription& description,
-            const Extensions& extensions, const SkShader& shader);
-    static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
-            GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
-}; // class SkiaComposeShader
-
 }; // namespace uirenderer
 }; // namespace android
 
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 597d95c..9e7faee 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -203,8 +203,9 @@
     ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d",
             this, flags, previous.get(), getViewportHeight(), isIgnored(), !mClipArea->isSimple());
     const Rect& clipRect(mClipArea->getClipRect());
-    ALOGD("  ClipRect %.1f %.1f %.1f %.1f",
-            clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+    ALOGD("  ClipRect %.1f %.1f %.1f %.1f, clip simple %d",
+            clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, mClipArea->isSimple());
+
     ALOGD("  Transform (at %p):", transform);
     transform->dump();
 }
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 66de333..d9d06bf 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -380,6 +380,7 @@
         const Vector3& lightCenter, float lightRadius) {
     ShadowDescription key(casterPerimeter, drawTransform);
 
+    if (mShadowCache.get(key)) return;
     sp<ShadowTask> task = new ShadowTask(drawTransform, localClip, opaque,
             casterPerimeter, transformXY, transformZ, lightCenter, lightRadius);
     if (mShadowProcessor == nullptr) {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 9456073..9237151 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -41,15 +41,10 @@
         RenderNode* rootRenderNode, IContextFactory* contextFactory)
         : mRenderThread(thread)
         , mEglManager(thread.eglManager())
-        , mEglSurface(EGL_NO_SURFACE)
-        , mBufferPreserved(false)
-        , mSwapBehavior(kSwap_default)
         , mOpaque(!translucent)
-        , mCanvas(nullptr)
-        , mHaveNewSurface(false)
         , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
         , mRootRenderNode(rootRenderNode)
-        , mCurrentFrameInfo(nullptr) {
+        , mJankTracker(thread.timeLord().frameIntervalNanos()) {
     mRenderThread.renderState().registerCanvasContext(this);
     mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
 }
@@ -258,6 +253,7 @@
 
     // TODO: Use a fence for real completion?
     mCurrentFrameInfo->markFrameCompleted();
+    mJankTracker.addFrame(*mCurrentFrameInfo);
     mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo);
     profiler().finishFrame();
 }
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index c3904c2..f5f1f54 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -127,23 +127,24 @@
     RenderThread& mRenderThread;
     EglManager& mEglManager;
     sp<ANativeWindow> mNativeWindow;
-    EGLSurface mEglSurface;
-    bool mBufferPreserved;
-    SwapBehavior mSwapBehavior;
+    EGLSurface mEglSurface = EGL_NO_SURFACE;
+    bool mBufferPreserved = false;
+    SwapBehavior mSwapBehavior = kSwap_default;
 
     bool mOpaque;
-    OpenGLRenderer* mCanvas;
-    bool mHaveNewSurface;
+    OpenGLRenderer* mCanvas = nullptr;
+    bool mHaveNewSurface = false;
     DamageAccumulator mDamageAccumulator;
     std::unique_ptr<AnimationContext> mAnimationContext;
 
     const sp<RenderNode> mRootRenderNode;
 
     DrawProfiler mProfiler;
-    FrameInfo* mCurrentFrameInfo;
+    FrameInfo* mCurrentFrameInfo = nullptr;
     // Ring buffer large enough for 1 second worth of frames
     RingBuffer<FrameInfo, 60> mFrames;
     std::string mName;
+    JankTracker mJankTracker;
 
     std::set<RenderNode*> mPrefetechedLayers;
 };
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 0091790..cc87241 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -441,6 +441,19 @@
     post(task);
 }
 
+CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
+    args->thread->jankTracker().switchStorageToAshmem(args->fd);
+    close(args->fd);
+    return nullptr;
+}
+
+void RenderProxy::setProcessStatsBuffer(int fd) {
+    SETUP_TASK(setProcessStatsBuffer);
+    args->thread = &mRenderThread;
+    args->fd = dup(fd);
+    post(task);
+}
+
 void RenderProxy::post(RenderTask* task) {
     mRenderThread.queue(task);
 }
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 43cbe07..29c6f08 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -99,6 +99,7 @@
     ANDROID_API static void dumpGraphicsMemory(int fd);
 
     ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
+    ANDROID_API void setProcessStatsBuffer(int fd);
 
 private:
     RenderThread& mRenderThread;
diff --git a/libs/hwui/thread/Signal.h b/libs/hwui/thread/Signal.h
index dcf5449..d4cfeeb 100644
--- a/libs/hwui/thread/Signal.h
+++ b/libs/hwui/thread/Signal.h
@@ -30,8 +30,10 @@
     ~Signal() { }
 
     void signal() {
-        Mutex::Autolock l(mLock);
-        mSignaled = true;
+        {
+            Mutex::Autolock l(mLock);
+            mSignaled = true;
+        }
         mCondition.signal(mType);
     }
 
diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp
index c69b2fd..f0ed0bb 100644
--- a/libs/hwui/thread/TaskManager.cpp
+++ b/libs/hwui/thread/TaskManager.cpp
@@ -109,8 +109,11 @@
         return false;
     }
 
-    Mutex::Autolock l(mLock);
-    ssize_t index = mTasks.add(task);
+    ssize_t index;
+    {
+        Mutex::Autolock l(mLock);
+        index = mTasks.add(task);
+    }
     mSignal.signal();
 
     return index >= 0;
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 9a0266d..3c973a2 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -38,6 +38,7 @@
     public static final int ENCODING_DEFAULT = 1;
 
     // These values must be kept in sync with core/jni/android_media_AudioFormat.h
+    // Also sync av/services/audiopolicy/managerdefault/ConfigParsingUtils.h
     /** Audio data format: PCM 16 bit per sample. Guaranteed to be supported by devices. */
     public static final int ENCODING_PCM_16BIT = 2;
     /** Audio data format: PCM 8 bit per sample. Not guaranteed to be supported by devices. */
@@ -48,6 +49,10 @@
     public static final int ENCODING_AC3 = 5;
     /** Audio data format: E-AC-3 compressed */
     public static final int ENCODING_E_AC3 = 6;
+    /** Audio data format: DTS compressed */
+    public static final int ENCODING_DTS = 7;
+    /** Audio data format: DTS HD compressed */
+    public static final int ENCODING_DTS_HD = 8;
 
     /** Invalid audio channel configuration */
     /** @deprecated use CHANNEL_INVALID instead  */
@@ -68,7 +73,7 @@
     public static final int CHANNEL_OUT_DEFAULT = 1;
 
     // Output channel mask definitions below are translated to the native values defined in
-    //  in /system/core/include/system/audio.h in the JNI code of AudioTrack
+    //  in /system/media/audio/include/system/audio.h in the JNI code of AudioTrack
     public static final int CHANNEL_OUT_FRONT_LEFT = 0x4;
     public static final int CHANNEL_OUT_FRONT_RIGHT = 0x8;
     public static final int CHANNEL_OUT_FRONT_CENTER = 0x10;
@@ -235,6 +240,8 @@
         case ENCODING_PCM_FLOAT:
         case ENCODING_AC3:
         case ENCODING_E_AC3:
+        case ENCODING_DTS:
+        case ENCODING_DTS_HD:
             return true;
         default:
             return false;
@@ -252,6 +259,8 @@
             return true;
         case ENCODING_AC3:
         case ENCODING_E_AC3:
+        case ENCODING_DTS:
+        case ENCODING_DTS_HD:
             return false;
         case ENCODING_INVALID:
         default:
@@ -400,6 +409,8 @@
          *     {@link AudioFormat#ENCODING_PCM_FLOAT},
          *     {@link AudioFormat#ENCODING_AC3},
          *     {@link AudioFormat#ENCODING_E_AC3}.
+         *     {@link AudioFormat#ENCODING_DTS},
+         *     {@link AudioFormat#ENCODING_DTS_HD}.
          * @return the same Builder instance.
          * @throws java.lang.IllegalArgumentException
          */
@@ -413,6 +424,8 @@
                 case ENCODING_PCM_FLOAT:
                 case ENCODING_AC3:
                 case ENCODING_E_AC3:
+                case ENCODING_DTS:
+                case ENCODING_DTS_HD:
                     mEncoding = encoding;
                     break;
                 case ENCODING_INVALID:
@@ -478,7 +491,9 @@
         ENCODING_PCM_16BIT,
         ENCODING_PCM_FLOAT,
         ENCODING_AC3,
-        ENCODING_E_AC3
+        ENCODING_E_AC3,
+        ENCODING_DTS,
+        ENCODING_DTS_HD
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Encoding {}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 28941b9..cb70e8b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -134,6 +134,22 @@
     public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
 
     /**
+     * @hide Broadcast intent when the devices for a particular stream type changes.
+     * Includes the stream, the new devices and previous devices.
+     * Notes:
+     *  - for internal platform use only, do not make public,
+     *  - never used for "remote" volume changes
+     *
+     * @see #EXTRA_VOLUME_STREAM_TYPE
+     * @see #EXTRA_VOLUME_STREAM_DEVICES
+     * @see #EXTRA_PREV_VOLUME_STREAM_DEVICES
+     * @see #getDevicesForStream
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String STREAM_DEVICES_CHANGED_ACTION =
+        "android.media.STREAM_DEVICES_CHANGED_ACTION";
+
+    /**
      * @hide Broadcast intent when a stream mute state changes.
      * Includes the stream that changed and the new mute state
      *
@@ -196,6 +212,18 @@
         "android.media.EXTRA_PREV_VOLUME_STREAM_VALUE";
 
     /**
+     * @hide The devices associated with the stream for the stream devices changed intent.
+     */
+    public static final String EXTRA_VOLUME_STREAM_DEVICES =
+        "android.media.EXTRA_VOLUME_STREAM_DEVICES";
+
+    /**
+     * @hide The previous devices associated with the stream for the stream devices changed intent.
+     */
+    public static final String EXTRA_PREV_VOLUME_STREAM_DEVICES =
+        "android.media.EXTRA_PREV_VOLUME_STREAM_DEVICES";
+
+    /**
      * @hide The new master volume mute state for the master mute changed intent.
      * Value is boolean
      */
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
index c05fd77..c49e8c2 100644
--- a/media/java/android/media/AudioPortEventHandler.java
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -40,6 +40,12 @@
     private static final int AUDIOPORT_EVENT_SERVICE_DIED = 3;
     private static final int AUDIOPORT_EVENT_NEW_LISTENER = 4;
 
+    /**
+     * Accessed by native methods: JNI Callback context.
+     */
+    @SuppressWarnings("unused")
+    private long mJniCallback;
+
     void init() {
         synchronized (this) {
             if (mHandler != null) {
@@ -63,9 +69,6 @@
                                 listeners = mListeners;
                             }
                         }
-                        if (listeners.isEmpty()) {
-                            return;
-                        }
                         // reset audio port cache if the event corresponds to a change coming
                         // from audio policy service or if mediaserver process died.
                         if (msg.what == AUDIOPORT_EVENT_PORT_LIST_UPDATED ||
@@ -73,6 +76,11 @@
                                 msg.what == AUDIOPORT_EVENT_SERVICE_DIED) {
                             AudioManager.resetAudioPortGeneration();
                         }
+
+                        if (listeners.isEmpty()) {
+                            return;
+                        }
+
                         ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
                         ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
                         if (msg.what != AUDIOPORT_EVENT_SERVICE_DIED) {
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 259fe37..99b7bee 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -20,6 +20,7 @@
 import java.nio.ByteBuffer;
 import java.util.Iterator;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Binder;
 import android.os.Handler;
@@ -313,8 +314,14 @@
 
         audioParamCheck(attributes.getCapturePreset(), rate, encoding);
 
-        mChannelCount = AudioFormat.channelCountFromInChannelMask(format.getChannelMask());
-        mChannelMask = getChannelMaskFromLegacyConfig(format.getChannelMask(), false);
+        int channelMask = AudioFormat.CHANNEL_IN_DEFAULT;
+        if ((format.getPropertySetMask()
+                & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0)
+        {
+            channelMask = format.getChannelMask();
+        }
+        mChannelCount = AudioFormat.channelCountFromInChannelMask(channelMask);
+        mChannelMask = getChannelMaskFromLegacyConfig(channelMask, false);
 
         audioBuffSizeCheck(bufferSizeInBytes);
 
@@ -335,6 +342,161 @@
         mState = STATE_INITIALIZED;
     }
 
+    /**
+     * Builder class for {@link AudioRecord} objects.
+     * Use this class to configure and create an <code>AudioRecord</code> instance. By setting the
+     * recording preset (a.k.a. recording source) and audio format parameters, you indicate which of
+     *  those vary from the default behavior on the device.
+     * <p> Here is an example where <code>Builder</code> is used to specify all {@link AudioFormat}
+     * parameters, to be used by a new <code>AudioRecord</code> instance:
+     *
+     * <pre class="prettyprint">
+     * AudioRecord recorder = new AudioRecord.Builder()
+     *         .setCapturePreset(MediaRecorder.AudioSource.VOICE_COMMUNICATION)
+     *         .setAudioFormat(new AudioFormat.Builder()
+     *                 .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+     *                 .setSampleRate(32000)
+     *                 .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
+     *                 .build())
+     *         .setBufferSize(2*minBuffSize)
+     *         .build();
+     * </pre>
+     * <p>
+     * If the capture preset is not set with {@link #setCapturePreset(int)},
+     * {@link MediaRecorder.AudioSource#DEFAULT} is used.
+     * <br>If the audio format is not specified or is incomplete, its sample rate will be the
+     * default output sample rate of the device (see
+     * {@link AudioManager#PROPERTY_OUTPUT_SAMPLE_RATE}), its channel configuration will be
+     * {@link AudioFormat#CHANNEL_IN_DEFAULT}.
+     * <br>Failing to set an adequate buffer size with {@link #setBufferSizeInBytes(int)} will
+     * prevent the successful creation of an <code>AudioRecord</code> instance.
+     */
+    public static class Builder {
+        private AudioAttributes mAttributes;
+        private AudioFormat mFormat;
+        private int mBufferSizeInBytes;
+        private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
+
+        /**
+         * Constructs a new Builder with the default values as described above.
+         */
+        public Builder() {
+        }
+
+        /**
+         * @param preset the capture preset (also referred to as the recording source).
+         * See {@link MediaRecorder.AudioSource} for the supported capture preset definitions.
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        public Builder setCapturePreset(int preset) throws IllegalArgumentException {
+            if ( (preset < MediaRecorder.AudioSource.DEFAULT) ||
+                    (preset > MediaRecorder.getAudioSourceMax()) ) {
+                throw new IllegalArgumentException("Invalid audio source " + preset);
+            }
+            mAttributes = new AudioAttributes.Builder()
+                    .setInternalCapturePreset(preset)
+                    .build();
+            return this;
+        }
+
+        /**
+         * @hide
+         * To be only used by system components. Allows specifying non-public capture presets
+         * @param attributes a non-null {@link AudioAttributes} instance that contains the capture
+         *     preset to be used.
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        @SystemApi
+        public Builder setAudioAttributes(@NonNull AudioAttributes attributes)
+                throws IllegalArgumentException {
+            if (attributes == null) {
+                throw new IllegalArgumentException("Illegal null AudioAttributes argument");
+            }
+            if (attributes.getCapturePreset() == MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID) {
+                throw new IllegalArgumentException(
+                        "No valid capture preset in AudioAttributes argument");
+            }
+            // keep reference, we only copy the data when building
+            mAttributes = attributes;
+            return this;
+        }
+
+        /**
+         * Sets the format of the audio data to be captured.
+         * @param format a non-null {@link AudioFormat} instance
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        public Builder setAudioFormat(@NonNull AudioFormat format) throws IllegalArgumentException {
+            if (format == null) {
+                throw new IllegalArgumentException("Illegal null AudioFormat argument");
+            }
+            // keep reference, we only copy the data when building
+            mFormat = format;
+            return this;
+        }
+
+        /**
+         * Sets the total size (in bytes) of the buffer where audio data is written
+         * during the recording. New audio data can be read from this buffer in smaller chunks
+         * than this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum
+         * required buffer size for the successful creation of an AudioRecord instance.
+         * Using values smaller than getMinBufferSize() will result in an initialization failure.
+         * @param bufferSizeInBytes a value strictly greater than 0
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        public Builder setBufferSizeInBytes(int bufferSizeInBytes) throws IllegalArgumentException {
+            if (bufferSizeInBytes <= 0) {
+                throw new IllegalArgumentException("Invalid buffer size " + bufferSizeInBytes);
+            }
+            mBufferSizeInBytes = bufferSizeInBytes;
+            return this;
+        }
+
+        /**
+         * @hide
+         * To be only used by system components.
+         * @param sessionId ID of audio session the AudioRecord must be attached to, or
+         *     {@link AudioManager#AUDIO_SESSION_ID_GENERATE} if the session isn't known at
+         *     construction time.
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        @SystemApi
+        public Builder setSessionId(int sessionId) throws IllegalArgumentException {
+            if (sessionId < 0) {
+                throw new IllegalArgumentException("Invalid session ID " + sessionId);
+            }
+            mSessionId = sessionId;
+            return this;
+        }
+
+        /**
+         * @return a new {@link AudioRecord} instance initialized with all the parameters set
+         *     on this <code>Builder</code>
+         * @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
+         *     were incompatible, or if they are not supported by the device.
+         */
+        public AudioRecord build() throws UnsupportedOperationException {
+            if (mFormat == null) {
+                mFormat = new AudioFormat.Builder().build();
+            }
+            if (mAttributes == null) {
+                mAttributes = new AudioAttributes.Builder()
+                        .setInternalCapturePreset(MediaRecorder.AudioSource.DEFAULT)
+                        .build();
+            }
+            try {
+                return new AudioRecord(mAttributes, mFormat, mBufferSizeInBytes, mSessionId);
+            } catch (IllegalArgumentException e) {
+                throw new UnsupportedOperationException(e.getMessage());
+            }
+        }
+    }
+
     // Convenience method for the constructor's parameter checks.
     // This, getChannelMaskFromLegacyConfig and audioBuffSizeCheck are where constructor
     // IllegalArgumentException-s are thrown
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 787320e..25e6594 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -123,7 +123,7 @@
     /** @deprecated */
     @Deprecated public static final int ROUTE_ALL               = 0xFFFFFFFF;
 
-    // Keep in sync with system/core/include/system/audio.h
+    // Keep in sync with system/media/audio/include/system/audio.h
     public static final int AUDIO_SESSION_ALLOCATE = 0;
 
     /*
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 93e2cbe..98bfaff 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -21,7 +21,10 @@
 import java.lang.ref.WeakReference;
 import java.nio.ByteBuffer;
 import java.nio.NioUtils;
+
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.app.AppOpsManager;
 import android.content.Context;
@@ -113,6 +116,14 @@
      */
     public static final int MODE_STREAM = 1;
 
+    /** @hide */
+    @IntDef({
+        MODE_STATIC,
+        MODE_STREAM
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TransferMode {}
+
     /**
      * State of an AudioTrack that was not successfully initialized upon creation.
      */
@@ -457,6 +468,179 @@
         }
     }
 
+    /**
+     * Builder class for {@link AudioTrack} objects.
+     * Use this class to configure and create an <code>AudioTrack</code> instance. By setting audio
+     * attributes and audio format parameters, you indicate which of those vary from the default
+     * behavior on the device.
+     * <p> Here is an example where <code>Builder</code> is used to specify all {@link AudioFormat}
+     * parameters, to be used by a new <code>AudioTrack</code> instance:
+     *
+     * <pre class="prettyprint">
+     * AudioTrack player = new AudioTrack.Builder()
+     *         .setAudioAttributes(new AudioAttributes.Builder()
+     *                  .setUsage(AudioAttributes.USAGE_ALARM)
+     *                  .setContentType(CONTENT_TYPE_MUSIC)
+     *                  .build())
+     *         .setAudioFormat(new AudioFormat.Builder()
+     *                 .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+     *                 .setSampleRate(441000)
+     *                 .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
+     *                 .build())
+     *         .setBufferSize(minBuffSize)
+     *         .build();
+     * </pre>
+     * <p>
+     * If the audio attributes are not set with {@link #setAudioAttributes(AudioAttributes)},
+     * attributes comprising {@link AudioAttributes#USAGE_MEDIA} will be used.
+     * <br>If the audio format is not specified or is incomplete, its sample rate will be the
+     * default output sample rate of the device (see
+     * {@link AudioManager#PROPERTY_OUTPUT_SAMPLE_RATE}), its channel configuration will be
+     * {@link AudioFormat#CHANNEL_OUT_STEREO} and the encoding will be
+     * {@link AudioFormat#ENCODING_PCM_16BIT}.
+     * <br>If the transfer mode is not specified with {@link #setTransferMode(int)},
+     * {@link AudioTrack#MODE_STREAM} will be used.
+     * <br>If the session ID is not specified with {@link #setSessionId(int)}, a new one will
+     * be generated.
+     */
+    public static class Builder {
+        private AudioAttributes mAttributes;
+        private AudioFormat mFormat;
+        private int mBufferSizeInBytes;
+        private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
+        private int mMode = MODE_STREAM;
+
+        /**
+         * Constructs a new Builder with the default values as described above.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Sets the {@link AudioAttributes}.
+         * @param attributes a non-null {@link AudioAttributes} instance that describes the audio
+         *     data to be played.
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes attributes)
+                throws IllegalArgumentException {
+            if (attributes == null) {
+                throw new IllegalArgumentException("Illegal null AudioAttributes argument");
+            }
+            // keep reference, we only copy the data when building
+            mAttributes = attributes;
+            return this;
+        }
+
+        /**
+         * Sets the format of the audio data to be played by the {@link AudioTrack}.
+         * See {@link AudioFormat.Builder} for configuring the audio format parameters such
+         * as encoding, channel mask and sample rate.
+         * @param format a non-null {@link AudioFormat} instance.
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        public @NonNull Builder setAudioFormat(@NonNull AudioFormat format)
+                throws IllegalArgumentException {
+            if (format == null) {
+                throw new IllegalArgumentException("Illegal null AudioFormat argument");
+            }
+            // keep reference, we only copy the data when building
+            mFormat = format;
+            return this;
+        }
+
+        /**
+         * Sets the total size (in bytes) of the buffer where audio data is read from for playback.
+         * If using the {@link AudioTrack} in streaming mode
+         * (see {@link AudioTrack#MODE_STREAM}, you can write data into this buffer in smaller
+         * chunks than this size. See {@link #getMinBufferSize(int, int, int)} to determine
+         * the minimum required buffer size for the successful creation of an AudioTrack instance
+         * in streaming mode. Using values smaller than <code>getMinBufferSize()</code> will result
+         * in an exception when trying to build the <code>AudioTrack</code>.
+         * <br>If using the <code>AudioTrack</code> in static mode (see
+         * {@link AudioTrack#MODE_STATIC}), this is the maximum size of the sound that will be
+         * played by this instance.
+         * @param bufferSizeInBytes
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        public @NonNull Builder setBufferSizeInBytes(int bufferSizeInBytes)
+                throws IllegalArgumentException {
+            if (bufferSizeInBytes <= 0) {
+                throw new IllegalArgumentException("Invalid buffer size " + bufferSizeInBytes);
+            }
+            mBufferSizeInBytes = bufferSizeInBytes;
+            return this;
+        }
+
+        /**
+         * Sets the mode under which buffers of audio data are transferred from the
+         * {@link AudioTrack} to the framework.
+         * @param mode one of {@link AudioTrack#MODE_STREAM}, {@link AudioTrack#MODE_STATIC}.
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        public @NonNull Builder setTransferMode(@TransferMode int mode)
+                throws IllegalArgumentException {
+            switch(mode) {
+                case MODE_STREAM:
+                case MODE_STATIC:
+                    mMode = mode;
+                    break;
+                default:
+                    throw new IllegalArgumentException("Invalid transfer mode " + mode);
+            }
+            return this;
+        }
+
+        /**
+         * Sets the session ID the {@link AudioTrack} will be attached to.
+         * @param sessionId a strictly positive ID number retrieved from another
+         *     <code>AudioTrack</code> via {@link AudioTrack#getAudioSessionId()} or allocated by
+         *     {@link AudioManager} via {@link AudioManager#generateAudioSessionId()}, or
+         *     {@link AudioManager#AUDIO_SESSION_ID_GENERATE}.
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        public @NonNull Builder setSessionId(int sessionId)
+                throws IllegalArgumentException {
+            if ((sessionId != AudioManager.AUDIO_SESSION_ID_GENERATE) && (sessionId < 1)) {
+                throw new IllegalArgumentException("Invalid audio session ID " + sessionId);
+            }
+            mSessionId = sessionId;
+            return this;
+        }
+
+        /**
+         * Builds an {@link AudioTrack} instance initialized with all the parameters set
+         * on this <code>Builder</code>.
+         * @return a new {@link AudioTrack} instance.
+         * @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
+         *     were incompatible, or if they are not supported by the device.
+         */
+        public @NonNull AudioTrack build() throws UnsupportedOperationException {
+            if (mAttributes == null) {
+                mAttributes = new AudioAttributes.Builder()
+                        .setUsage(AudioAttributes.USAGE_MEDIA)
+                        .build();
+            }
+            if (mFormat == null) {
+                mFormat = new AudioFormat.Builder()
+                        .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
+                        .setSampleRate(AudioSystem.getPrimaryOutputSamplingRate())
+                        .setEncoding(AudioFormat.ENCODING_DEFAULT)
+                        .build();
+            }
+            try {
+                return new AudioTrack(mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId);
+            } catch (IllegalArgumentException e) {
+                throw new UnsupportedOperationException(e.getMessage());
+            }
+        }
+    }
+
     // mask of all the channels supported by this implementation
     private static final int SUPPORTED_OUT_CHANNELS =
             AudioFormat.CHANNEL_OUT_FRONT_LEFT |
@@ -1749,5 +1933,4 @@
     private static void loge(String msg) {
         Log.e(TAG, msg);
     }
-
 }
diff --git a/media/java/android/media/MediaDescription.java b/media/java/android/media/MediaDescription.java
index ddbffc2..afc3ca7 100644
--- a/media/java/android/media/MediaDescription.java
+++ b/media/java/android/media/MediaDescription.java
@@ -41,9 +41,13 @@
      * Extras for opaque use by apps/system.
      */
     private final Bundle mExtras;
+    /**
+     * A Uri to identify this content.
+     */
+    private final Uri mMediaUri;
 
     private MediaDescription(String mediaId, CharSequence title, CharSequence subtitle,
-            CharSequence description, Bitmap icon, Uri iconUri, Bundle extras) {
+            CharSequence description, Bitmap icon, Uri iconUri, Bundle extras, Uri mediaUri) {
         mMediaId = mediaId;
         mTitle = title;
         mSubtitle = subtitle;
@@ -51,6 +55,7 @@
         mIcon = icon;
         mIconUri = iconUri;
         mExtras = extras;
+        mMediaUri = mediaUri;
     }
 
     private MediaDescription(Parcel in) {
@@ -61,6 +66,7 @@
         mIcon = in.readParcelable(null);
         mIconUri = in.readParcelable(null);
         mExtras = in.readBundle();
+        mMediaUri = in.readParcelable(null);
     }
 
     /**
@@ -125,6 +131,15 @@
         return mExtras;
     }
 
+    /**
+     * Returns a Uri representing this content or null.
+     *
+     * @return A media Uri or null.
+     */
+    public @Nullable Uri getMediaUri() {
+        return mMediaUri;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -139,6 +154,7 @@
         dest.writeParcelable(mIcon, flags);
         dest.writeParcelable(mIconUri, flags);
         dest.writeBundle(mExtras);
+        dest.writeParcelable(mMediaUri, flags);
     }
 
     @Override
@@ -170,6 +186,7 @@
         private Bitmap mIcon;
         private Uri mIconUri;
         private Bundle mExtras;
+        private Uri mMediaUri;
 
         /**
          * Creates an initially empty builder.
@@ -257,9 +274,20 @@
             return this;
         }
 
+        /**
+         * Sets the media uri.
+         *
+         * @param mediaUri The content's {@link Uri} for the item or null.
+         * @return this
+         */
+        public Builder setMediaUri(@Nullable Uri mediaUri) {
+            mMediaUri = mediaUri;
+            return this;
+        }
+
         public MediaDescription build() {
             return new MediaDescription(mMediaId, mTitle, mSubtitle, mDescription, mIcon, mIconUri,
-                    mExtras);
+                    mExtras, mMediaUri);
         }
     }
 }
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index d77fcd8..83954ae 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2602,15 +2602,21 @@
                 return;
 
             case MEDIA_STOPPED:
-                if (mTimeProvider != null) {
-                    mTimeProvider.onStopped();
+                {
+                    TimeProvider timeProvider = mTimeProvider;
+                    if (timeProvider != null) {
+                        timeProvider.onStopped();
+                    }
                 }
                 break;
 
             case MEDIA_STARTED:
             case MEDIA_PAUSED:
-                if (mTimeProvider != null) {
-                    mTimeProvider.onPaused(msg.what == MEDIA_PAUSED);
+                {
+                    TimeProvider timeProvider = mTimeProvider;
+                    if (timeProvider != null) {
+                        timeProvider.onPaused(msg.what == MEDIA_PAUSED);
+                    }
                 }
                 break;
 
@@ -2620,21 +2626,26 @@
                 return;
 
             case MEDIA_SEEK_COMPLETE:
-              if (mOnSeekCompleteListener != null) {
-                  mOnSeekCompleteListener.onSeekComplete(mMediaPlayer);
-              }
-              // fall through
+                if (mOnSeekCompleteListener != null) {
+                    mOnSeekCompleteListener.onSeekComplete(mMediaPlayer);
+                }
+                // fall through
 
             case MEDIA_SKIPPED:
-              if (mTimeProvider != null) {
-                  mTimeProvider.onSeekComplete(mMediaPlayer);
-              }
-              return;
+                {
+                    TimeProvider timeProvider = mTimeProvider;
+                    if (timeProvider != null) {
+                        timeProvider.onSeekComplete(mMediaPlayer);
+                    }
+                }
+                return;
 
             case MEDIA_SET_VIDEO_SIZE:
-              if (mOnVideoSizeChangedListener != null)
-                  mOnVideoSizeChangedListener.onVideoSizeChanged(mMediaPlayer, msg.arg1, msg.arg2);
-              return;
+                if (mOnVideoSizeChangedListener != null) {
+                    mOnVideoSizeChangedListener.onVideoSizeChanged(
+                        mMediaPlayer, msg.arg1, msg.arg2);
+                }
+                return;
 
             case MEDIA_ERROR:
                 Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 58c86f2..876aebc 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -157,8 +157,11 @@
     }
 
     /**
-     * Defines the audio source. These constants are used with
-     * {@link MediaRecorder#setAudioSource(int)}.
+     * Defines the audio source.
+     * An audio source defines both a default physical source of audio signal, and a recording
+     * configuration; it's also known as a capture preset. These constants are for instance used
+     * in {@link MediaRecorder#setAudioSource(int)} or
+     * {@link AudioRecord.Builder#setCapturePreset(int)}.
      */
     public final class AudioSource {
 
@@ -168,7 +171,7 @@
         public final static int AUDIO_SOURCE_INVALID = -1;
 
       /* Do not change these values without updating their counterparts
-       * in system/core/include/system/audio.h!
+       * in system/media/audio/include/system/audio.h!
        */
 
         /** Default audio source **/
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index b4c612a..c227eb7 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -1500,18 +1500,18 @@
 
         /**
          * The default playback type, "local", indicating the presentation of the media is happening
-         * on the same device (e.g. a phone, a tablet) as where it is controlled from.
+         * on the same device (e&#46;g&#46; a phone, a tablet) as where it is controlled from.
          * @see #getPlaybackType()
          */
         public final static int PLAYBACK_TYPE_LOCAL = 0;
         /**
          * A playback type indicating the presentation of the media is happening on
-         * a different device (i.e. the remote device) than where it is controlled from.
+         * a different device (i&#46;e&#46; the remote device) than where it is controlled from.
          * @see #getPlaybackType()
          */
         public final static int PLAYBACK_TYPE_REMOTE = 1;
         /**
-         * Playback information indicating the playback volume is fixed, i.e. it cannot be
+         * Playback information indicating the playback volume is fixed, i&#46;e&#46; it cannot be
          * controlled from this object. An example of fixed playback volume is a remote player,
          * playing over HDMI where the user prefers to control the volume on the HDMI sink, rather
          * than attenuate at the source.
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 1255276..9ea6722 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -553,15 +553,8 @@
                         boolean isimage = MediaFile.isImageFileType(mFileType);
 
                         if (isaudio || isvideo || isimage) {
-                            if (mExternalIsEmulated && path.startsWith(mExternalStoragePath)) {
-                                // try to rewrite the path to bypass the sd card fuse layer
-                                String directPath = Environment.getMediaStorageDirectory() +
-                                        path.substring(mExternalStoragePath.length());
-                                File f = new File(directPath);
-                                if (f.exists()) {
-                                    path = directPath;
-                                }
-                            }
+                            path = Environment.maybeTranslateEmulatedPathToInternal(new File(path))
+                                    .getAbsolutePath();
                         }
 
                         // we only extract metadata for audio and video files
diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java
new file mode 100644
index 0000000..e87647d
--- /dev/null
+++ b/media/java/android/media/MediaSync.java
@@ -0,0 +1,526 @@
+/*
+ * 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.media;
+
+import android.annotation.IntDef;
+import android.media.AudioTrack;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.view.Surface;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * MediaSync class can be used to synchronously playback audio and video streams.
+ * It can be used to play audio-only or video-only stream, too.
+ *
+ * <p>MediaSync is generally used like this:
+ * <pre>
+ * MediaSync sync = new MediaSync();
+ * sync.configureSurface(surface);
+ * Surface inputSurface = sync.createInputSurface();
+ * ...
+ * // MediaCodec videoDecoder = ...;
+ * videoDecoder.configure(format, inputSurface, ...);
+ * ...
+ * sync.configureAudioTrack(audioTrack, nativeSampleRateInHz);
+ * sync.setCallback(new MediaSync.Callback() {
+ *     \@Override
+ *     public void onReturnAudioBuffer(MediaSync sync, ByteBuffer audioBuffer, int bufferIndex) {
+ *         ...
+ *     }
+ * });
+ * // This needs to be done since sync is paused on creation.
+ * sync.setPlaybackRate(1.0f, MediaSync.PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+ *
+ * for (;;) {
+ *   ...
+ *   // send video frames to surface for rendering, e.g., call
+ *   // videoDecoder.releaseOutputBuffer(videoOutputBufferIx, videoPresentationTimeNs);
+ *   // More details are available as below.
+ *   ...
+ *   sync.queueAudio(audioByteBuffer, bufferIndex, size, audioPresentationTimeUs); // non-blocking.
+ *   // The audioByteBuffer and bufferIndex will be returned via callback.
+ *   // More details are available as below.
+ *   ...
+ *     ...
+ * }
+ * sync.setPlaybackRate(0.0f, MediaSync.PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+ * sync.release();
+ * sync = null;
+ *
+ * // The following code snippet illustrates how video/audio raw frames are created by
+ * // MediaCodec's, how they are fed to MediaSync and how they are returned by MediaSync.
+ * // This is the callback from MediaCodec.
+ * onOutputBufferAvailable(MediaCodec codec, int bufferIndex, BufferInfo info) {
+ *     // ...
+ *     if (codec == videoDecoder) {
+ *         // surface timestamp must contain media presentation time in nanoseconds.
+ *         codec.releaseOutputBuffer(bufferIndex, 1000 * info.presentationTime);
+ *     } else {
+ *         ByteBuffer audioByteBuffer = codec.getOutputBuffer(bufferIndex);
+ *         sync.queueByteBuffer(audioByteBuffer, bufferIndex, info.size, info.presentationTime);
+ *     }
+ *     // ...
+ * }
+ *
+ * // This is the callback from MediaSync.
+ * onReturnAudioBuffer(MediaSync sync, ByteBuffer buffer, int bufferIndex) {
+ *     // ...
+ *     audioDecoder.releaseBuffer(bufferIndex, false);
+ *     // ...
+ * }
+ *
+ * </pre>
+ *
+ * The client needs to configure corresponding sink (i.e., Surface and AudioTrack) based on
+ * the stream type it will play.
+ * <p>
+ * For video, the client needs to call {@link #createInputSurface} to obtain a surface on
+ * which it will render video frames.
+ * <p>
+ * For audio, the client needs to set up audio track correctly, e.g., using {@link
+ * AudioTrack#MODE_STREAM}. The audio buffers are sent to MediaSync directly via {@link
+ * #queueAudio}, and are returned to the client via {@link Callback#onReturnAudioBuffer}
+ * asynchronously. The client should not modify an audio buffer till it's returned.
+ * <p>
+ * The client can optionally pre-fill audio/video buffers by setting playback rate to 0.0,
+ * and then feed audio/video buffers to corresponding components. This can reduce possible
+ * initial underrun.
+ * <p>
+ */
+final public class MediaSync {
+    /**
+     * MediaSync callback interface. Used to notify the user asynchronously
+     * of various MediaSync events.
+     */
+    public static abstract class Callback {
+        /**
+         * Called when returning an audio buffer which has been consumed.
+         *
+         * @param sync The MediaSync object.
+         * @param audioBuffer The returned audio buffer.
+         */
+        public abstract void onReturnAudioBuffer(
+                MediaSync sync, ByteBuffer audioBuffer, int bufferIndex);
+    }
+
+    private static final String TAG = "MediaSync";
+
+    private static final int EVENT_CALLBACK = 1;
+    private static final int EVENT_SET_CALLBACK = 2;
+
+    private static final int CB_RETURN_AUDIO_BUFFER = 1;
+
+    private static class AudioBuffer {
+        public ByteBuffer mByteBuffer;
+        public int mBufferIndex;
+        public int mSizeInBytes;
+        long mPresentationTimeUs;
+
+        public AudioBuffer(ByteBuffer byteBuffer, int bufferIndex,
+                           int sizeInBytes, long presentationTimeUs) {
+            mByteBuffer = byteBuffer;
+            mBufferIndex = bufferIndex;
+            mSizeInBytes = sizeInBytes;
+            mPresentationTimeUs = presentationTimeUs;
+        }
+    }
+
+    private final Object mCallbackLock = new Object();
+    private Handler mCallbackHandler = null;
+    private MediaSync.Callback mCallback = null;
+
+    private int mNativeSampleRateInHz = 0;
+
+    private Thread mAudioThread = null;
+    // Created on mAudioThread when mAudioThread is started. When used on user thread, they should
+    // be guarded by checking mAudioThread.
+    private Handler mAudioHandler = null;
+    private Looper mAudioLooper = null;
+
+    private final Object mAudioLock = new Object();
+    private AudioTrack mAudioTrack = null;
+    private List<AudioBuffer> mAudioBuffers = new LinkedList<AudioBuffer>();
+    private float mPlaybackRate = 0.0f;
+
+    private long mNativeContext;
+
+    /**
+     * Class constructor. On creation, MediaSync is paused, i.e., playback rate is 0.0f.
+     */
+    public MediaSync() {
+        native_setup();
+    }
+
+    private native final void native_setup();
+
+    @Override
+    protected void finalize() {
+        native_finalize();
+    }
+
+    private native final void native_finalize();
+
+    /**
+     * Make sure you call this when you're done to free up any opened
+     * component instance instead of relying on the garbage collector
+     * to do this for you at some point in the future.
+     */
+    public final void release() {
+        returnAudioBuffers();
+        if (mAudioThread != null) {
+            if (mAudioLooper != null) {
+                mAudioLooper.quit();
+            }
+        }
+        setCallback(null, null);
+        native_release();
+    }
+
+    private native final void native_release();
+
+    /**
+     * Sets an asynchronous callback for actionable MediaSync events.
+     * It shouldn't be called inside callback.
+     *
+     * @param cb The callback that will run.
+     * @param handler The Handler that will run the callback. Using null means to use MediaSync's
+     *     internal handler if it exists.
+     */
+    public void setCallback(/* MediaSync. */ Callback cb, Handler handler) {
+        synchronized(mCallbackLock) {
+            if (handler != null) {
+                mCallbackHandler = handler;
+            } else {
+                Looper looper;
+                if ((looper = Looper.myLooper()) == null) {
+                    looper = Looper.getMainLooper();
+                }
+                if (looper == null) {
+                    mCallbackHandler = null;
+                } else {
+                    mCallbackHandler = new Handler(looper);
+                }
+            }
+
+            mCallback = cb;
+        }
+    }
+
+    /**
+     * Configures the output surface for MediaSync.
+     *
+     * @param surface Specify a surface on which to render the video data.
+     * @throws IllegalArgumentException if the surface has been released, or is invalid.
+     *     or can not be connected.
+     * @throws IllegalStateException if not in the Initialized state, or another surface
+     *     has already been configured.
+     */
+    public void configureSurface(Surface surface) {
+        native_configureSurface(surface);
+    }
+
+    private native final void native_configureSurface(Surface surface);
+
+    /**
+     * Configures the audio track for MediaSync.
+     *
+     * @param audioTrack Specify an AudioTrack through which to render the audio data.
+     * @throws IllegalArgumentException if the audioTrack has been released, or is invalid,
+     *     or nativeSampleRateInHz is invalid.
+     * @throws IllegalStateException if not in the Initialized state, or another audio track
+     *     has already been configured.
+     */
+    public void configureAudioTrack(AudioTrack audioTrack, int nativeSampleRateInHz) {
+        if (audioTrack != null && nativeSampleRateInHz <= 0) {
+            final String msg = "Native sample rate " + nativeSampleRateInHz + " is invalid";
+            throw new IllegalArgumentException(msg);
+        }
+        native_configureAudioTrack(audioTrack, nativeSampleRateInHz);
+        mAudioTrack = audioTrack;
+        mNativeSampleRateInHz = nativeSampleRateInHz;
+        if (mAudioThread == null) {
+            createAudioThread();
+        }
+    }
+
+    private native final void native_configureAudioTrack(
+            AudioTrack audioTrack, int nativeSampleRateInHz);
+
+    /**
+     * Requests a Surface to use as the input. This may only be called after
+     * {@link #configureSurface}.
+     * <p>
+     * The application is responsible for calling release() on the Surface when
+     * done.
+     * @throws IllegalStateException if not configured, or another input surface has
+     *     already been created.
+     */
+    public native final Surface createInputSurface();
+
+    /**
+     * Specifies resampling as audio mode for variable rate playback, i.e.,
+     * resample the waveform based on the requested playback rate to get
+     * a new waveform, and play back the new waveform at the original sampling
+     * frequency.
+     * When rate is larger than 1.0, pitch becomes higher.
+     * When rate is smaller than 1.0, pitch becomes lower.
+     */
+    public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0;
+
+    /**
+     * Specifies time stretching as audio mode for variable rate playback.
+     * Time stretching changes the duration of the audio samples without
+     * affecting its pitch.
+     * FIXME: implement time strectching.
+     * @hide
+     */
+    public static final int PLAYBACK_RATE_AUDIO_MODE_STRETCH = 1;
+
+    /** @hide */
+    @IntDef(
+        value = {
+            PLAYBACK_RATE_AUDIO_MODE_RESAMPLE,
+            PLAYBACK_RATE_AUDIO_MODE_STRETCH })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PlaybackRateAudioMode {}
+
+    /**
+     * Sets playback rate. It does same as {@link #setPlaybackRate(float, int)},
+     * except that it always uses {@link #PLAYBACK_RATE_AUDIO_MODE_STRETCH} for audioMode.
+     *
+     * @param rate the ratio between desired playback rate and normal one. 1.0 means normal
+     *     playback speed. 0.0 means stop or pause. Value larger than 1.0 means faster playback,
+     *     while value between 0.0 and 1.0 for slower playback.
+     *
+     * @throws IllegalStateException if the internal sync engine or the audio track has not
+     *     been initialized.
+     * TODO: unhide when PLAYBACK_RATE_AUDIO_MODE_STRETCH is supported.
+     * @hide
+     */
+    public void setPlaybackRate(float rate) {
+        setPlaybackRate(rate, PLAYBACK_RATE_AUDIO_MODE_STRETCH);
+    }
+
+    /**
+     * Sets playback rate and audio mode.
+     *
+     * <p> The supported audio modes are:
+     * <ul>
+     * <li> {@link #PLAYBACK_RATE_AUDIO_MODE_RESAMPLE}
+     * </ul>
+     *
+     * @param rate the ratio between desired playback rate and normal one. 1.0 means normal
+     *     playback speed. 0.0 means stop or pause. Value larger than 1.0 means faster playback,
+     *     while value between 0.0 and 1.0 for slower playback.
+     * @param audioMode audio playback mode. Must be one of the supported
+     *     audio modes.
+     *
+     * @throws IllegalStateException if the internal sync engine or the audio track has not
+     *     been initialized.
+     * @throws IllegalArgumentException if audioMode is not supported.
+     */
+    public void setPlaybackRate(float rate, @PlaybackRateAudioMode int audioMode) {
+        if (!isAudioPlaybackModeSupported(audioMode)) {
+            final String msg = "Audio playback mode " + audioMode + " is not supported";
+            throw new IllegalArgumentException(msg);
+        }
+
+        int status = AudioTrack.SUCCESS;
+        if (mAudioTrack != null) {
+            int playbackSampleRate = (int)(rate * mNativeSampleRateInHz + 0.5);
+            rate = playbackSampleRate / (float)mNativeSampleRateInHz;
+
+            try {
+                if (rate == 0.0) {
+                    mAudioTrack.pause();
+                } else {
+                    status = mAudioTrack.setPlaybackRate(playbackSampleRate);
+                    mAudioTrack.play();
+                }
+            } catch (IllegalStateException e) {
+                throw e;
+            }
+        }
+
+        if (status != AudioTrack.SUCCESS) {
+            throw new IllegalArgumentException("Fail to set playback rate in audio track");
+        }
+
+        synchronized(mAudioLock) {
+            mPlaybackRate = rate;
+        }
+        if (mPlaybackRate != 0.0 && mAudioThread != null) {
+            postRenderAudio(0);
+        }
+        native_setPlaybackRate(mPlaybackRate);
+    }
+
+    private native final void native_setPlaybackRate(float rate);
+
+    /*
+     * Test whether a given audio playback mode is supported.
+     * TODO query supported AudioPlaybackMode from audio track.
+     */
+    private boolean isAudioPlaybackModeSupported(int mode) {
+        return (mode == PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+    }
+
+    /**
+     * Queues the audio data asynchronously for playback (AudioTrack must be in streaming mode).
+     * @param audioData the buffer that holds the data to play. This buffer will be returned
+     *     to the client via registered callback.
+     * @param bufferIndex the buffer index used to identify audioData. It will be returned to
+     *     the client along with audioData. This helps applications to keep track of audioData.
+     * @param sizeInBytes number of bytes to queue.
+     * @param presentationTimeUs the presentation timestamp in microseconds for the first frame
+     *     in the buffer.
+     * @throws IllegalStateException if audio track is not configured or internal configureation
+     *     has not been done correctly.
+     */
+    public void queueAudio(
+            ByteBuffer audioData, int bufferIndex, int sizeInBytes, long presentationTimeUs) {
+        if (mAudioTrack == null || mAudioThread == null) {
+            throw new IllegalStateException(
+                    "AudioTrack is NOT configured or audio thread is not created");
+        }
+
+        synchronized(mAudioLock) {
+            mAudioBuffers.add(new AudioBuffer(
+                    audioData, bufferIndex, sizeInBytes, presentationTimeUs));
+        }
+
+        if (mPlaybackRate != 0.0) {
+            postRenderAudio(0);
+        }
+    }
+
+    // When called on user thread, make sure to check mAudioThread != null.
+    private void postRenderAudio(long delayMillis) {
+        mAudioHandler.postDelayed(new Runnable() {
+            public void run() {
+                synchronized(mAudioLock) {
+                    if (mPlaybackRate == 0.0) {
+                        return;
+                    }
+
+                    if (mAudioBuffers.isEmpty()) {
+                        return;
+                    }
+
+                    AudioBuffer audioBuffer = mAudioBuffers.get(0);
+                    int sizeWritten = mAudioTrack.write(
+                            audioBuffer.mByteBuffer,
+                            audioBuffer.mSizeInBytes,
+                            AudioTrack.WRITE_NON_BLOCKING);
+                    if (sizeWritten > 0) {
+                        if (audioBuffer.mPresentationTimeUs != -1) {
+                            native_updateQueuedAudioData(
+                                    audioBuffer.mSizeInBytes, audioBuffer.mPresentationTimeUs);
+                            audioBuffer.mPresentationTimeUs = -1;
+                        }
+
+                        if (sizeWritten == audioBuffer.mSizeInBytes) {
+                            postReturnByteBuffer(audioBuffer);
+                            mAudioBuffers.remove(0);
+                            if (!mAudioBuffers.isEmpty()) {
+                                postRenderAudio(0);
+                            }
+                            return;
+                        }
+
+                        audioBuffer.mSizeInBytes -= sizeWritten;
+                    }
+                    // TODO: wait time depends on fullness of audio track.
+                    postRenderAudio(10);
+                }
+            }
+        }, delayMillis);
+    }
+
+    private native final void native_updateQueuedAudioData(
+            int sizeInBytes, long presentationTimeUs);
+
+    private final void postReturnByteBuffer(final AudioBuffer audioBuffer) {
+        synchronized(mCallbackLock) {
+            if (mCallbackHandler != null) {
+                final MediaSync sync = this;
+                mCallbackHandler.post(new Runnable() {
+                    public void run() {
+                        synchronized(mCallbackLock) {
+                            if (mCallbackHandler == null
+                                    || mCallbackHandler.getLooper().getThread()
+                                            != Thread.currentThread()) {
+                                // callback handler has been changed.
+                                return;
+                            }
+                            if (mCallback != null) {
+                                mCallback.onReturnAudioBuffer(sync, audioBuffer.mByteBuffer,
+                                        audioBuffer.mBufferIndex);
+                            }
+                        }
+                    }
+                });
+            }
+        }
+    }
+
+    private final void returnAudioBuffers() {
+        synchronized(mAudioLock) {
+            for (AudioBuffer audioBuffer: mAudioBuffers) {
+                postReturnByteBuffer(audioBuffer);
+            }
+            mAudioBuffers.clear();
+        }
+    }
+
+    private void createAudioThread() {
+        mAudioThread = new Thread() {
+            @Override
+            public void run() {
+                Looper.prepare();
+                synchronized(mAudioLock) {
+                    mAudioLooper = Looper.myLooper();
+                    mAudioHandler = new Handler();
+                    mAudioLock.notify();
+                }
+                Looper.loop();
+            }
+        };
+        mAudioThread.start();
+
+        synchronized(mAudioLock) {
+            try {
+                mAudioLock.wait();
+            } catch(InterruptedException e) {
+            }
+        }
+    }
+
+    static {
+        System.loadLibrary("media_jni");
+        native_init();
+    }
+
+    private static native final void native_init();
+}
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index db6b38b..88d979e 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -32,7 +32,6 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
 
@@ -112,7 +111,24 @@
  * resumes.</p>
  */
 public class SoundPool {
-    private final SoundPoolDelegate mImpl;
+    static { System.loadLibrary("soundpool"); }
+
+    // SoundPool messages
+    //
+    // must match SoundPool.h
+    private static final int SAMPLE_LOADED = 1;
+
+    private final static String TAG = "SoundPool";
+    private final static boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private long mNativeContext; // accessed by native methods
+
+    private EventHandler mEventHandler;
+    private SoundPool.OnLoadCompleteListener mOnLoadCompleteListener;
+
+    private final Object mLock;
+    private final AudioAttributes mAttributes;
+    private final IAppOpsService mAppOps;
 
     /**
      * Constructor. Constructs a SoundPool object with the following
@@ -135,10 +151,374 @@
     }
 
     private SoundPool(int maxStreams, AudioAttributes attributes) {
-        if (SystemProperties.getBoolean("config.disable_media", false)) {
-            mImpl = new SoundPoolStub();
+        // do native setup
+        if (native_setup(new WeakReference<SoundPool>(this), maxStreams, attributes) != 0) {
+            throw new RuntimeException("Native setup failed");
+        }
+        mLock = new Object();
+        mAttributes = attributes;
+        IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
+        mAppOps = IAppOpsService.Stub.asInterface(b);
+    }
+
+    /**
+     * Release the SoundPool resources.
+     *
+     * Release all memory and native resources used by the SoundPool
+     * object. The SoundPool can no longer be used and the reference
+     * should be set to null.
+     */
+    public native final void release();
+
+    protected void finalize() { release(); }
+
+    /**
+     * Load the sound from the specified path.
+     *
+     * @param path the path to the audio file
+     * @param priority the priority of the sound. Currently has no effect. Use
+     *                 a value of 1 for future compatibility.
+     * @return a sound ID. This value can be used to play or unload the sound.
+     */
+    public int load(String path, int priority) {
+        int id = 0;
+        try {
+            File f = new File(path);
+            ParcelFileDescriptor fd = ParcelFileDescriptor.open(f,
+                    ParcelFileDescriptor.MODE_READ_ONLY);
+            if (fd != null) {
+                id = _load(fd.getFileDescriptor(), 0, f.length(), priority);
+                fd.close();
+            }
+        } catch (java.io.IOException e) {
+            Log.e(TAG, "error loading " + path);
+        }
+        return id;
+    }
+
+    /**
+     * Load the sound from the specified APK resource.
+     *
+     * Note that the extension is dropped. For example, if you want to load
+     * a sound from the raw resource file "explosion.mp3", you would specify
+     * "R.raw.explosion" as the resource ID. Note that this means you cannot
+     * have both an "explosion.wav" and an "explosion.mp3" in the res/raw
+     * directory.
+     * 
+     * @param context the application context
+     * @param resId the resource ID
+     * @param priority the priority of the sound. Currently has no effect. Use
+     *                 a value of 1 for future compatibility.
+     * @return a sound ID. This value can be used to play or unload the sound.
+     */
+    public int load(Context context, int resId, int priority) {
+        AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
+        int id = 0;
+        if (afd != null) {
+            id = _load(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(), priority);
+            try {
+                afd.close();
+            } catch (java.io.IOException ex) {
+                //Log.d(TAG, "close failed:", ex);
+            }
+        }
+        return id;
+    }
+
+    /**
+     * Load the sound from an asset file descriptor.
+     *
+     * @param afd an asset file descriptor
+     * @param priority the priority of the sound. Currently has no effect. Use
+     *                 a value of 1 for future compatibility.
+     * @return a sound ID. This value can be used to play or unload the sound.
+     */
+    public int load(AssetFileDescriptor afd, int priority) {
+        if (afd != null) {
+            long len = afd.getLength();
+            if (len < 0) {
+                throw new AndroidRuntimeException("no length for fd");
+            }
+            return _load(afd.getFileDescriptor(), afd.getStartOffset(), len, priority);
         } else {
-            mImpl = new SoundPoolImpl(this, maxStreams, attributes);
+            return 0;
+        }
+    }
+
+    /**
+     * Load the sound from a FileDescriptor.
+     *
+     * This version is useful if you store multiple sounds in a single
+     * binary. The offset specifies the offset from the start of the file
+     * and the length specifies the length of the sound within the file.
+     *
+     * @param fd a FileDescriptor object
+     * @param offset offset to the start of the sound
+     * @param length length of the sound
+     * @param priority the priority of the sound. Currently has no effect. Use
+     *                 a value of 1 for future compatibility.
+     * @return a sound ID. This value can be used to play or unload the sound.
+     */
+    public int load(FileDescriptor fd, long offset, long length, int priority) {
+        return _load(fd, offset, length, priority);
+    }
+
+    /**
+     * Unload a sound from a sound ID.
+     *
+     * Unloads the sound specified by the soundID. This is the value
+     * returned by the load() function. Returns true if the sound is
+     * successfully unloaded, false if the sound was already unloaded.
+     *
+     * @param soundID a soundID returned by the load() function
+     * @return true if just unloaded, false if previously unloaded
+     */
+    public native final boolean unload(int soundID);
+
+    /**
+     * Play a sound from a sound ID.
+     *
+     * Play the sound specified by the soundID. This is the value 
+     * returned by the load() function. Returns a non-zero streamID
+     * if successful, zero if it fails. The streamID can be used to
+     * further control playback. Note that calling play() may cause
+     * another sound to stop playing if the maximum number of active
+     * streams is exceeded. A loop value of -1 means loop forever,
+     * a value of 0 means don't loop, other values indicate the
+     * number of repeats, e.g. a value of 1 plays the audio twice.
+     * The playback rate allows the application to vary the playback
+     * rate (pitch) of the sound. A value of 1.0 means play back at
+     * the original frequency. A value of 2.0 means play back twice
+     * as fast, and a value of 0.5 means playback at half speed.
+     *
+     * @param soundID a soundID returned by the load() function
+     * @param leftVolume left volume value (range = 0.0 to 1.0)
+     * @param rightVolume right volume value (range = 0.0 to 1.0)
+     * @param priority stream priority (0 = lowest priority)
+     * @param loop loop mode (0 = no loop, -1 = loop forever)
+     * @param rate playback rate (1.0 = normal playback, range 0.5 to 2.0)
+     * @return non-zero streamID if successful, zero if failed
+     */
+    public final int play(int soundID, float leftVolume, float rightVolume,
+            int priority, int loop, float rate) {
+        if (isRestricted()) {
+            leftVolume = rightVolume = 0;
+        }
+        return _play(soundID, leftVolume, rightVolume, priority, loop, rate);
+    }
+
+    /**
+     * Pause a playback stream.
+     *
+     * Pause the stream specified by the streamID. This is the
+     * value returned by the play() function. If the stream is
+     * playing, it will be paused. If the stream is not playing
+     * (e.g. is stopped or was previously paused), calling this
+     * function will have no effect.
+     *
+     * @param streamID a streamID returned by the play() function
+     */
+    public native final void pause(int streamID);
+
+    /**
+     * Resume a playback stream.
+     *
+     * Resume the stream specified by the streamID. This
+     * is the value returned by the play() function. If the stream
+     * is paused, this will resume playback. If the stream was not
+     * previously paused, calling this function will have no effect.
+     *
+     * @param streamID a streamID returned by the play() function
+     */
+    public native final void resume(int streamID);
+
+    /**
+     * Pause all active streams.
+     *
+     * Pause all streams that are currently playing. This function
+     * iterates through all the active streams and pauses any that
+     * are playing. It also sets a flag so that any streams that
+     * are playing can be resumed by calling autoResume().
+     */
+    public native final void autoPause();
+
+    /**
+     * Resume all previously active streams.
+     *
+     * Automatically resumes all streams that were paused in previous
+     * calls to autoPause().
+     */
+    public native final void autoResume();
+
+    /**
+     * Stop a playback stream.
+     *
+     * Stop the stream specified by the streamID. This
+     * is the value returned by the play() function. If the stream
+     * is playing, it will be stopped. It also releases any native
+     * resources associated with this stream. If the stream is not
+     * playing, it will have no effect.
+     *
+     * @param streamID a streamID returned by the play() function
+     */
+    public native final void stop(int streamID);
+
+    /**
+     * Set stream volume.
+     *
+     * Sets the volume on the stream specified by the streamID.
+     * This is the value returned by the play() function. The
+     * value must be in the range of 0.0 to 1.0. If the stream does
+     * not exist, it will have no effect.
+     *
+     * @param streamID a streamID returned by the play() function
+     * @param leftVolume left volume value (range = 0.0 to 1.0)
+     * @param rightVolume right volume value (range = 0.0 to 1.0)
+     */
+    public final void setVolume(int streamID, float leftVolume, float rightVolume) {
+        if (isRestricted()) {
+            return;
+        }
+        _setVolume(streamID, leftVolume, rightVolume);
+    }
+
+    /**
+     * Similar, except set volume of all channels to same value.
+     * @hide
+     */
+    public void setVolume(int streamID, float volume) {
+        setVolume(streamID, volume, volume);
+    }
+
+    /**
+     * Change stream priority.
+     *
+     * Change the priority of the stream specified by the streamID.
+     * This is the value returned by the play() function. Affects the
+     * order in which streams are re-used to play new sounds. If the
+     * stream does not exist, it will have no effect.
+     *
+     * @param streamID a streamID returned by the play() function
+     */
+    public native final void setPriority(int streamID, int priority);
+
+    /**
+     * Set loop mode.
+     *
+     * Change the loop mode. A loop value of -1 means loop forever,
+     * a value of 0 means don't loop, other values indicate the
+     * number of repeats, e.g. a value of 1 plays the audio twice.
+     * If the stream does not exist, it will have no effect.
+     *
+     * @param streamID a streamID returned by the play() function
+     * @param loop loop mode (0 = no loop, -1 = loop forever)
+     */
+    public native final void setLoop(int streamID, int loop);
+
+    /**
+     * Change playback rate.
+     *
+     * The playback rate allows the application to vary the playback
+     * rate (pitch) of the sound. A value of 1.0 means playback at
+     * the original frequency. A value of 2.0 means playback twice
+     * as fast, and a value of 0.5 means playback at half speed.
+     * If the stream does not exist, it will have no effect.
+     *
+     * @param streamID a streamID returned by the play() function
+     * @param rate playback rate (1.0 = normal playback, range 0.5 to 2.0)
+     */
+    public native final void setRate(int streamID, float rate);
+
+    public interface OnLoadCompleteListener {
+        /**
+         * Called when a sound has completed loading.
+         *
+         * @param soundPool SoundPool object from the load() method
+         * @param sampleId the sample ID of the sound loaded.
+         * @param status the status of the load operation (0 = success)
+         */
+        public void onLoadComplete(SoundPool soundPool, int sampleId, int status);
+    }
+
+    /**
+     * Sets the callback hook for the OnLoadCompleteListener.
+     */
+    public void setOnLoadCompleteListener(OnLoadCompleteListener listener) {
+        synchronized(mLock) {
+            if (listener != null) {
+                // setup message handler
+                Looper looper;
+                if ((looper = Looper.myLooper()) != null) {
+                    mEventHandler = new EventHandler(looper);
+                } else if ((looper = Looper.getMainLooper()) != null) {
+                    mEventHandler = new EventHandler(looper);
+                } else {
+                    mEventHandler = null;
+                }
+            } else {
+                mEventHandler = null;
+            }
+            mOnLoadCompleteListener = listener;
+        }
+    }
+
+    private boolean isRestricted() {
+        if ((mAttributes.getFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
+            return false;
+        }
+        try {
+            final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO,
+                    mAttributes.getUsage(),
+                    Process.myUid(), ActivityThread.currentPackageName());
+            return mode != AppOpsManager.MODE_ALLOWED;
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    private native final int _load(FileDescriptor fd, long offset, long length, int priority); 
+
+    private native final int native_setup(Object weakRef, int maxStreams,
+            Object/*AudioAttributes*/ attributes);
+
+    private native final int _play(int soundID, float leftVolume, float rightVolume,
+            int priority, int loop, float rate);
+
+    private native final void _setVolume(int streamID, float leftVolume, float rightVolume);
+
+    // post event from native code to message handler
+    @SuppressWarnings("unchecked")
+    private static void postEventFromNative(Object ref, int msg, int arg1, int arg2, Object obj) {
+        SoundPool soundPool = ((WeakReference<SoundPool>) ref).get();
+        if (soundPool == null)
+            return;
+
+        if (soundPool.mEventHandler != null) {
+            Message m = soundPool.mEventHandler.obtainMessage(msg, arg1, arg2, obj);
+            soundPool.mEventHandler.sendMessage(m);
+        }
+    }
+
+    private final class EventHandler extends Handler {
+        public EventHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+            case SAMPLE_LOADED:
+                if (DEBUG) Log.d(TAG, "Sample " + msg.arg1 + " loaded");
+                synchronized(mLock) {
+                    if (mOnLoadCompleteListener != null) {
+                        mOnLoadCompleteListener.onLoadComplete(SoundPool.this, msg.arg1, msg.arg2);
+                    }
+                }
+                break;
+            default:
+                Log.e(TAG, "Unknown message type " + msg.what);
+                return;
+            }
         }
     }
 
@@ -197,613 +577,4 @@
             return new SoundPool(mMaxStreams, mAudioAttributes);
         }
     }
-
-    /**
-     * Load the sound from the specified path.
-     *
-     * @param path the path to the audio file
-     * @param priority the priority of the sound. Currently has no effect. Use
-     *                 a value of 1 for future compatibility.
-     * @return a sound ID. This value can be used to play or unload the sound.
-     */
-    public int load(String path, int priority) {
-        return mImpl.load(path, priority);
-    }
-
-    /**
-     * Load the sound from the specified APK resource.
-     *
-     * Note that the extension is dropped. For example, if you want to load
-     * a sound from the raw resource file "explosion.mp3", you would specify
-     * "R.raw.explosion" as the resource ID. Note that this means you cannot
-     * have both an "explosion.wav" and an "explosion.mp3" in the res/raw
-     * directory.
-     * 
-     * @param context the application context
-     * @param resId the resource ID
-     * @param priority the priority of the sound. Currently has no effect. Use
-     *                 a value of 1 for future compatibility.
-     * @return a sound ID. This value can be used to play or unload the sound.
-     */
-    public int load(Context context, int resId, int priority) {
-        return mImpl.load(context, resId, priority);
-    }
-
-    /**
-     * Load the sound from an asset file descriptor.
-     *
-     * @param afd an asset file descriptor
-     * @param priority the priority of the sound. Currently has no effect. Use
-     *                 a value of 1 for future compatibility.
-     * @return a sound ID. This value can be used to play or unload the sound.
-     */
-    public int load(AssetFileDescriptor afd, int priority) {
-        return mImpl.load(afd, priority);
-    }
-
-    /**
-     * Load the sound from a FileDescriptor.
-     *
-     * This version is useful if you store multiple sounds in a single
-     * binary. The offset specifies the offset from the start of the file
-     * and the length specifies the length of the sound within the file.
-     *
-     * @param fd a FileDescriptor object
-     * @param offset offset to the start of the sound
-     * @param length length of the sound
-     * @param priority the priority of the sound. Currently has no effect. Use
-     *                 a value of 1 for future compatibility.
-     * @return a sound ID. This value can be used to play or unload the sound.
-     */
-    public int load(FileDescriptor fd, long offset, long length, int priority) {
-        return mImpl.load(fd, offset, length, priority);
-    }
-
-    /**
-     * Unload a sound from a sound ID.
-     *
-     * Unloads the sound specified by the soundID. This is the value
-     * returned by the load() function. Returns true if the sound is
-     * successfully unloaded, false if the sound was already unloaded.
-     *
-     * @param soundID a soundID returned by the load() function
-     * @return true if just unloaded, false if previously unloaded
-     */
-    public final boolean unload(int soundID) {
-        return mImpl.unload(soundID);
-    }
-
-    /**
-     * Play a sound from a sound ID.
-     *
-     * Play the sound specified by the soundID. This is the value 
-     * returned by the load() function. Returns a non-zero streamID
-     * if successful, zero if it fails. The streamID can be used to
-     * further control playback. Note that calling play() may cause
-     * another sound to stop playing if the maximum number of active
-     * streams is exceeded. A loop value of -1 means loop forever,
-     * a value of 0 means don't loop, other values indicate the
-     * number of repeats, e.g. a value of 1 plays the audio twice.
-     * The playback rate allows the application to vary the playback
-     * rate (pitch) of the sound. A value of 1.0 means play back at
-     * the original frequency. A value of 2.0 means play back twice
-     * as fast, and a value of 0.5 means playback at half speed.
-     *
-     * @param soundID a soundID returned by the load() function
-     * @param leftVolume left volume value (range = 0.0 to 1.0)
-     * @param rightVolume right volume value (range = 0.0 to 1.0)
-     * @param priority stream priority (0 = lowest priority)
-     * @param loop loop mode (0 = no loop, -1 = loop forever)
-     * @param rate playback rate (1.0 = normal playback, range 0.5 to 2.0)
-     * @return non-zero streamID if successful, zero if failed
-     */
-    public final int play(int soundID, float leftVolume, float rightVolume,
-            int priority, int loop, float rate) {
-        return mImpl.play(
-            soundID, leftVolume, rightVolume, priority, loop, rate);
-    }
-
-    /**
-     * Pause a playback stream.
-     *
-     * Pause the stream specified by the streamID. This is the
-     * value returned by the play() function. If the stream is
-     * playing, it will be paused. If the stream is not playing
-     * (e.g. is stopped or was previously paused), calling this
-     * function will have no effect.
-     *
-     * @param streamID a streamID returned by the play() function
-     */
-    public final void pause(int streamID) {
-        mImpl.pause(streamID);
-    }
-
-    /**
-     * Resume a playback stream.
-     *
-     * Resume the stream specified by the streamID. This
-     * is the value returned by the play() function. If the stream
-     * is paused, this will resume playback. If the stream was not
-     * previously paused, calling this function will have no effect.
-     *
-     * @param streamID a streamID returned by the play() function
-     */
-    public final void resume(int streamID) {
-        mImpl.resume(streamID);
-    }
-
-    /**
-     * Pause all active streams.
-     *
-     * Pause all streams that are currently playing. This function
-     * iterates through all the active streams and pauses any that
-     * are playing. It also sets a flag so that any streams that
-     * are playing can be resumed by calling autoResume().
-     */
-    public final void autoPause() {
-        mImpl.autoPause();
-    }
-
-    /**
-     * Resume all previously active streams.
-     *
-     * Automatically resumes all streams that were paused in previous
-     * calls to autoPause().
-     */
-    public final void autoResume() {
-        mImpl.autoResume();
-    }
-
-    /**
-     * Stop a playback stream.
-     *
-     * Stop the stream specified by the streamID. This
-     * is the value returned by the play() function. If the stream
-     * is playing, it will be stopped. It also releases any native
-     * resources associated with this stream. If the stream is not
-     * playing, it will have no effect.
-     *
-     * @param streamID a streamID returned by the play() function
-     */
-    public final void stop(int streamID) {
-        mImpl.stop(streamID);
-    }
-
-    /**
-     * Set stream volume.
-     *
-     * Sets the volume on the stream specified by the streamID.
-     * This is the value returned by the play() function. The
-     * value must be in the range of 0.0 to 1.0. If the stream does
-     * not exist, it will have no effect.
-     *
-     * @param streamID a streamID returned by the play() function
-     * @param leftVolume left volume value (range = 0.0 to 1.0)
-     * @param rightVolume right volume value (range = 0.0 to 1.0)
-     */
-    public final void setVolume(int streamID,
-            float leftVolume, float rightVolume) {
-        mImpl.setVolume(streamID, leftVolume, rightVolume);
-    }
-
-    /**
-     * Similar, except set volume of all channels to same value.
-     * @hide
-     */
-    public void setVolume(int streamID, float volume) {
-        setVolume(streamID, volume, volume);
-    }
-
-    /**
-     * Change stream priority.
-     *
-     * Change the priority of the stream specified by the streamID.
-     * This is the value returned by the play() function. Affects the
-     * order in which streams are re-used to play new sounds. If the
-     * stream does not exist, it will have no effect.
-     *
-     * @param streamID a streamID returned by the play() function
-     */
-    public final void setPriority(int streamID, int priority) {
-        mImpl.setPriority(streamID, priority);
-    }
-
-    /**
-     * Set loop mode.
-     *
-     * Change the loop mode. A loop value of -1 means loop forever,
-     * a value of 0 means don't loop, other values indicate the
-     * number of repeats, e.g. a value of 1 plays the audio twice.
-     * If the stream does not exist, it will have no effect.
-     *
-     * @param streamID a streamID returned by the play() function
-     * @param loop loop mode (0 = no loop, -1 = loop forever)
-     */
-    public final void setLoop(int streamID, int loop) {
-        mImpl.setLoop(streamID, loop);
-    }
-
-    /**
-     * Change playback rate.
-     *
-     * The playback rate allows the application to vary the playback
-     * rate (pitch) of the sound. A value of 1.0 means playback at
-     * the original frequency. A value of 2.0 means playback twice
-     * as fast, and a value of 0.5 means playback at half speed.
-     * If the stream does not exist, it will have no effect.
-     *
-     * @param streamID a streamID returned by the play() function
-     * @param rate playback rate (1.0 = normal playback, range 0.5 to 2.0)
-     */
-    public final void setRate(int streamID, float rate) {
-        mImpl.setRate(streamID, rate);
-    }
-
-    public interface OnLoadCompleteListener {
-        /**
-         * Called when a sound has completed loading.
-         *
-         * @param soundPool SoundPool object from the load() method
-         * @param sampleId the sample ID of the sound loaded.
-         * @param status the status of the load operation (0 = success)
-         */
-        public void onLoadComplete(SoundPool soundPool, int sampleId, int status);
-    }
-
-    /**
-     * Sets the callback hook for the OnLoadCompleteListener.
-     */
-    public void setOnLoadCompleteListener(OnLoadCompleteListener listener) {
-        mImpl.setOnLoadCompleteListener(listener);
-    }
-
-    /**
-     * Release the SoundPool resources.
-     *
-     * Release all memory and native resources used by the SoundPool
-     * object. The SoundPool can no longer be used and the reference
-     * should be set to null.
-     */
-    public final void release() {
-        mImpl.release();
-    }
-
-    /**
-     * Interface for SoundPool implementations.
-     * SoundPool is statically referenced and unconditionally called from all
-     * over the framework, so we can't simply omit the class or make it throw
-     * runtime exceptions, as doing so would break the framework. Instead we
-     * now select either a real or no-op impl object based on whether media is
-     * enabled.
-     *
-     * @hide
-     */
-    /* package */ interface SoundPoolDelegate {
-        public int load(String path, int priority);
-        public int load(Context context, int resId, int priority);
-        public int load(AssetFileDescriptor afd, int priority);
-        public int load(
-                FileDescriptor fd, long offset, long length, int priority);
-        public boolean unload(int soundID);
-        public int play(
-                int soundID, float leftVolume, float rightVolume,
-                int priority, int loop, float rate);
-        public void pause(int streamID);
-        public void resume(int streamID);
-        public void autoPause();
-        public void autoResume();
-        public void stop(int streamID);
-        public void setVolume(int streamID, float leftVolume, float rightVolume);
-        public void setVolume(int streamID, float volume);
-        public void setPriority(int streamID, int priority);
-        public void setLoop(int streamID, int loop);
-        public void setRate(int streamID, float rate);
-        public void setOnLoadCompleteListener(OnLoadCompleteListener listener);
-        public void release();
-    }
-
-
-    /**
-     * Real implementation of the delegate interface. This was formerly the
-     * body of SoundPool itself.
-     */
-    /* package */ static class SoundPoolImpl implements SoundPoolDelegate {
-        static { System.loadLibrary("soundpool"); }
-
-        private final static String TAG = "SoundPool";
-        private final static boolean DEBUG = false;
-
-        private long mNativeContext; // accessed by native methods
-
-        private EventHandler mEventHandler;
-        private SoundPool.OnLoadCompleteListener mOnLoadCompleteListener;
-        private SoundPool mProxy;
-
-        private final Object mLock;
-        private final AudioAttributes mAttributes;
-        private final IAppOpsService mAppOps;
-
-        // SoundPool messages
-        //
-        // must match SoundPool.h
-        private static final int SAMPLE_LOADED = 1;
-
-        public SoundPoolImpl(SoundPool proxy, int maxStreams, AudioAttributes attr) {
-
-            // do native setup
-            if (native_setup(new WeakReference(this), maxStreams, attr) != 0) {
-                throw new RuntimeException("Native setup failed");
-            }
-            mLock = new Object();
-            mProxy = proxy;
-            mAttributes = attr;
-            IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
-            mAppOps = IAppOpsService.Stub.asInterface(b);
-        }
-
-        public int load(String path, int priority)
-        {
-            int id = 0;
-            try {
-                File f = new File(path);
-                ParcelFileDescriptor fd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
-                if (fd != null) {
-                    id = _load(fd.getFileDescriptor(), 0, f.length(), priority);
-                    fd.close();
-                }
-            } catch (java.io.IOException e) {
-                Log.e(TAG, "error loading " + path);
-            }
-            return id;
-        }
-
-        @Override
-        public int load(Context context, int resId, int priority) {
-            AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
-            int id = 0;
-            if (afd != null) {
-                id = _load(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(), priority);
-                try {
-                    afd.close();
-                } catch (java.io.IOException ex) {
-                    //Log.d(TAG, "close failed:", ex);
-                }
-            }
-            return id;
-        }
-
-        @Override
-        public int load(AssetFileDescriptor afd, int priority) {
-            if (afd != null) {
-                long len = afd.getLength();
-                if (len < 0) {
-                    throw new AndroidRuntimeException("no length for fd");
-                }
-                return _load(afd.getFileDescriptor(), afd.getStartOffset(), len, priority);
-            } else {
-                return 0;
-            }
-        }
-
-        @Override
-        public int load(FileDescriptor fd, long offset, long length, int priority) {
-            return _load(fd, offset, length, priority);
-        }
-
-        private native final int _load(FileDescriptor fd, long offset, long length, int priority);
-
-        @Override
-        public native final boolean unload(int soundID);
-
-        @Override
-        public final int play(int soundID, float leftVolume, float rightVolume,
-                int priority, int loop, float rate) {
-            if (isRestricted()) {
-                leftVolume = rightVolume = 0;
-            }
-            return _play(soundID, leftVolume, rightVolume, priority, loop, rate);
-        }
-
-        public native final int _play(int soundID, float leftVolume, float rightVolume,
-                int priority, int loop, float rate);
-
-        private boolean isRestricted() {
-            if ((mAttributes.getFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
-                return false;
-            }
-            try {
-                final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO,
-                        mAttributes.getUsage(),
-                        Process.myUid(), ActivityThread.currentPackageName());
-                return mode != AppOpsManager.MODE_ALLOWED;
-            } catch (RemoteException e) {
-                return false;
-            }
-        }
-
-        @Override
-        public native final void pause(int streamID);
-
-        @Override
-        public native final void resume(int streamID);
-
-        @Override
-        public native final void autoPause();
-
-        @Override
-        public native final void autoResume();
-
-        @Override
-        public native final void stop(int streamID);
-
-        @Override
-        public final void setVolume(int streamID, float leftVolume, float rightVolume) {
-            if (isRestricted()) {
-                return;
-            }
-            _setVolume(streamID, leftVolume, rightVolume);
-        }
-
-        private native final void _setVolume(int streamID, float leftVolume, float rightVolume);
-
-        @Override
-        public void setVolume(int streamID, float volume) {
-            setVolume(streamID, volume, volume);
-        }
-
-        @Override
-        public native final void setPriority(int streamID, int priority);
-
-        @Override
-        public native final void setLoop(int streamID, int loop);
-
-        @Override
-        public native final void setRate(int streamID, float rate);
-
-        @Override
-        public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener)
-        {
-            synchronized(mLock) {
-                if (listener != null) {
-                    // setup message handler
-                    Looper looper;
-                    if ((looper = Looper.myLooper()) != null) {
-                        mEventHandler = new EventHandler(mProxy, looper);
-                    } else if ((looper = Looper.getMainLooper()) != null) {
-                        mEventHandler = new EventHandler(mProxy, looper);
-                    } else {
-                        mEventHandler = null;
-                    }
-                } else {
-                    mEventHandler = null;
-                }
-                mOnLoadCompleteListener = listener;
-            }
-        }
-
-        private class EventHandler extends Handler
-        {
-            private SoundPool mSoundPool;
-
-            public EventHandler(SoundPool soundPool, Looper looper) {
-                super(looper);
-                mSoundPool = soundPool;
-            }
-
-            @Override
-            public void handleMessage(Message msg) {
-                switch(msg.what) {
-                case SAMPLE_LOADED:
-                    if (DEBUG) Log.d(TAG, "Sample " + msg.arg1 + " loaded");
-                    synchronized(mLock) {
-                        if (mOnLoadCompleteListener != null) {
-                            mOnLoadCompleteListener.onLoadComplete(mSoundPool, msg.arg1, msg.arg2);
-                        }
-                    }
-                    break;
-                default:
-                    Log.e(TAG, "Unknown message type " + msg.what);
-                    return;
-                }
-            }
-        }
-
-        // post event from native code to message handler
-        private static void postEventFromNative(Object weakRef, int msg, int arg1, int arg2, Object obj)
-        {
-            SoundPoolImpl soundPoolImpl = (SoundPoolImpl)((WeakReference)weakRef).get();
-            if (soundPoolImpl == null)
-                return;
-
-            if (soundPoolImpl.mEventHandler != null) {
-                Message m = soundPoolImpl.mEventHandler.obtainMessage(msg, arg1, arg2, obj);
-                soundPoolImpl.mEventHandler.sendMessage(m);
-            }
-        }
-
-        public native final void release();
-
-        private native final int native_setup(Object weakRef, int maxStreams,
-                Object/*AudioAttributes*/ attributes);
-
-        protected void finalize() { release(); }
-    }
-
-    /**
-     * No-op implementation of SoundPool.
-     * Used when media is disabled by the system.
-     * @hide
-     */
-    /* package */ static class SoundPoolStub implements SoundPoolDelegate {
-        public SoundPoolStub() { }
-
-        public int load(String path, int priority) {
-            return 0;
-        }
-
-        @Override
-        public int load(Context context, int resId, int priority) {
-            return 0;
-        }
-
-        @Override
-        public int load(AssetFileDescriptor afd, int priority) {
-            return 0;
-        }
-
-        @Override
-        public int load(FileDescriptor fd, long offset, long length, int priority) {
-            return 0;
-        }
-
-        @Override
-        public final boolean unload(int soundID) {
-            return true;
-        }
-
-        @Override
-        public final int play(int soundID, float leftVolume, float rightVolume,
-                int priority, int loop, float rate) {
-            return 0;
-        }
-
-        @Override
-        public final void pause(int streamID) { }
-
-        @Override
-        public final void resume(int streamID) { }
-
-        @Override
-        public final void autoPause() { }
-
-        @Override
-        public final void autoResume() { }
-
-        @Override
-        public final void stop(int streamID) { }
-
-        @Override
-        public final void setVolume(int streamID,
-                float leftVolume, float rightVolume) { }
-
-        @Override
-        public void setVolume(int streamID, float volume) {
-        }
-
-        @Override
-        public final void setPriority(int streamID, int priority) { }
-
-        @Override
-        public final void setLoop(int streamID, int loop) { }
-
-        @Override
-        public final void setRate(int streamID, float rate) { }
-
-        @Override
-        public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener) {
-        }
-
-        @Override
-        public final void release() { }
-    }
 }
diff --git a/media/java/android/media/midi/MidiDevice.java b/media/java/android/media/midi/MidiDevice.java
index 569f7c6..6b36554 100644
--- a/media/java/android/media/midi/MidiDevice.java
+++ b/media/java/android/media/midi/MidiDevice.java
@@ -34,9 +34,6 @@
 /**
  * This class is used for sending and receiving data to and from a MIDI device
  * Instances of this class are created by {@link MidiManager#openDevice}.
- *
- * CANDIDATE FOR PUBLIC API
- * @hide
  */
 public final class MidiDevice implements Closeable {
     private static final String TAG = "MidiDevice";
@@ -49,6 +46,11 @@
 
     private final CloseGuard mGuard = CloseGuard.get();
 
+    /**
+     * This class represents a connection between the output port of one device
+     * and the input port of another. Created by {@link #connectPorts}.
+     * Close this object to terminate the connection.
+     */
     public class MidiConnection implements Closeable {
         private final IBinder mToken;
         private final MidiInputPort mInputPort;
@@ -134,11 +136,11 @@
     /**
      * Connects the supplied {@link MidiInputPort} to the output port of this device
      * with the specified port number. Once the connection is made, the MidiInput port instance
-     * can no longer receive data via its {@link MidiReciever.receive} method.
-     * This method returns a {@link #MidiConnection} object, which can be used to close the connection
+     * can no longer receive data via its {@link MidiReceiver#onReceive} method.
+     * This method returns a {@link MidiDevice.MidiConnection} object, which can be used to close the connection
      * @param inputPort the inputPort to connect
      * @param outputPortNumber the port number of the output port to connect inputPort to.
-     * @return {@link #MidiConnection} object if the connection is successful, or null in case of failure
+     * @return {@link MidiDevice.MidiConnection} object if the connection is successful, or null in case of failure
      */
     public MidiConnection connectPorts(MidiInputPort inputPort, int outputPortNumber) {
         if (outputPortNumber < 0 || outputPortNumber >= mDeviceInfo.getOutputPortCount()) {
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index d27351f..bc85f92 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -24,6 +24,8 @@
 import android.system.OsConstants;
 import android.util.Log;
 
+import com.android.internal.midi.MidiDispatcher;
+
 import dalvik.system.CloseGuard;
 
 import libcore.io.IoUtils;
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index 1b98ca5..d62b2dc 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -38,9 +38,6 @@
  *
  * {@samplecode
  * MidiManager manager = (MidiManager) getSystemService(Context.MIDI_SERVICE);}
- *
- * CANDIDATE FOR PUBLIC API
- * @hide
  */
 public final class MidiManager {
     private static final String TAG = "MidiManager";
@@ -128,7 +125,7 @@
         /**
          * Called to notify when the status of a MIDI device has changed
          *
-         * @param device a {@link MidiDeviceStatus} for the changed device
+         * @param status a {@link MidiDeviceStatus} for the changed device
          */
         public void onDeviceStatusChanged(MidiDeviceStatus status) {
         }
@@ -221,7 +218,7 @@
      * Opens a MIDI device for reading and writing.
      *
      * @param deviceInfo a {@link android.media.midi.MidiDeviceInfo} to open
-     * @param callback a {@link #DeviceOpenCallback} to be called to receive the result
+     * @param callback a {@link MidiManager.DeviceOpenCallback} to be called to receive the result
      * @param handler the {@link android.os.Handler Handler} that will be used for delivering
      *                the result. If handler is null, then the thread used for the
      *                callback is unspecified.
diff --git a/media/java/android/media/midi/MidiOutputPort.java b/media/java/android/media/midi/MidiOutputPort.java
index b8ed36f..0290a76 100644
--- a/media/java/android/media/midi/MidiOutputPort.java
+++ b/media/java/android/media/midi/MidiOutputPort.java
@@ -21,6 +21,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.midi.MidiDispatcher;
+
 import dalvik.system.CloseGuard;
 
 import libcore.io.IoUtils;
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index 49087b0..adb6b06 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -15,8 +15,8 @@
 
 package android.media.session;
 
-import android.media.Rating;
 import android.content.Intent;
+import android.media.Rating;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.ResultReceiver;
@@ -30,8 +30,9 @@
 
     // These callbacks are for the TransportPerformer
     void onPlay();
-    void onPlayFromMediaId(String uri, in Bundle extras);
+    void onPlayFromMediaId(String mediaId, in Bundle extras);
     void onPlayFromSearch(String query, in Bundle extras);
+    void onPlayFromUri(in Uri uri, in Bundle extras);
     void onSkipToTrack(long id);
     void onPause();
     void onStop();
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index e2d06d3..8d58a60 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -23,9 +23,9 @@
 import android.media.routing.IMediaRouterDelegate;
 import android.media.routing.IMediaRouterStateCallback;
 import android.media.session.ISessionControllerCallback;
+import android.media.session.MediaSession;
 import android.media.session.ParcelableVolumeInfo;
 import android.media.session.PlaybackState;
-import android.media.session.MediaSession;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.ResultReceiver;
@@ -55,8 +55,9 @@
 
     // These commands are for the TransportControls
     void play();
-    void playFromMediaId(String uri, in Bundle extras);
+    void playFromMediaId(String mediaId, in Bundle extras);
     void playFromSearch(String string, in Bundle extras);
+    void playFromUri(in Uri uri, in Bundle extras);
     void skipToQueueItem(long id);
     void pause();
     void stop();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index c23a139..dd81a22 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -516,8 +516,8 @@
     }
 
     /**
-     * Callback for receiving updates on from the session. A Callback can be
-     * registered using {@link #registerCallback}
+     * Callback for receiving updates from the session. A Callback can be
+     * registered using {@link #registerCallback}.
      */
     public static abstract class Callback {
         /**
@@ -615,9 +615,9 @@
         }
 
         /**
-         * Request that the player start playback for a specific {@link Uri}.
+         * Request that the player start playback for a specific media id.
          *
-         * @param mediaId The uri of the requested media.
+         * @param mediaId The id of the requested media.
          * @param extras Optional extras that can include extra information about the media item
          *               to be played.
          */
@@ -656,6 +656,25 @@
         }
 
         /**
+         * Request that the player start playback for a specific {@link Uri}.
+         *
+         * @param uri  The URI of the requested media.
+         * @param extras Optional extras that can include extra information about the media item
+         *               to be played.
+         */
+        public void playFromUri(Uri uri, Bundle extras) {
+            if (uri == null || Uri.EMPTY.equals(uri)) {
+                throw new IllegalArgumentException(
+                        "You must specify a non-empty Uri for playFromUri.");
+            }
+            try {
+                mSessionBinder.playFromUri(uri, extras);
+            } catch (RemoteException e) {
+                Log.wtf(TAG, "Error calling play(" + uri + ").", e);
+            }
+        }
+
+        /**
          * Play an item with a specific id in the play queue. If you specify an
          * id that is not in the play queue, the behavior is undefined.
          */
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index cc602c9..cee82b4 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -30,6 +30,7 @@
 import android.media.Rating;
 import android.media.VolumeProvider;
 import android.media.routing.MediaRouter;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -541,6 +542,10 @@
         postToCallback(CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras);
     }
 
+    private void dispatchPlayFromUri(Uri uri, Bundle extras) {
+        postToCallback(CallbackMessageHandler.MSG_PLAY_URI, uri, extras);
+    }
+
     private void dispatchSkipToItem(long id) {
         postToCallback(CallbackMessageHandler.MSG_SKIP_TO_ITEM, id);
     }
@@ -833,6 +838,12 @@
         }
 
         /**
+         * Override to handle requests to play a specific media item represented by a URI.
+         */
+        public void onPlayFromUri(Uri uri, Bundle extras) {
+        }
+
+        /**
          * Override to handle requests to play an item with a given id from the
          * play queue.
          */
@@ -961,6 +972,14 @@
         }
 
         @Override
+        public void onPlayFromUri(Uri uri, Bundle extras) {
+            MediaSession session = mMediaSession.get();
+            if (session != null) {
+                session.dispatchPlayFromUri(uri, extras);
+            }
+        }
+
+        @Override
         public void onSkipToTrack(long id) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
@@ -1171,6 +1190,7 @@
         private static final int MSG_COMMAND = 15;
         private static final int MSG_ADJUST_VOLUME = 16;
         private static final int MSG_SET_VOLUME = 17;
+        private static final int MSG_PLAY_URI = 18;
 
         private MediaSession.Callback mCallback;
 
@@ -1210,6 +1230,9 @@
                 case MSG_PLAY_SEARCH:
                     mCallback.onPlayFromSearch((String) msg.obj, msg.getData());
                     break;
+                case MSG_PLAY_URI:
+                    mCallback.onPlayFromUri((Uri) msg.obj, msg.getData());
+                    break;
                 case MSG_SKIP_TO_ITEM:
                     mCallback.onSkipToQueueItem((Long) msg.obj);
                     break;
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 6807e7f..bbe04b5 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -126,6 +126,13 @@
     public static final long ACTION_SKIP_TO_QUEUE_ITEM = 1 << 12;
 
     /**
+     * Indicates this session supports the play from URI command.
+     *
+     * @see Builder#setActions(long)
+     */
+    public static final long ACTION_PLAY_FROM_URI = 1 << 13;
+
+    /**
      * This is the default playback state and indicates that no media has been
      * added yet, or the performer has been reset and has no content to play.
      *
@@ -353,6 +360,11 @@
      * <li> {@link PlaybackState#ACTION_SKIP_TO_NEXT}</li>
      * <li> {@link PlaybackState#ACTION_SEEK_TO}</li>
      * <li> {@link PlaybackState#ACTION_SET_RATING}</li>
+     * <li> {@link PlaybackState#ACTION_PLAY_PAUSE}</li>
+     * <li> {@link PlaybackState#ACTION_PLAY_FROM_MEDIA_ID}</li>
+     * <li> {@link PlaybackState#ACTION_PLAY_FROM_SEARCH}</li>
+     * <li> {@link PlaybackState#ACTION_SKIP_TO_QUEUE_ITEM}</li>
+     * <li> {@link PlaybackState#ACTION_PLAY_FROM_URI}</li>
      * </ul>
      */
     public long getActions() {
@@ -868,6 +880,11 @@
          * <li> {@link PlaybackState#ACTION_SKIP_TO_NEXT}</li>
          * <li> {@link PlaybackState#ACTION_SEEK_TO}</li>
          * <li> {@link PlaybackState#ACTION_SET_RATING}</li>
+         * <li> {@link PlaybackState#ACTION_PLAY_PAUSE}</li>
+         * <li> {@link PlaybackState#ACTION_PLAY_FROM_MEDIA_ID}</li>
+         * <li> {@link PlaybackState#ACTION_PLAY_FROM_SEARCH}</li>
+         * <li> {@link PlaybackState#ACTION_SKIP_TO_QUEUE_ITEM}</li>
+         * <li> {@link PlaybackState#ACTION_PLAY_FROM_URI}</li>
          * </ul>
          *
          * @param actions The set of actions allowed.
diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index 7a023d6..86c0e5d 100644
--- a/media/java/android/media/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -40,4 +40,7 @@
     void onContentAllowed(int seq);
     void onContentBlocked(in String rating, int seq);
     void onLayoutSurface(int left, int top, int right, int bottom, int seq);
+    void onTimeShiftStatusChanged(int status, int seq);
+    void onTimeShiftStartPositionChanged(long timeMs, int seq);
+    void onTimeShiftCurrentPositionChanged(long timeMs, int seq);
 }
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 21549c9..f96469e 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -74,6 +74,12 @@
 
     void requestUnblockContent(in IBinder sessionToken, in String unblockedRating, int userId);
 
+    void timeShiftPause(in IBinder sessionToken, int userId);
+    void timeShiftResume(in IBinder sessionToken, int userId);
+    void timeShiftSeekTo(in IBinder sessionToken, long timeMs, int userId);
+    void timeShiftSetPlaybackRate(in IBinder sessionToken, float rate, int audioMode, int userId);
+    void timeShiftTrackCurrentPosition(in IBinder sessionToken, boolean enabled, int userId);
+
     // For TV input hardware binding
     List<TvInputHardwareInfo> getHardwareList();
     ITvInputHardware acquireTvInputHardware(int deviceId, in ITvInputHardwareCallback callback,
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 1aad2fa..306abb8 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -46,4 +46,10 @@
     void removeOverlayView();
 
     void requestUnblockContent(in String unblockedRating);
+
+    void timeShiftPause();
+    void timeShiftResume();
+    void timeShiftSeekTo(long timeMs);
+    void timeShiftSetPlaybackRate(float rate, int audioMode);
+    void timeShiftTrackCurrentPosition(boolean enabled);
 }
diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
index 063d10d..e936810 100644
--- a/media/java/android/media/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -37,4 +37,7 @@
     void onContentAllowed();
     void onContentBlocked(in String rating);
     void onLayoutSurface(int left, int top, int right, int bottom);
+    void onTimeShiftStatusChanged(int status);
+    void onTimeShiftStartPositionChanged(long timeMs);
+    void onTimeShiftCurrentPositionChanged(long timeMs);
 }
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 94c9690..f22a8fc 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -57,6 +57,11 @@
     private static final int DO_RELAYOUT_OVERLAY_VIEW = 11;
     private static final int DO_REMOVE_OVERLAY_VIEW = 12;
     private static final int DO_REQUEST_UNBLOCK_CONTENT = 13;
+    private static final int DO_TIME_SHIFT_PAUSE = 14;
+    private static final int DO_TIME_SHIFT_RESUME = 15;
+    private static final int DO_TIME_SHIFT_SEEK_TO = 16;
+    private static final int DO_TIME_SHIFT_SET_PLAYBACK_RATE = 17;
+    private static final int DO_TIME_SHIFT_TRACK_CURRENT_POSITION = 18;
 
     private final HandlerCaller mCaller;
 
@@ -153,6 +158,26 @@
                 mTvInputSessionImpl.unblockContent((String) msg.obj);
                 break;
             }
+            case DO_TIME_SHIFT_PAUSE: {
+                mTvInputSessionImpl.timeShiftPause();
+                break;
+            }
+            case DO_TIME_SHIFT_RESUME: {
+                mTvInputSessionImpl.timeShiftResume();
+                break;
+            }
+            case DO_TIME_SHIFT_SEEK_TO: {
+                mTvInputSessionImpl.timeShiftSeekTo((Long) msg.obj);
+                break;
+            }
+            case DO_TIME_SHIFT_SET_PLAYBACK_RATE: {
+                mTvInputSessionImpl.timeShiftSetPlaybackRate((Float) msg.obj, msg.arg1);
+                break;
+            }
+            case DO_TIME_SHIFT_TRACK_CURRENT_POSITION: {
+                mTvInputSessionImpl.timeShiftTrackCurrentPosition((Boolean) msg.obj);
+                break;
+            }
             default: {
                 Log.w(TAG, "Unhandled message code: " + msg.what);
                 break;
@@ -242,6 +267,34 @@
                 DO_REQUEST_UNBLOCK_CONTENT, unblockedRating));
     }
 
+    @Override
+    public void timeShiftPause() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_TIME_SHIFT_PAUSE));
+    }
+
+    @Override
+    public void timeShiftResume() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_TIME_SHIFT_RESUME));
+    }
+
+    @Override
+    public void timeShiftSeekTo(long timeMs) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_TIME_SHIFT_SEEK_TO,
+                Long.valueOf(timeMs)));
+    }
+
+    @Override
+    public void timeShiftSetPlaybackRate(float rate, int audioMode) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageIO(DO_TIME_SHIFT_SET_PLAYBACK_RATE,
+                audioMode, Float.valueOf(rate)));
+    }
+
+    @Override
+    public void timeShiftTrackCurrentPosition(boolean enabled) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_TIME_SHIFT_TRACK_CURRENT_POSITION,
+                Boolean.valueOf(enabled)));
+    }
+
     private final class TvInputEventReceiver extends InputEventReceiver {
         public TvInputEventReceiver(InputChannel inputChannel, Looper looper) {
             super(inputChannel, looper);
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index f55299e..a4d8174 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -71,6 +71,28 @@
      */
     public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = VIDEO_UNAVAILABLE_REASON_END;
 
+    private static final int TIME_SHIFT_STATUS_START = 0;
+    private static final int TIME_SHIFT_STATUS_END = 2;
+
+    /**
+     * Time shifting is available. In this status, the application can pause/resume the playback,
+     * seek to a specific position, and change the playback rate.
+     */
+    public static final int TIME_SHIFT_STATUS_AVAILABLE = TIME_SHIFT_STATUS_START;
+
+    /**
+     * Time shifting is not available.
+     */
+    public static final int TIME_SHIFT_STATUS_UNAVAILABLE = 1;
+
+    /**
+     * An error occurred while handling a time shift request. To recover the status, tune to a
+     * new channel.
+     */
+    public static final int TIME_SHIFT_STATUS_ERROR = TIME_SHIFT_STATUS_END;
+
+    public static final long TIME_SHIFT_INVALID_TIME = Long.MIN_VALUE;
+
     /**
      * The TV input is in unknown state.
      * <p>
@@ -271,7 +293,7 @@
         /**
          * This is called when the video is not available, so the TV input stops the playback.
          *
-         * @param session A {@link TvInputManager.Session} associated with this callback
+         * @param session A {@link TvInputManager.Session} associated with this callback.
          * @param reason The reason why the TV input stopped the playback:
          * <ul>
          * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
@@ -287,7 +309,7 @@
          * This is called when the current program content turns out to be allowed to watch since
          * its content rating is not blocked by parental controls.
          *
-         * @param session A {@link TvInputManager.Session} associated with this callback
+         * @param session A {@link TvInputManager.Session} associated with this callback.
          */
         public void onContentAllowed(Session session) {
         }
@@ -296,7 +318,7 @@
          * This is called when the current program content turns out to be not allowed to watch
          * since its content rating is blocked by parental controls.
          *
-         * @param session A {@link TvInputManager.Session} associated with this callback
+         * @param session A {@link TvInputManager.Session} associated with this callback.
          * @param rating The content ration of the blocked program.
          */
         public void onContentBlocked(Session session, TvContentRating rating) {
@@ -306,7 +328,7 @@
          * This is called when {@link TvInputService.Session#layoutSurface} is called to change the
          * layout of surface.
          *
-         * @param session A {@link TvInputManager.Session} associated with this callback
+         * @param session A {@link TvInputManager.Session} associated with this callback.
          * @param left Left position.
          * @param top Top position.
          * @param right Right position.
@@ -328,6 +350,40 @@
         @SystemApi
         public void onSessionEvent(Session session, String eventType, Bundle eventArgs) {
         }
+
+        /**
+         * This is called when the trick play status is changed.
+         *
+         * @param session A {@link TvInputManager.Session} associated with this callback.
+         * @param status The current time shift status:
+         * <ul>
+         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_AVAILABLE}
+         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_UNAVAILABLE}
+         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_ERROR}
+         * </ul>
+         */
+        public void onTimeShiftStatusChanged(Session session, int status) {
+        }
+
+        /**
+         * This is called when the time shift start position is changed. The application may seek to
+         * a position in the range from the start position and the current time, inclusive.
+         *
+         * @param session A {@link TvInputManager.Session} associated with this callback.
+         * @param timeMs The start of the possible time shift range, in milliseconds since the
+         *         epoch.
+         */
+        public void onTimeShiftStartPositionChanged(Session session, long timeMs) {
+        }
+
+        /**
+         * This is called when the current position is changed.
+         *
+         * @param session A {@link TvInputManager.Session} associated with this callback.
+         * @param timeMs The current position, in milliseconds since the epoch.
+         */
+        public void onTimeShiftCurrentPositionChanged(Session session, long timeMs) {
+        }
     }
 
     private static final class SessionCallbackRecord {
@@ -450,6 +506,33 @@
                 }
             });
         }
+
+        void postTimeShiftStatusChanged(final int status) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onTimeShiftStatusChanged(mSession, status);
+                }
+            });
+        }
+
+        void postTimeShiftStartPositionChanged(final long timeMs) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onTimeShiftStartPositionChanged(mSession, timeMs);
+                }
+            });
+        }
+
+        void postTimeShiftCurrentPositionChanged(final long timeMs) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mSessionCallback.onTimeShiftCurrentPositionChanged(mSession, timeMs);
+                }
+            });
+        }
     }
 
     /**
@@ -718,6 +801,42 @@
                     record.postSessionEvent(eventType, eventArgs);
                 }
             }
+
+            @Override
+            public void onTimeShiftStatusChanged(int status, int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postTimeShiftStatusChanged(status);
+                }
+            }
+
+            @Override
+            public void onTimeShiftStartPositionChanged(long timeMs, int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postTimeShiftStartPositionChanged(timeMs);
+                }
+            }
+
+            @Override
+            public void onTimeShiftCurrentPositionChanged(long timeMs, int seq) {
+                synchronized (mSessionCallbackRecordMap) {
+                    SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+                    if (record == null) {
+                        Log.e(TAG, "Callback not found for seq " + seq);
+                        return;
+                    }
+                    record.postTimeShiftCurrentPositionChanged(timeMs);
+                }
+            }
         };
         mManagerCallback = new ITvInputManagerCallback.Stub() {
             @Override
@@ -1171,22 +1290,22 @@
         private TvInputEventSender mSender;
         private InputChannel mChannel;
 
-        private final Object mTrackLock = new Object();
-        // @GuardedBy("mTrackLock")
+        private final Object mMetadataLock = new Object();
+        // @GuardedBy("mMetadataLock")
         private final List<TvTrackInfo> mAudioTracks = new ArrayList<TvTrackInfo>();
-        // @GuardedBy("mTrackLock")
+        // @GuardedBy("mMetadataLock")
         private final List<TvTrackInfo> mVideoTracks = new ArrayList<TvTrackInfo>();
-        // @GuardedBy("mTrackLock")
+        // @GuardedBy("mMetadataLock")
         private final List<TvTrackInfo> mSubtitleTracks = new ArrayList<TvTrackInfo>();
-        // @GuardedBy("mTrackLock")
+        // @GuardedBy("mMetadataLock")
         private String mSelectedAudioTrackId;
-        // @GuardedBy("mTrackLock")
+        // @GuardedBy("mMetadataLock")
         private String mSelectedVideoTrackId;
-        // @GuardedBy("mTrackLock")
+        // @GuardedBy("mMetadataLock")
         private String mSelectedSubtitleTrackId;
-        // @GuardedBy("mTrackLock")
+        // @GuardedBy("mMetadataLock")
         private int mVideoWidth;
-        // @GuardedBy("mTrackLock")
+        // @GuardedBy("mMetadataLock")
         private int mVideoHeight;
 
         private Session(IBinder token, InputChannel channel, ITvInputManager service, int userId,
@@ -1322,7 +1441,7 @@
                 Log.w(TAG, "The session has been already released");
                 return;
             }
-            synchronized (mTrackLock) {
+            synchronized (mMetadataLock) {
                 mAudioTracks.clear();
                 mVideoTracks.clear();
                 mSubtitleTracks.clear();
@@ -1367,7 +1486,7 @@
          * @see #getTracks
          */
         public void selectTrack(int type, String trackId) {
-            synchronized (mTrackLock) {
+            synchronized (mMetadataLock) {
                 if (type == TvTrackInfo.TYPE_AUDIO) {
                     if (trackId != null && !containsTrack(mAudioTracks, trackId)) {
                         Log.w(TAG, "Invalid audio trackId: " + trackId);
@@ -1416,7 +1535,7 @@
          * @return the list of tracks for the given type.
          */
         public List<TvTrackInfo> getTracks(int type) {
-            synchronized (mTrackLock) {
+            synchronized (mMetadataLock) {
                 if (type == TvTrackInfo.TYPE_AUDIO) {
                     if (mAudioTracks == null) {
                         return null;
@@ -1445,7 +1564,7 @@
          * @see #selectTrack
          */
         public String getSelectedTrack(int type) {
-            synchronized (mTrackLock) {
+            synchronized (mMetadataLock) {
                 if (type == TvTrackInfo.TYPE_AUDIO) {
                     return mSelectedAudioTrackId;
                 } else if (type == TvTrackInfo.TYPE_VIDEO) {
@@ -1462,7 +1581,7 @@
          * there is an update.
          */
         boolean updateTracks(List<TvTrackInfo> tracks) {
-            synchronized (mTrackLock) {
+            synchronized (mMetadataLock) {
                 mAudioTracks.clear();
                 mVideoTracks.clear();
                 mSubtitleTracks.clear();
@@ -1485,7 +1604,7 @@
          * Returns true if there is an update.
          */
         boolean updateTrackSelection(int type, String trackId) {
-            synchronized (mTrackLock) {
+            synchronized (mMetadataLock) {
                 if (type == TvTrackInfo.TYPE_AUDIO && trackId != mSelectedAudioTrackId) {
                     mSelectedAudioTrackId = trackId;
                     return true;
@@ -1509,7 +1628,7 @@
          * track.
          */
         TvTrackInfo getVideoTrackToNotify() {
-            synchronized (mTrackLock) {
+            synchronized (mMetadataLock) {
                 if (!mVideoTracks.isEmpty() && mSelectedVideoTrackId != null) {
                     for (TvTrackInfo track : mVideoTracks) {
                         if (track.getId().equals(mSelectedVideoTrackId)) {
@@ -1528,6 +1647,92 @@
         }
 
         /**
+         * Pauses the playback. Call {@link #timeShiftResume()} to restart the playback.
+         */
+        void timeShiftPause() {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.timeShiftPause(mToken, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
+         * Resumes the playback. No-op if it is already playing the channel.
+         */
+        void timeShiftResume() {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.timeShiftResume(mToken, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
+         * Seeks to the specific time position. The position should be in the range from the start
+         * time from the start time,
+         * {@link TvInputCallback#onTimeShiftStartPositionChanged(String, long)}, to the current
+         * time, inclusive.
+         *
+         * @param timeMs The target time, in milliseconds since the epoch.
+         */
+        void timeShiftSeekTo(long timeMs) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.timeShiftSeekTo(mToken, timeMs, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
+         * Sets a playback rate and an audio mode.
+         *
+         * @param rate The ratio between desired playback rate and normal one.
+         * @param audioMode The audio playback mode. Must be one of the supported audio modes:
+         * <ul>
+         * <li> {@link android.media.MediaPlayer#PLAYBACK_RATE_AUDIO_MODE_RESAMPLE}
+         * </ul>
+         */
+        void timeShiftSetPlaybackRate(float rate, int audioMode) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.timeShiftSetPlaybackRate(mToken, rate, audioMode, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
+         * Returns the current playback position.
+         */
+        void timeShiftTrackCurrentPosition(boolean enabled) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.timeShiftTrackCurrentPosition(mToken, enabled, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
          * Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle)
          * TvInputService.Session.appPrivateCommand()} on the current TvView.
          *
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index b887855..93abc2b 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -235,7 +235,9 @@
      * Base class for derived classes to implement to provide a TV input session.
      */
     public abstract static class Session implements KeyEvent.Callback {
-        private static final int DETACH_OVERLAY_VIEW_TIMEOUT = 5000;
+        private static final int DETACH_OVERLAY_VIEW_TIMEOUT_MS = 5000;
+        private static final int POSITION_UPDATE_INTERVAL_MS = 1000;
+
         private final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState();
         private final WindowManager mWindowManager;
         final Handler mHandler;
@@ -248,6 +250,10 @@
         private boolean mOverlayViewEnabled;
         private IBinder mWindowToken;
         private Rect mOverlayFrame;
+        private long mCurrentPositionMs;
+        private final TimeShiftCurrentPositionTrackingRunnable
+                mTimeShiftCurrentPositionTrackingRunnable =
+                new TimeShiftCurrentPositionTrackingRunnable();
 
         private final Object mLock = new Object();
         // @GuardedBy("mLock")
@@ -264,6 +270,7 @@
             mContext = context;
             mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
             mHandler = new Handler(context.getMainLooper());
+            mCurrentPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
         }
 
         /**
@@ -550,6 +557,89 @@
         }
 
         /**
+         * Informs the application that the trick play status is changed.
+         * <p>
+         * The application assumes that time shift is not available by default. So, the
+         * implementation should call this method with
+         * {@link TvInputManager#TIME_SHIFT_STATUS_AVAILABLE} on tune request, if the time shift is
+         * available in the given channel.
+         * Note that sending {@link TvInputManager#TIME_SHIFT_STATUS_AVAILABLE} means the session
+         * implemented {@link #onTimeShiftPause}, {@link #onTimeShiftResume},
+         * {@link #onTimeShiftSeekTo}, {@link #onTimeShiftGetCurrentPosition}, and
+         * {@link #onTimeShiftSetPlaybackRate}, and these are working at the moment.
+         * </p>
+         *
+         * @param status The current time shift status:
+         * <ul>
+         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_AVAILABLE}
+         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_UNAVAILABLE}
+         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_ERROR}
+         * </ul>
+         */
+        public void notifyTimeShiftStatusChanged(final int status) {
+            executeOrPostRunnable(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) Log.d(TAG, "notifyTimeShiftStatusChanged");
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onTimeShiftStatusChanged(status);
+                        }
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in notifyTimeShiftStatusChanged");
+                    }
+                }
+            });
+        }
+
+        /**
+         * Informs the application that the time shift start position is changed.
+         * <p>
+         * The application may seek to a position in the range from the start position and the
+         * current time, inclusive. So, the implementation should call this whenever the range is
+         * updated.
+         * </p>
+         *
+         * @param timeMs the start of possible time shift range, in milliseconds since the epoch.
+         */
+        public void notifyTimeShiftStartPositionChanged(final long timeMs) {
+            executeOrPostRunnable(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) Log.d(TAG, "notifyTimeShiftStartPositionChanged");
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onTimeShiftStartPositionChanged(timeMs);
+                        }
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in notifyTimeShiftStartPositionChanged");
+                    }
+                }
+            });
+        }
+
+        /**
+         * Informs the application that the current playback position is changed.
+         *
+         * @param timeMs The current position, in milliseconds since the epoch.
+         */
+        private void notifyTimeShiftCurrentPositionChanged(final long timeMs) {
+            executeOrPostRunnable(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        if (DEBUG) Log.d(TAG, "notifyTimeShiftCurrentPositionChanged");
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onTimeShiftCurrentPositionChanged(timeMs);
+                        }
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "error in notifyTimeShiftCurrentPositionChanged");
+                    }
+                }
+            });
+        }
+
+        /**
          * Assigns a position of the {@link Surface} passed by {@link #onSetSurface}. The position
          * is relative to an overlay view.
          *
@@ -756,6 +846,72 @@
         }
 
         /**
+         * Called when an application requests to pause the playback.
+         *
+         * @see #onTimeShiftResume()
+         * @see #onTimeShiftSeekTo(long)
+         * @see #onTimeShiftSetPlaybackRate(float, int)
+         * @see #onTimeShiftGetCurrentPosition()
+         */
+        public void onTimeShiftPause() {
+        }
+
+        /**
+         * Called when an application requests to resume the playback.
+         *
+         * @see #onTimeShiftPause()
+         * @see #onTimeShiftSeekTo(long)
+         * @see #onTimeShiftSetPlaybackRate(float, int)
+         * @see #onTimeShiftGetCurrentPosition()
+         */
+        public void onTimeShiftResume() {
+        }
+
+        /**
+         * Called when an application requests to seek to a specific position. The {@code timeMs} is
+         * expected to be in a range from the start time,
+         * {@link #notifyTimeShiftStartPositionChanged(long)}, to the current time, inclusive. If it
+         * is not, the implementation should seek to the nearest time position in the range.
+         *
+         * @param timeMs The target time, in milliseconds since the epoch
+         * @see #onTimeShiftResume()
+         * @see #onTimeShiftPause()
+         * @see #onTimeShiftSetPlaybackRate(float, int)
+         * @see #onTimeShiftGetCurrentPosition()
+         */
+        public void onTimeShiftSeekTo(long timeMs) {
+        }
+
+        /**
+         * Called when an application sets a playback rate and an audio mode.
+         *
+         * @param rate The ratio between desired playback rate and normal one.
+         * @param audioMode The audio playback mode. Must be one of the supported audio modes:
+         * <ul>
+         * <li> {@link android.media.MediaPlayer#PLAYBACK_RATE_AUDIO_MODE_RESAMPLE}
+         * </ul>
+         * @see #onTimeShiftResume()
+         * @see #onTimeShiftPause()
+         * @see #onTimeShiftSeekTo(long)
+         * @see #onTimeShiftGetCurrentPosition()
+         */
+        public void onTimeShiftSetPlaybackRate(float rate, int audioMode) {
+        }
+
+        /**
+         * Returns the current playback position in milliseconds since the epoch.
+         * {@link TvInputManager#TIME_SHIFT_INVALID_TIME} if position is unknown at this moment.
+         *
+         * @see #onTimeShiftResume()
+         * @see #onTimeShiftPause()
+         * @see #onTimeShiftSeekTo(long)
+         * @see #onTimeShiftSetPlaybackRate(float, int)
+         */
+        public long onTimeShiftGetCurrentPosition() {
+            return TvInputManager.TIME_SHIFT_INVALID_TIME;
+        }
+
+        /**
          * Default implementation of {@link android.view.KeyEvent.Callback#onKeyDown(int, KeyEvent)
          * KeyEvent.Callback.onKeyDown()}: always returns false (doesn't handle the event).
          * <p>
@@ -887,6 +1043,7 @@
             // Removes the overlay view lastly so that any hanging on the main thread can be handled
             // in {@link #scheduleOverlayViewCleanup}.
             removeOverlayView(true);
+            mHandler.removeCallbacks(mTimeShiftCurrentPositionTrackingRunnable);
         }
 
         /**
@@ -930,6 +1087,7 @@
          * Calls {@link #onTune}.
          */
         void tune(Uri channelUri, Bundle params) {
+            mCurrentPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
             onTune(channelUri, params);
             // TODO: Handle failure.
         }
@@ -1059,6 +1217,46 @@
         }
 
         /**
+         * Calls {@link #onTimeShiftPause}.
+         */
+        void timeShiftPause() {
+            onTimeShiftPause();
+        }
+
+        /**
+         * Calls {@link #onTimeShiftResume}.
+         */
+        void timeShiftResume() {
+            onTimeShiftResume();
+        }
+
+        /**
+         * Calls {@link #onTimeShiftSeekTo}.
+         */
+        void timeShiftSeekTo(long timeMs) {
+            onTimeShiftSeekTo(timeMs);
+        }
+
+        /**
+         * Calls {@link #onTimeShiftSetPlaybackRate}.
+         */
+        void timeShiftSetPlaybackRate(float rate, int audioMode) {
+            onTimeShiftSetPlaybackRate(rate, audioMode);
+        }
+
+        /**
+         * Turns on/off the current position tracking.
+         */
+        void timeShiftTrackCurrentPosition(boolean enabled) {
+            if (enabled) {
+                mHandler.post(mTimeShiftCurrentPositionTrackingRunnable);
+            } else {
+                mHandler.removeCallbacks(mTimeShiftCurrentPositionTrackingRunnable);
+                mCurrentPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
+            }
+        }
+
+        /**
          * Schedules a task which checks whether the overlay view is detached and kills the process
          * if it is not. Note that this method is expected to be called in a non-main thread.
          */
@@ -1077,12 +1275,19 @@
         int dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
             if (DEBUG) Log.d(TAG, "dispatchInputEvent(" + event + ")");
             boolean isNavigationKey = false;
+            boolean skipDispatchToOverlayView = false;
             if (event instanceof KeyEvent) {
                 KeyEvent keyEvent = (KeyEvent) event;
-                isNavigationKey = isNavigationKey(keyEvent.getKeyCode());
                 if (keyEvent.dispatch(this, mDispatcherState, this)) {
                     return TvInputManager.Session.DISPATCH_HANDLED;
                 }
+                isNavigationKey = isNavigationKey(keyEvent.getKeyCode());
+                // When media keys and KEYCODE_MEDIA_AUDIO_TRACK are dispatched to ViewRootImpl,
+                // ViewRootImpl always consumes the keys. In this case, an application loses
+                // a chance to handle media keys. Therefore, media keys are not dispatched to
+                // ViewRootImpl.
+                skipDispatchToOverlayView = KeyEvent.isMediaKey(keyEvent.getKeyCode())
+                        || keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK;
             } else if (event instanceof MotionEvent) {
                 MotionEvent motionEvent = (MotionEvent) event;
                 final int source = motionEvent.getSource();
@@ -1100,7 +1305,8 @@
                     }
                 }
             }
-            if (mOverlayViewContainer == null || !mOverlayViewContainer.isAttachedToWindow()) {
+            if (mOverlayViewContainer == null || !mOverlayViewContainer.isAttachedToWindow()
+                    || skipDispatchToOverlayView) {
                 return TvInputManager.Session.DISPATCH_NOT_HANDLED;
             }
             if (!mOverlayViewContainer.hasWindowFocus()) {
@@ -1146,12 +1352,26 @@
             }
         }
 
+        private final class TimeShiftCurrentPositionTrackingRunnable implements Runnable {
+            @Override
+            public void run() {
+                long pos = onTimeShiftGetCurrentPosition();
+                if (mCurrentPositionMs != pos) {
+                    mCurrentPositionMs = pos;
+                    notifyTimeShiftCurrentPositionChanged(pos);
+                }
+                mHandler.removeCallbacks(mTimeShiftCurrentPositionTrackingRunnable);
+                mHandler.postDelayed(mTimeShiftCurrentPositionTrackingRunnable,
+                        POSITION_UPDATE_INTERVAL_MS);
+            }
+        }
+
         private final class OverlayViewCleanUpTask extends AsyncTask<View, Void, Void> {
             @Override
             protected Void doInBackground(View... views) {
                 View overlayViewParent = views[0];
                 try {
-                    Thread.sleep(DETACH_OVERLAY_VIEW_TIMEOUT);
+                    Thread.sleep(DETACH_OVERLAY_VIEW_TIMEOUT_MS);
                 } catch (InterruptedException e) {
                     return null;
                 }
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 6fc1b82..115d094 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -42,6 +42,7 @@
 import android.view.ViewRootImpl;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -103,6 +104,7 @@
     private int mSurfaceViewRight;
     private int mSurfaceViewTop;
     private int mSurfaceViewBottom;
+    private List<TimeShiftPositionCallback> mTimeShiftPositionCallbacks = new ArrayList<>();
 
     private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
         @Override
@@ -420,6 +422,85 @@
     }
 
     /**
+     * Pauses the playback. Call {@link #timeShiftResume()} to restart the playback.
+     */
+    public void timeShiftPause() {
+        if (mSession != null) {
+            mSession.timeShiftPause();
+        }
+    }
+
+    /**
+     * Resumes the playback. No-op if it is already playing the channel.
+     */
+    public void timeShiftResume() {
+        if (mSession != null) {
+            mSession.timeShiftResume();
+        }
+    }
+
+    /**
+     * Seeks to the specific time position. The position should be in the range from the start time
+     * from the start time, {@link TimeShiftPositionCallback#onTimeShiftStartPositionChanged},
+     * to the current time, inclusive.
+     *
+     * @param timeMs The target time, in milliseconds since the epoch.
+     */
+    public void timeShiftSeekTo(long timeMs) {
+        if (mSession != null) {
+            mSession.timeShiftSeekTo(timeMs);
+        }
+    }
+
+    /**
+     * Sets a playback rate and an audio mode.
+     *
+     * @param rate The ratio between desired playback rate and normal one.
+     * @param audioMode The audio playback mode. Must be one of the supported audio modes:
+     * <ul>
+     * <li> {@link android.media.MediaPlayer#PLAYBACK_RATE_AUDIO_MODE_RESAMPLE}
+     * </ul>
+     */
+    public void timeShiftSetPlaybackRate(float rate, int audioMode) {
+        if (mSession != null) {
+            mSession.timeShiftSetPlaybackRate(rate, audioMode);
+        }
+    }
+
+    /**
+     * Registers a {@link TvView.TimeShiftPositionCallback}.
+     *
+     * @param callback A callback used to monitor the time shift range and current position.
+     */
+    public void registerTimeShiftPositionCallback(TimeShiftPositionCallback callback) {
+        if (callback == null) {
+            throw new IllegalArgumentException("callback can not be null.");
+        }
+        mTimeShiftPositionCallbacks.add(callback);
+        ensureCurrentPositionTracking();
+    }
+
+    /**
+     * Unregisters the existing {@link TvView.TimeShiftPositionCallback}.
+     *
+     * @param callback The existing callback to remove.
+     */
+    public void unregisterTimeShiftPositionCallback(TimeShiftPositionCallback callback) {
+        if (callback == null) {
+            throw new IllegalArgumentException("callback can not be null.");
+        }
+        mTimeShiftPositionCallbacks.remove(callback);
+        ensureCurrentPositionTracking();
+    }
+
+    private void ensureCurrentPositionTracking() {
+        if (mSession == null) {
+            return;
+        }
+        mSession.timeShiftTrackCurrentPosition(!mTimeShiftPositionCallbacks.isEmpty());
+    }
+
+    /**
      * Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle)
      * TvInputService.Session.appPrivateCommand()} on the current TvView.
      *
@@ -729,6 +810,32 @@
     }
 
     /**
+     * Callback used to receive the information on the possible range for time shifting and currrent
+     * position.
+     */
+    public abstract static class TimeShiftPositionCallback {
+        /**
+         * This is called when the time shift start position is changed. The application may seek to
+         * a position in the range from the start position and the current time, inclusive.
+         *
+         * @param inputId The ID of the TV input bound to this view.
+         * @param timeMs the start of the possible time shift range, in milliseconds since the
+         *         epoch.
+         */
+        public void onTimeShiftStartPositionChanged(String inputId, long timeMs) {
+        }
+
+        /**
+         * This is called when the current playback position is changed.
+         *
+         * @param inputId The ID of the TV input bound to this view.
+         * @param timeMs The current position, in milliseconds since the epoch.
+         */
+        public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) {
+        }
+    }
+
+    /**
      * Callback used to receive various status updates on the {@link TvView}.
      */
     public abstract static class TvInputCallback {
@@ -838,6 +945,7 @@
         /**
          * This is invoked when a custom event from the bound TV input is sent to this view.
          *
+         * @param inputId The ID of the TV input bound to this view.
          * @param eventType The type of the event.
          * @param eventArgs Optional arguments of the event.
          * @hide
@@ -845,6 +953,20 @@
         @SystemApi
         public void onEvent(String inputId, String eventType, Bundle eventArgs) {
         }
+
+        /**
+         * This is called when the time shift status is changed.
+         *
+         * @param inputId The ID of the TV input bound to this view.
+         * @param status The current time shift status:
+         * <ul>
+         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_AVAILABLE}
+         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_UNAVAILABLE}
+         * <li>{@link TvInputManager#TIME_SHIFT_STATUS_ERROR}
+         * </ul>
+         */
+        public void onTimeShiftStatusChanged(String inputId, int status) {
+        }
     }
 
     /**
@@ -918,6 +1040,7 @@
                     mAppPrivateCommandAction = null;
                     mAppPrivateCommandData = null;
                 }
+                ensureCurrentPositionTracking();
             } else {
                 mSessionCallback = null;
                 if (mCallback != null) {
@@ -1087,5 +1210,47 @@
                 mCallback.onEvent(mInputId, eventType, eventArgs);
             }
         }
+
+        @Override
+        public void onTimeShiftStatusChanged(Session session, int status) {
+            if (DEBUG) {
+                Log.d(TAG, "onTimeShiftStatusChanged()");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onTimeShiftStatusChanged - session not created");
+                return;
+            }
+            if (mCallback != null) {
+                mCallback.onTimeShiftStatusChanged(mInputId, status);
+            }
+        }
+
+        @Override
+        public void onTimeShiftStartPositionChanged(Session session, long timeMs) {
+            if (DEBUG) {
+                Log.d(TAG, "onTimeShiftStartPositionChanged()");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onTimeShiftStartPositionChanged - session not created");
+                return;
+            }
+            for (TimeShiftPositionCallback callback : mTimeShiftPositionCallbacks) {
+                callback.onTimeShiftStartPositionChanged(mInputId, timeMs);
+            }
+        }
+
+        @Override
+        public void onTimeShiftCurrentPositionChanged(Session session, long timeMs) {
+            if (DEBUG) {
+                Log.d(TAG, "onTimeShiftCurrentPositionChanged()");
+            }
+            if (this != mSessionCallback) {
+                Log.w(TAG, "onTimeShiftCurrentPositionChanged - session not created");
+                return;
+            }
+            for (TimeShiftPositionCallback callback : mTimeShiftPositionCallbacks) {
+                callback.onTimeShiftCurrentPositionChanged(mInputId, timeMs);
+            }
+        }
     }
 }
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index e20eabc..3641ff5 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -38,7 +38,7 @@
     public MtpStorage(StorageVolume volume, Context context) {
         mStorageId = volume.getStorageId();
         mPath = volume.getPath();
-        mDescription = context.getResources().getString(volume.getDescriptionId());
+        mDescription = volume.getDescription(context);
         mReserveSpace = volume.getMtpReserveSpace() * 1024L * 1024L;
         mRemovable = volume.isRemovable();
         mMaxFileSize = volume.getMaxFileSize();
@@ -59,7 +59,7 @@
      *
      * @return the storage ID
      */
-    public static int getStorageId(int index) {
+    public static int getStorageIdForIndex(int index) {
         // storage ID is 0x00010001 for primary storage,
         // then 0x00020001, 0x00030001, etc. for secondary storages
         return ((index + 1) << 16) + 1;
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index dae57a8..5b177e5 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -10,11 +10,12 @@
     android_media_MediaDrm.cpp \
     android_media_MediaExtractor.cpp \
     android_media_MediaHTTPConnection.cpp \
+    android_media_MediaMetadataRetriever.cpp \
     android_media_MediaMuxer.cpp \
     android_media_MediaPlayer.cpp \
     android_media_MediaRecorder.cpp \
     android_media_MediaScanner.cpp \
-    android_media_MediaMetadataRetriever.cpp \
+    android_media_MediaSync.cpp \
     android_media_ResampleInputStream.cpp \
     android_media_MediaProfiles.cpp \
     android_media_AmrInputStream.cpp \
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 9fc7e8e..708c083 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -431,6 +431,19 @@
             pData = buffer->data;
             dataSize = buffer->stride * buffer->height;
             break;
+        case HAL_PIXEL_FORMAT_RAW12:
+            // Single plane 10bpp bayer data.
+            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+            LOG_ALWAYS_FATAL_IF(buffer->width % 4,
+                                "Width is not multiple of 4 %d", buffer->width);
+            LOG_ALWAYS_FATAL_IF(buffer->height % 2,
+                                "Height is not even %d", buffer->height);
+            LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),
+                                "stride (%d) should be at least %d",
+                                buffer->stride, buffer->width * 12 / 8);
+            pData = buffer->data;
+            dataSize = buffer->stride * buffer->height;
+            break;
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
             // Single plane, 32bpp.
@@ -492,8 +505,10 @@
             break;
         case HAL_PIXEL_FORMAT_BLOB:
         case HAL_PIXEL_FORMAT_RAW10:
-            // Blob is used for JPEG data, RAW10 is used for 10-bit raw data, they are
-            // single plane, row and pixel strides are 0.
+        case HAL_PIXEL_FORMAT_RAW12:
+            // Blob is used for JPEG data, RAW10 and RAW12 is used for 10-bit and 12-bit raw data,
+            // those are single plane data with pixel stride 0 since they don't really have a
+            // well defined pixel stride
             ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
             pixelStride = 0;
             break;
@@ -549,12 +564,14 @@
             rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
             break;
         case HAL_PIXEL_FORMAT_BLOB:
-            // Blob is used for JPEG data, RAW10 is used for 10-bit raw data, they are
-            // single plane, row and pixel strides are 0.
+            // Blob is used for JPEG data. It is single plane and has 0 row stride and
+            // 0 pixel stride
             ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
             rowStride = 0;
             break;
         case HAL_PIXEL_FORMAT_RAW10:
+        case HAL_PIXEL_FORMAT_RAW12:
+            // RAW10 and RAW12 are used for 10-bit and 12-bit raw data, they are single plane
             ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
             rowStride = buffer->stride;
             break;
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index b748f3a..3e41716 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -926,6 +926,7 @@
 extern int register_android_media_MediaMuxer(JNIEnv *env);
 extern int register_android_media_MediaRecorder(JNIEnv *env);
 extern int register_android_media_MediaScanner(JNIEnv *env);
+extern int register_android_media_MediaSync(JNIEnv *env);
 extern int register_android_media_ResampleInputStream(JNIEnv *env);
 extern int register_android_media_MediaProfiles(JNIEnv *env);
 extern int register_android_media_AmrInputStream(JNIEnv *env);
@@ -1009,6 +1010,11 @@
         goto bail;
     }
 
+    if (register_android_media_MediaSync(env) < 0) {
+        ALOGE("ERROR: MediaSync native registration failed");
+        goto bail;
+    }
+
     if (register_android_media_MediaExtractor(env) < 0) {
         ALOGE("ERROR: MediaCodec native registration failed");
         goto bail;
diff --git a/media/jni/android_media_MediaSync.cpp b/media/jni/android_media_MediaSync.cpp
new file mode 100644
index 0000000..f31b511
--- /dev/null
+++ b/media/jni/android_media_MediaSync.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaSync-JNI"
+#include <utils/Log.h>
+
+#include "android_media_MediaSync.h"
+
+#include "android_media_AudioTrack.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/android_view_Surface.h"
+#include "jni.h"
+#include "JNIHelp.h"
+
+#include <gui/Surface.h>
+
+#include <media/AudioTrack.h>
+#include <media/stagefright/MediaSync.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+
+#include <nativehelper/ScopedLocalRef.h>
+
+namespace android {
+
+struct fields_t {
+    jfieldID context;
+};
+
+static fields_t gFields;
+
+////////////////////////////////////////////////////////////////////////////////
+
+JMediaSync::JMediaSync() {
+    mSync = MediaSync::create();
+}
+
+JMediaSync::~JMediaSync() {
+}
+
+status_t JMediaSync::configureSurface(const sp<IGraphicBufferProducer> &bufferProducer) {
+    return mSync->configureSurface(bufferProducer);
+}
+
+status_t JMediaSync::configureAudioTrack(
+        const sp<AudioTrack> &audioTrack,
+        int32_t nativeSampleRateInHz) {
+    return mSync->configureAudioTrack(audioTrack, nativeSampleRateInHz);
+}
+
+status_t JMediaSync::createInputSurface(
+        sp<IGraphicBufferProducer>* bufferProducer) {
+    return mSync->createInputSurface(bufferProducer);
+}
+
+void JMediaSync::setPlaybackRate(float rate) {
+    mSync->setPlaybackRate(rate);
+}
+
+status_t JMediaSync::updateQueuedAudioData(
+        int sizeInBytes, int64_t presentationTimeUs) {
+    return mSync->updateQueuedAudioData(sizeInBytes, presentationTimeUs);
+}
+
+}  // namespace android
+
+////////////////////////////////////////////////////////////////////////////////
+
+using namespace android;
+
+static sp<JMediaSync> setMediaSync(JNIEnv *env, jobject thiz, const sp<JMediaSync> &sync) {
+    sp<JMediaSync> old = (JMediaSync *)env->GetLongField(thiz, gFields.context);
+    if (sync != NULL) {
+        sync->incStrong(thiz);
+    }
+    if (old != NULL) {
+        old->decStrong(thiz);
+    }
+
+    env->SetLongField(thiz, gFields.context, (jlong)sync.get());
+
+    return old;
+}
+
+static sp<JMediaSync> getMediaSync(JNIEnv *env, jobject thiz) {
+    return (JMediaSync *)env->GetLongField(thiz, gFields.context);
+}
+
+static void android_media_MediaSync_release(JNIEnv *env, jobject thiz) {
+    setMediaSync(env, thiz, NULL);
+}
+
+static void throwExceptionAsNecessary(
+        JNIEnv *env, status_t err, const char *msg = NULL) {
+    switch (err) {
+        case INVALID_OPERATION:
+            jniThrowException(env, "java/lang/IllegalStateException", msg);
+            break;
+
+        case BAD_VALUE:
+            jniThrowException(env, "java/lang/IllegalArgumentException", msg);
+            break;
+
+        default:
+            break;
+    }
+}
+
+static void android_media_MediaSync_native_configureSurface(
+        JNIEnv *env, jobject thiz, jobject jsurface) {
+    ALOGV("android_media_MediaSync_configureSurface");
+
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return;
+    }
+
+    sp<IGraphicBufferProducer> bufferProducer;
+    if (jsurface != NULL) {
+        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
+        if (surface != NULL) {
+            bufferProducer = surface->getIGraphicBufferProducer();
+        } else {
+            throwExceptionAsNecessary(env, BAD_VALUE, "The surface has been released");
+            return;
+        }
+    }
+
+    status_t err = sync->configureSurface(bufferProducer);
+
+    if (err == INVALID_OPERATION) {
+        throwExceptionAsNecessary(
+                env, INVALID_OPERATION, "Surface has already been configured");
+    } if (err != NO_ERROR) {
+        AString msg("Failed to connect to surface with error ");
+        msg.append(err);
+        throwExceptionAsNecessary(env, BAD_VALUE, msg.c_str());
+    }
+}
+
+static void android_media_MediaSync_native_configureAudioTrack(
+        JNIEnv *env, jobject thiz, jobject jaudioTrack, jint nativeSampleRateInHz) {
+    ALOGV("android_media_MediaSync_configureAudioTrack");
+
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return;
+    }
+
+    sp<AudioTrack> audioTrack;
+    if (jaudioTrack != NULL) {
+        audioTrack = android_media_AudioTrack_getAudioTrack(env, jaudioTrack);
+        if (audioTrack == NULL) {
+            throwExceptionAsNecessary(env, BAD_VALUE, "The audio track has been released");
+            return;
+        }
+    }
+
+    status_t err = sync->configureAudioTrack(audioTrack, nativeSampleRateInHz);
+
+    if (err == INVALID_OPERATION) {
+        throwExceptionAsNecessary(
+                env, INVALID_OPERATION, "Audio track has already been configured");
+    } if (err != NO_ERROR) {
+        AString msg("Failed to configure audio track with error ");
+        msg.append(err);
+        throwExceptionAsNecessary(env, BAD_VALUE, msg.c_str());
+    }
+}
+
+static jobject android_media_MediaSync_createInputSurface(
+        JNIEnv* env, jobject thiz) {
+    ALOGV("android_media_MediaSync_createInputSurface");
+
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return NULL;
+    }
+
+    // Tell the MediaSync that we want to use a Surface as input.
+    sp<IGraphicBufferProducer> bufferProducer;
+    status_t err = sync->createInputSurface(&bufferProducer);
+    if (err != NO_ERROR) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return NULL;
+    }
+
+    // Wrap the IGBP in a Java-language Surface.
+    return android_view_Surface_createFromIGraphicBufferProducer(env,
+            bufferProducer);
+}
+
+static void android_media_MediaSync_native_updateQueuedAudioData(
+        JNIEnv *env, jobject thiz, jint sizeInBytes, jlong presentationTimeUs) {
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return;
+    }
+
+    status_t err = sync->updateQueuedAudioData(sizeInBytes, presentationTimeUs);
+    if (err != NO_ERROR) {
+        throwExceptionAsNecessary(env, err);
+        return;
+    }
+}
+
+static void android_media_MediaSync_native_init(JNIEnv *env) {
+    ScopedLocalRef<jclass> clazz(env, env->FindClass("android/media/MediaSync"));
+    CHECK(clazz.get() != NULL);
+
+    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
+    CHECK(gFields.context != NULL);
+}
+
+static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) {
+    sp<JMediaSync> sync = new JMediaSync();
+
+    setMediaSync(env, thiz, sync);
+}
+
+static void android_media_MediaSync_native_setPlaybackRate(
+        JNIEnv *env, jobject thiz, jfloat rate) {
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return;
+    }
+
+    sync->setPlaybackRate(rate);
+}
+
+static void android_media_MediaSync_native_finalize(JNIEnv *env, jobject thiz) {
+    android_media_MediaSync_release(env, thiz);
+}
+
+static JNINativeMethod gMethods[] = {
+    { "native_configureSurface",
+      "(Landroid/view/Surface;)V",
+      (void *)android_media_MediaSync_native_configureSurface },
+
+    { "native_configureAudioTrack",
+      "(Landroid/media/AudioTrack;I)V",
+      (void *)android_media_MediaSync_native_configureAudioTrack },
+
+    { "createInputSurface", "()Landroid/view/Surface;",
+      (void *)android_media_MediaSync_createInputSurface },
+
+    { "native_updateQueuedAudioData",
+      "(IJ)V",
+      (void *)android_media_MediaSync_native_updateQueuedAudioData },
+
+    { "native_init", "()V", (void *)android_media_MediaSync_native_init },
+
+    { "native_setup", "()V", (void *)android_media_MediaSync_native_setup },
+
+    { "native_release", "()V", (void *)android_media_MediaSync_release },
+
+    { "native_setPlaybackRate", "(F)V", (void *)android_media_MediaSync_native_setPlaybackRate },
+
+    { "native_finalize", "()V", (void *)android_media_MediaSync_native_finalize },
+};
+
+int register_android_media_MediaSync(JNIEnv *env) {
+    return AndroidRuntime::registerNativeMethods(
+                   env, "android/media/MediaSync", gMethods, NELEM(gMethods));
+}
diff --git a/media/jni/android_media_MediaSync.h b/media/jni/android_media_MediaSync.h
new file mode 100644
index 0000000..5750083
--- /dev/null
+++ b/media/jni/android_media_MediaSync.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef _ANDROID_MEDIA_MEDIASYNC_H_
+#define _ANDROID_MEDIA_MEDIASYNC_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class AudioTrack;
+struct IGraphicBufferProducer;
+class MediaSync;
+
+struct JMediaSync : public RefBase {
+    JMediaSync();
+
+    status_t configureSurface(const sp<IGraphicBufferProducer> &bufferProducer);
+    status_t configureAudioTrack(
+            const sp<AudioTrack> &audioTrack, int32_t nativeSampleRateInHz);
+
+    status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
+
+    status_t updateQueuedAudioData(int sizeInBytes, int64_t presentationTimeUs);
+
+    void setPlaybackRate(float rate);
+
+protected:
+    virtual ~JMediaSync();
+
+private:
+    sp<MediaSync> mSync;
+
+    DISALLOW_EVIL_CONSTRUCTORS(JMediaSync);
+};
+
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_MEDIASYNC_H_
diff --git a/media/jni/soundpool/Android.mk b/media/jni/soundpool/Android.mk
index 71ab013..2476056 100644
--- a/media/jni/soundpool/Android.mk
+++ b/media/jni/soundpool/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    android_media_SoundPool_SoundPoolImpl.cpp \
+    android_media_SoundPool.cpp \
     SoundPool.cpp \
     SoundPoolThread.cpp
 
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 10233f3..25c6154 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -716,7 +716,15 @@
         }
 #endif
 
-        if (!mAudioTrack.get() || mPrevSampleID != sample->sampleID()) {
+        // check if the existing track has the same sample id.
+        if (mAudioTrack != 0 && mPrevSampleID == sample->sampleID()) {
+            // the sample rate may fail to change if the audio track is a fast track.
+            if (mAudioTrack->setSampleRate(sampleRate) == NO_ERROR) {
+                newTrack = mAudioTrack;
+                ALOGV("reusing track %p for sample %d", mAudioTrack.get(), sample->sampleID());
+            }
+        }
+        if (newTrack == 0) {
             // mToggle toggles each time a track is started on a given channel.
             // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
             // as callback user data. This enables the detection of callbacks received from the old
@@ -746,10 +754,6 @@
             mToggle = toggle;
             mAudioTrack = newTrack;
             ALOGV("using new track %p for sample %d", newTrack.get(), sample->sampleID());
-        } else {
-            newTrack = mAudioTrack;
-            newTrack->setSampleRate(sampleRate);
-            ALOGV("reusing track %p for sample %d", mAudioTrack.get(), sample->sampleID());
         }
         newTrack->setVolume(leftVolume, rightVolume);
         newTrack->setLoop(0, frameCount, loop);
diff --git a/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
similarity index 74%
rename from media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp
rename to media/jni/soundpool/android_media_SoundPool.cpp
index b2333f8..fc4cf05 100644
--- a/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -47,10 +47,10 @@
 // ----------------------------------------------------------------------------
 
 static jint
-android_media_SoundPool_SoundPoolImpl_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
+android_media_SoundPool_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
         jlong offset, jlong length, jint priority)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_load_FD");
+    ALOGV("android_media_SoundPool_load_FD");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return 0;
     return (jint) ap->load(jniGetFDFromFileDescriptor(env, fileDescriptor),
@@ -58,104 +58,104 @@
 }
 
 static jboolean
-android_media_SoundPool_SoundPoolImpl_unload(JNIEnv *env, jobject thiz, jint sampleID) {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_unload\n");
+android_media_SoundPool_unload(JNIEnv *env, jobject thiz, jint sampleID) {
+    ALOGV("android_media_SoundPool_unload\n");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return JNI_FALSE;
     return ap->unload(sampleID) ? JNI_TRUE : JNI_FALSE;
 }
 
 static jint
-android_media_SoundPool_SoundPoolImpl_play(JNIEnv *env, jobject thiz, jint sampleID,
+android_media_SoundPool_play(JNIEnv *env, jobject thiz, jint sampleID,
         jfloat leftVolume, jfloat rightVolume, jint priority, jint loop,
         jfloat rate)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_play\n");
+    ALOGV("android_media_SoundPool_play\n");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return 0;
     return (jint) ap->play(sampleID, leftVolume, rightVolume, priority, loop, rate);
 }
 
 static void
-android_media_SoundPool_SoundPoolImpl_pause(JNIEnv *env, jobject thiz, jint channelID)
+android_media_SoundPool_pause(JNIEnv *env, jobject thiz, jint channelID)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_pause");
+    ALOGV("android_media_SoundPool_pause");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return;
     ap->pause(channelID);
 }
 
 static void
-android_media_SoundPool_SoundPoolImpl_resume(JNIEnv *env, jobject thiz, jint channelID)
+android_media_SoundPool_resume(JNIEnv *env, jobject thiz, jint channelID)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_resume");
+    ALOGV("android_media_SoundPool_resume");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return;
     ap->resume(channelID);
 }
 
 static void
-android_media_SoundPool_SoundPoolImpl_autoPause(JNIEnv *env, jobject thiz)
+android_media_SoundPool_autoPause(JNIEnv *env, jobject thiz)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_autoPause");
+    ALOGV("android_media_SoundPool_autoPause");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return;
     ap->autoPause();
 }
 
 static void
-android_media_SoundPool_SoundPoolImpl_autoResume(JNIEnv *env, jobject thiz)
+android_media_SoundPool_autoResume(JNIEnv *env, jobject thiz)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_autoResume");
+    ALOGV("android_media_SoundPool_autoResume");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return;
     ap->autoResume();
 }
 
 static void
-android_media_SoundPool_SoundPoolImpl_stop(JNIEnv *env, jobject thiz, jint channelID)
+android_media_SoundPool_stop(JNIEnv *env, jobject thiz, jint channelID)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_stop");
+    ALOGV("android_media_SoundPool_stop");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return;
     ap->stop(channelID);
 }
 
 static void
-android_media_SoundPool_SoundPoolImpl_setVolume(JNIEnv *env, jobject thiz, jint channelID,
+android_media_SoundPool_setVolume(JNIEnv *env, jobject thiz, jint channelID,
         jfloat leftVolume, jfloat rightVolume)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_setVolume");
+    ALOGV("android_media_SoundPool_setVolume");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return;
     ap->setVolume(channelID, (float) leftVolume, (float) rightVolume);
 }
 
 static void
-android_media_SoundPool_SoundPoolImpl_setPriority(JNIEnv *env, jobject thiz, jint channelID,
+android_media_SoundPool_setPriority(JNIEnv *env, jobject thiz, jint channelID,
         jint priority)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_setPriority");
+    ALOGV("android_media_SoundPool_setPriority");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return;
     ap->setPriority(channelID, (int) priority);
 }
 
 static void
-android_media_SoundPool_SoundPoolImpl_setLoop(JNIEnv *env, jobject thiz, jint channelID,
+android_media_SoundPool_setLoop(JNIEnv *env, jobject thiz, jint channelID,
         int loop)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_setLoop");
+    ALOGV("android_media_SoundPool_setLoop");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return;
     ap->setLoop(channelID, loop);
 }
 
 static void
-android_media_SoundPool_SoundPoolImpl_setRate(JNIEnv *env, jobject thiz, jint channelID,
+android_media_SoundPool_setRate(JNIEnv *env, jobject thiz, jint channelID,
        jfloat rate)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_setRate");
+    ALOGV("android_media_SoundPool_setRate");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return;
     ap->setRate(channelID, (float) rate);
@@ -169,7 +169,7 @@
 }
 
 static jint
-android_media_SoundPool_SoundPoolImpl_native_setup(JNIEnv *env, jobject thiz, jobject weakRef,
+android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz, jobject weakRef,
         jint maxChannels, jobject jaa)
 {
     if (jaa == 0) {
@@ -191,7 +191,7 @@
             (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
     paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
 
-    ALOGV("android_media_SoundPool_SoundPoolImpl_native_setup");
+    ALOGV("android_media_SoundPool_native_setup");
     SoundPool *ap = new SoundPool(maxChannels, paa);
     if (ap == NULL) {
         return -1;
@@ -211,9 +211,9 @@
 }
 
 static void
-android_media_SoundPool_SoundPoolImpl_release(JNIEnv *env, jobject thiz)
+android_media_SoundPool_release(JNIEnv *env, jobject thiz)
 {
-    ALOGV("android_media_SoundPool_SoundPoolImpl_release");
+    ALOGV("android_media_SoundPool_release");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap != NULL) {
 
@@ -236,63 +236,63 @@
 static JNINativeMethod gMethods[] = {
     {   "_load",
         "(Ljava/io/FileDescriptor;JJI)I",
-        (void *)android_media_SoundPool_SoundPoolImpl_load_FD
+        (void *)android_media_SoundPool_load_FD
     },
     {   "unload",
         "(I)Z",
-        (void *)android_media_SoundPool_SoundPoolImpl_unload
+        (void *)android_media_SoundPool_unload
     },
     {   "_play",
         "(IFFIIF)I",
-        (void *)android_media_SoundPool_SoundPoolImpl_play
+        (void *)android_media_SoundPool_play
     },
     {   "pause",
         "(I)V",
-        (void *)android_media_SoundPool_SoundPoolImpl_pause
+        (void *)android_media_SoundPool_pause
     },
     {   "resume",
         "(I)V",
-        (void *)android_media_SoundPool_SoundPoolImpl_resume
+        (void *)android_media_SoundPool_resume
     },
     {   "autoPause",
         "()V",
-        (void *)android_media_SoundPool_SoundPoolImpl_autoPause
+        (void *)android_media_SoundPool_autoPause
     },
     {   "autoResume",
         "()V",
-        (void *)android_media_SoundPool_SoundPoolImpl_autoResume
+        (void *)android_media_SoundPool_autoResume
     },
     {   "stop",
         "(I)V",
-        (void *)android_media_SoundPool_SoundPoolImpl_stop
+        (void *)android_media_SoundPool_stop
     },
     {   "_setVolume",
         "(IFF)V",
-        (void *)android_media_SoundPool_SoundPoolImpl_setVolume
+        (void *)android_media_SoundPool_setVolume
     },
     {   "setPriority",
         "(II)V",
-        (void *)android_media_SoundPool_SoundPoolImpl_setPriority
+        (void *)android_media_SoundPool_setPriority
     },
     {   "setLoop",
         "(II)V",
-        (void *)android_media_SoundPool_SoundPoolImpl_setLoop
+        (void *)android_media_SoundPool_setLoop
     },
     {   "setRate",
         "(IF)V",
-        (void *)android_media_SoundPool_SoundPoolImpl_setRate
+        (void *)android_media_SoundPool_setRate
     },
     {   "native_setup",
         "(Ljava/lang/Object;ILjava/lang/Object;)I",
-        (void*)android_media_SoundPool_SoundPoolImpl_native_setup
+        (void*)android_media_SoundPool_native_setup
     },
     {   "release",
         "()V",
-        (void*)android_media_SoundPool_SoundPoolImpl_release
+        (void*)android_media_SoundPool_release
     }
 };
 
-static const char* const kClassPathName = "android/media/SoundPool$SoundPoolImpl";
+static const char* const kClassPathName = "android/media/SoundPool";
 
 jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
 {
@@ -314,14 +314,14 @@
 
     fields.mNativeContext = env->GetFieldID(clazz, "mNativeContext", "J");
     if (fields.mNativeContext == NULL) {
-        ALOGE("Can't find SoundPoolImpl.mNativeContext");
+        ALOGE("Can't find SoundPool.mNativeContext");
         return result;
     }
 
     fields.mPostEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
                                                "(Ljava/lang/Object;IIILjava/lang/Object;)V");
     if (fields.mPostEvent == NULL) {
-        ALOGE("Can't find android/media/SoundPoolImpl.postEventFromNative");
+        ALOGE("Can't find android/media/SoundPool.postEventFromNative");
         return result;
     }
 
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index e95e5ec..a6f7a26 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -42,10 +42,21 @@
             </intent-filter>
         </activity>
 
+        <activity
+            android:name=".StandaloneActivity"
+            android:theme="@style/StandaloneTheme"
+            android:icon="@drawable/ic_doc_text"
+            android:enabled="false">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
         <provider
             android:name=".RecentsProvider"
             android:authorities="com.android.documentsui.recents"
-            android:exported="false" />
+            android:exported="false"/>
 
         <receiver android:name=".PackageReceiver">
             <intent-filter>
@@ -54,5 +65,10 @@
                 <data android:scheme="package" />
             </intent-filter>
         </receiver>
+
+        <service
+            android:name=".CopyService"
+            android:exported="false">
+        </service>
     </application>
 </manifest>
diff --git a/packages/DocumentsUI/res/menu/mode_directory.xml b/packages/DocumentsUI/res/menu/mode_directory.xml
index 0a3645f..4b89823 100644
--- a/packages/DocumentsUI/res/menu/mode_directory.xml
+++ b/packages/DocumentsUI/res/menu/mode_directory.xml
@@ -29,4 +29,12 @@
         android:icon="@drawable/ic_menu_delete"
         android:title="@string/menu_delete"
         android:showAsAction="always" />
+    <item
+        android:id="@+id/menu_select_all"
+        android:title="@string/menu_select_all"
+        android:showAsAction="never" />
+    <item
+        android:id="@+id/menu_copy"
+        android:title="@string/menu_copy"
+        android:showAsAction="never" />
 </menu>
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index 19fe7a7..549b661 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Deel"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Vee uit"</string>
     <string name="menu_select" msgid="8711270657353563424">"Kies \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Kies almal"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Wys interne berging"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Wys SD-kaart"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Versteek interne berging"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Kan lêer nie oopmaak nie"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Kan sommige dokumente nie uitvee nie"</string>
     <string name="share_via" msgid="8966594246261344259">"Deel via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Kanselleer"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index 419d162..3027400 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"አጋራ"</string>
     <string name="menu_delete" msgid="8138799623850614177">"ሰርዝ"</string>
     <string name="menu_select" msgid="8711270657353563424">"«<xliff:g id="DIRECTORY">^1</xliff:g>»ን ይምረጡ"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"ሁሉንም ምረጥ"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"ውስጣዊ ማከማቻ አሳይ"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD ካርድ አሳይ"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"ውስጣዊ ማከማቻ ደብቅ"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ፋይል መክፈት አይቻልም"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"አንዳንድ ሰነዶችን መሰረዝ አልተቻለም"</string>
     <string name="share_via" msgid="8966594246261344259">"በሚከተለው በኩል ያጋሩ"</string>
+    <string name="cancel" msgid="6442560571259935130">"ይቅር"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index 5bccdae..ea5a963 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"مشاركة"</string>
     <string name="menu_delete" msgid="8138799623850614177">"حذف"</string>
     <string name="menu_select" msgid="8711270657353563424">"تحديد \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"تحديد الكل"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"نسخ إلى…"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"إظهار وحدة التخزين الداخلية"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"‏إظهار بطاقة SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"إخفاء وحدة التخزين الداخلية"</string>
@@ -55,4 +57,15 @@
     <string name="toast_no_application" msgid="1339885974067891667">"لا يمكن فتح الملف"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"تعذر حذف بعض المستندات"</string>
     <string name="share_via" msgid="8966594246261344259">"مشاركة عبر"</string>
+    <string name="cancel" msgid="6442560571259935130">"إلغاء"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"جارٍ نسخ الملفات"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"المدة المتبقية: <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="zero">جارٍ نسخ <xliff:g id="COUNT_1">%1$d</xliff:g> ملفات.</item>
+      <item quantity="two">جارٍ نسخ ملفين (<xliff:g id="COUNT_1">%1$d</xliff:g>).</item>
+      <item quantity="few">جارٍ نسخ <xliff:g id="COUNT_1">%1$d</xliff:g> ملفات.</item>
+      <item quantity="many">جارٍ نسخ <xliff:g id="COUNT_1">%1$d</xliff:g> ملفًا.</item>
+      <item quantity="other">جارٍ نسخ <xliff:g id="COUNT_1">%1$d</xliff:g> من الملفات.</item>
+      <item quantity="one">جارٍ نسخ ملف واحد (<xliff:g id="COUNT_0">%1$d</xliff:g>).</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index 77f6855..a964253 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Споделяне"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Изтриване"</string>
     <string name="menu_select" msgid="8711270657353563424">"Избиране на „<xliff:g id="DIRECTORY">^1</xliff:g>“"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Избиране на всички"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Вътр. хранилище: Показв."</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD карта: Показване"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Вътр. хранилище: Скрив."</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Файлът не може да се отвори"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Някои документи не могат да бъдат изтрити"</string>
     <string name="share_via" msgid="8966594246261344259">"Споделяне чрез"</string>
+    <string name="cancel" msgid="6442560571259935130">"Отказ"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index 603cb96..1ee4289 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"ভাগ করুন"</string>
     <string name="menu_delete" msgid="8138799623850614177">"মুছুন"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" নির্বাচন করুন"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"সমস্ত নির্বাচন করুন"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"অভ্যন্তরীণ সঞ্চয়স্থান দেখান"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD কার্ড দেখান"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"অভ্যন্তরীণ সঞ্চয়স্থান লুকান"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ফাইল খোলা যাবে না"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"কিছু দস্তাবেজ মুছতে অসমর্থ"</string>
     <string name="share_via" msgid="8966594246261344259">"এর মাধ্যমে ভাগ করুন"</string>
+    <string name="cancel" msgid="6442560571259935130">"বাতিল করুন"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index d973650..c693c40 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Comparteix"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Suprimeix"</string>
     <string name="menu_select" msgid="8711270657353563424">"Selecciona \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Selecciona\'ls tots"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostra emmagatz. intern"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Mostra la targeta SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Amaga emmagatz. intern"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"No es pot obrir el fitxer."</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"No es poden suprimir alguns documents."</string>
     <string name="share_via" msgid="8966594246261344259">"Comparteix mitjançant"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancel·la"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index 36bb72f..5afba80 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Sdílet"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Smazat"</string>
     <string name="menu_select" msgid="8711270657353563424">"Vyberte adresář <xliff:g id="DIRECTORY">^1</xliff:g>"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Vybrat vše"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Zobrazit inter. úložiště"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Zobrazit SD kartu"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Skrýt interní úložiště"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Soubor nelze otevřít"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Některé dokumenty nelze smazat"</string>
     <string name="share_via" msgid="8966594246261344259">"Sdílet pomocí"</string>
+    <string name="cancel" msgid="6442560571259935130">"Zrušit"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index 5feb517..6aa40d03 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Del"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Slet"</string>
     <string name="menu_select" msgid="8711270657353563424">"Vælg \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Vælg alle"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Vis intern lagerplads"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Vis SD-kort"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Skjul intern lagerplads"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Filen kan ikke åbnes"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nogle dokumenter kan ikke slettes"</string>
     <string name="share_via" msgid="8966594246261344259">"Del via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Annuller"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index 598862b..8a95605 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Teilen"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Löschen"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" auswählen"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Alle auswählen"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Int. Speicher anzeigen"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD-Karte anzeigen"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Int. Speicher ausblenden"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Datei kann nicht geöffnet werden."</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Einige Dokumente konnten nicht gelöscht werden."</string>
     <string name="share_via" msgid="8966594246261344259">"Teilen über"</string>
+    <string name="cancel" msgid="6442560571259935130">"Abbrechen"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index 37f99cf..1158c87 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Κοινή χρήση"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Διαγραφή"</string>
     <string name="menu_select" msgid="8711270657353563424">"Επιλογή \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Επιλογή όλων"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Εμφ.εσωτ.χώρου αποθήκ."</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Εμφάνιση κάρτας SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Απόκρ.εσωτ.χώρου αποθήκ."</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Δεν είναι δυνατό το άνοιγμα του αρχείου"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Δεν είναι δυνατή η διαγραφή ορισμένων εγγράφων"</string>
     <string name="share_via" msgid="8966594246261344259">"Κοινή χρήση μέσω"</string>
+    <string name="cancel" msgid="6442560571259935130">"Ακύρωση"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml
index 2bd5615..7e720a1 100644
--- a/packages/DocumentsUI/res/values-en-rAU/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"Share"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Delete"</string>
     <string name="menu_select" msgid="8711270657353563424">"Select \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Select All"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"Copy to…"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Show internal storage"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Show SD card"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Hide internal storage"</string>
@@ -55,4 +57,11 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Cannot open file"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Unable to delete some documents"</string>
     <string name="share_via" msgid="8966594246261344259">"Share via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"Copying files"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
+      <item quantity="one">Copying <xliff:g id="COUNT_0">%1$d</xliff:g> file.</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index 2bd5615..7e720a1 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"Share"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Delete"</string>
     <string name="menu_select" msgid="8711270657353563424">"Select \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Select All"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"Copy to…"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Show internal storage"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Show SD card"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Hide internal storage"</string>
@@ -55,4 +57,11 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Cannot open file"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Unable to delete some documents"</string>
     <string name="share_via" msgid="8966594246261344259">"Share via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"Copying files"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
+      <item quantity="one">Copying <xliff:g id="COUNT_0">%1$d</xliff:g> file.</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index 2bd5615..7e720a1 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"Share"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Delete"</string>
     <string name="menu_select" msgid="8711270657353563424">"Select \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Select All"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"Copy to…"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Show internal storage"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Show SD card"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Hide internal storage"</string>
@@ -55,4 +57,11 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Cannot open file"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Unable to delete some documents"</string>
     <string name="share_via" msgid="8966594246261344259">"Share via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"Copying files"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> left"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="other">Copying <xliff:g id="COUNT_1">%1$d</xliff:g> files.</item>
+      <item quantity="one">Copying <xliff:g id="COUNT_0">%1$d</xliff:g> file.</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index 4a47b73..7ad3fab7 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Compartir"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Eliminar"</string>
     <string name="menu_select" msgid="8711270657353563424">"Seleccionar \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Seleccionar todos"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar almacen. interno"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Mostrar tarjeta SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ocultar almacen. interno"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"No se puede abrir el archivo."</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"No es posible eliminar algunos documentos."</string>
     <string name="share_via" msgid="8966594246261344259">"Compartir mediante"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 95cc812..5380be3 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Compartir"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Eliminar"</string>
     <string name="menu_select" msgid="8711270657353563424">"Selecciona \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Seleccionar todo"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar almac. interno"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Mostrar tarjeta SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ocultar almac. interno"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Error al abrir el archivo"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"No es posible eliminar algunos documentos"</string>
     <string name="share_via" msgid="8966594246261344259">"Compartir a través de"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index c98f0b9..a030ef0 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Jaga"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Kustuta"</string>
     <string name="menu_select" msgid="8711270657353563424">"Kataloogi „<xliff:g id="DIRECTORY">^1</xliff:g>” valimine"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Vali kõik"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Kuva sis. salvestusruum"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Kuva SD-kaart"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Peida sis. salvestusruum"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Faili ei saa avada"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Mõnda dokumenti ei õnnestu kustutada"</string>
     <string name="share_via" msgid="8966594246261344259">"Jagage teenusega"</string>
+    <string name="cancel" msgid="6442560571259935130">"Tühista"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index 1fd7b1d..ce9d974 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Partekatu"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Ezabatu"</string>
     <string name="menu_select" msgid="8711270657353563424">"Hautatu \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Hautatu guztiak"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Erakutsi barneko memoria"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Erakutsi SD txartela"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ezkutatu barneko memoria"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Ezin da fitxategia ireki"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Ezin izan dira dokumentu batzuk ezabatu"</string>
     <string name="share_via" msgid="8966594246261344259">"Partekatu honen bidez:"</string>
+    <string name="cancel" msgid="6442560571259935130">"Utzi"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index 6c57211..4b641ab 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"اشتراک‌گذاری"</string>
     <string name="menu_delete" msgid="8138799623850614177">"حذف"</string>
     <string name="menu_select" msgid="8711270657353563424">"انتخاب «<xliff:g id="DIRECTORY">^1</xliff:g>»"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"انتخاب همه"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"نمایش فضای ذخیره‌سازی داخلی"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"‏نمایش کارت SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"پنهان کردن فضای ذخیره‌سازی داخلی"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"فایل باز نمی‌شود"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"برخی از اسناد حذف نمی‌شوند"</string>
     <string name="share_via" msgid="8966594246261344259">"اشتراک‌گذاری از طریق"</string>
+    <string name="cancel" msgid="6442560571259935130">"لغو"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 185be47..243db28 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Jaa"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Poista"</string>
     <string name="menu_select" msgid="8711270657353563424">"Valitse <xliff:g id="DIRECTORY">^1</xliff:g>"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Valitse kaikki"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Näytä sis. tallennustila"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Näytä SD-kortti"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Piilota sis. tallennust."</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Tiedostoa ei voi avata"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Joitakin asiakirjoja ei voi poistaa"</string>
     <string name="share_via" msgid="8966594246261344259">"Jaa sovelluksessa"</string>
+    <string name="cancel" msgid="6442560571259935130">"Peruuta"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index 4e4c0ed..250115b 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Partager"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Supprimer"</string>
     <string name="menu_select" msgid="8711270657353563424">"Sélectionner « <xliff:g id="DIRECTORY">^1</xliff:g> »"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Tout sélectionner"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Aff. mém. stock. interne"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Afficher la carte SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Masquer mém. stock. int."</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Impossible d\'ouvrir le fichier"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Impossible de supprimer certains documents"</string>
     <string name="share_via" msgid="8966594246261344259">"Partager par"</string>
+    <string name="cancel" msgid="6442560571259935130">"Annuler"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index b760caa..d340b4b 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Partager"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Supprimer"</string>
     <string name="menu_select" msgid="8711270657353563424">"Sélectionner \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Tout sélectionner"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Aff. mém. stock. interne"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Afficher la carte SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Masquer mém. stock. int."</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Impossible d\'ouvrir le fichier."</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Impossible de supprimer certains documents."</string>
     <string name="share_via" msgid="8966594246261344259">"Partager via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Annuler"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index bc6ee9e..6812145 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Compartir"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Eliminar"</string>
     <string name="menu_select" msgid="8711270657353563424">"Selecciona \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Seleccionar todos"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar almacen. interno"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Mostrar tarxeta SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ocultar almacen. interno"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Non se pode abrir o ficheiro"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Non se poden eliminar algúns documentos"</string>
     <string name="share_via" msgid="8966594246261344259">"Compartir a través de"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index 88f26ed..725e3f2 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"साझा करें"</string>
     <string name="menu_delete" msgid="8138799623850614177">"हटाएं"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" चुनें"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"सभी चुनें"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"आंतरिक मेमोरी दिखाएं"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD कार्ड दिखाएं"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"आंतरिक मेमोरी छिपाएं"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"फ़ाइल नहीं खोली जा सकती"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"कुछ दस्तावेज़ों को हटाने में अक्षम"</string>
     <string name="share_via" msgid="8966594246261344259">"इसके द्वारा साझा करें"</string>
+    <string name="cancel" msgid="6442560571259935130">"अभी नहीं"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index 60343d2..548c5bc 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Dijeli"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Izbriši"</string>
     <string name="menu_select" msgid="8711270657353563424">"Odaberi \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Odaberi sve"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Pokaži internu pohranu"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Pokaži SD karticu"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Sakrij internu pohranu"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Datoteku nije moguće otvoriti"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nije moguće izbrisati neke dokumente"</string>
     <string name="share_via" msgid="8966594246261344259">"Dijeli putem"</string>
+    <string name="cancel" msgid="6442560571259935130">"Odustani"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index a9b5a7c..9d3ae4b 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Megosztás"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Törlés"</string>
     <string name="menu_select" msgid="8711270657353563424">"A(z) „<xliff:g id="DIRECTORY">^1</xliff:g>” mappa kiválasztása"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Az összes kijelölése"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Belső tárhely"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD-kártya megjelenítése"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Belső tárhely elrejtése"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"A fájlt nem lehet megnyitni"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Néhány dokumentumot nem lehet törölni"</string>
     <string name="share_via" msgid="8966594246261344259">"Megosztás itt:"</string>
+    <string name="cancel" msgid="6442560571259935130">"Mégse"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index 487f5bd..afcc177 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Համօգտագործել"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Ջնջել"</string>
     <string name="menu_select" msgid="8711270657353563424">"Ընտրել «<xliff:g id="DIRECTORY">^1</xliff:g>»"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Ընտրել բոլորը"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Ցույց տալ ներքին պահոցը"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Ցույց տալ SD քարտը"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Թաքցնել ներքին պահոցը"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Հնարավոր չէ բացել ֆայլը"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Անհնար է ջնջել որոշ փաստաթղթեր"</string>
     <string name="share_via" msgid="8966594246261344259">"Տարածել"</string>
+    <string name="cancel" msgid="6442560571259935130">"Չեղարկել"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index 1514fc6..8384b62 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"Bagikan"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Hapus"</string>
     <string name="menu_select" msgid="8711270657353563424">"Pilih \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Pilih Semua"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"Salin ke…"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Tampilkan simpanan internal"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Tampilkan kartu SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Sembunyikan simpanan internal"</string>
@@ -55,4 +57,11 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Tidak dapat membuka file"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Tidak dapat menghapus beberapa dokumen"</string>
     <string name="share_via" msgid="8966594246261344259">"Bagikan melalui"</string>
+    <string name="cancel" msgid="6442560571259935130">"Batal"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"Menyalin file"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> lagi"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="other">Menyalin <xliff:g id="COUNT_1">%1$d</xliff:g> file.</item>
+      <item quantity="one">Menyalin <xliff:g id="COUNT_0">%1$d</xliff:g> file.</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index f324dad..a8dde93 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Deila"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Eyða"</string>
     <string name="menu_select" msgid="8711270657353563424">"Velja „<xliff:g id="DIRECTORY">^1</xliff:g>“"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Velja allt"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Sýna innbyggða geymslu"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Sýna SD-kort"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Fela innbyggða geymslu"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Ekki er hægt að opna skrána"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Ekki er hægt að eyða einhverjum skjölum"</string>
     <string name="share_via" msgid="8966594246261344259">"Deila í gegnum"</string>
+    <string name="cancel" msgid="6442560571259935130">"Hætta við"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index a073c44..59b9a94 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Condividi"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Elimina"</string>
     <string name="menu_select" msgid="8711270657353563424">"Seleziona \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Seleziona tutti"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostra memoria interna"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Mostra scheda SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Nascondi memoria interna"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Impossibile aprire il file"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Impossibile eliminare alcuni documenti"</string>
     <string name="share_via" msgid="8966594246261344259">"Condividi via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Annulla"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index 6ab2880..ed387be 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"שתף"</string>
     <string name="menu_delete" msgid="8138799623850614177">"מחק"</string>
     <string name="menu_select" msgid="8711270657353563424">"בחר ב-\"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"בחר הכל"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"העתק אל…"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"הצג אחסון פנימי"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"‏הצג כרטיס SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"הסתר אחסון פנימי"</string>
@@ -55,4 +57,13 @@
     <string name="toast_no_application" msgid="1339885974067891667">"לא ניתן לפתוח את הקובץ"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"לא ניתן למחוק חלק מהמסמכים"</string>
     <string name="share_via" msgid="8966594246261344259">"שתף באמצעות"</string>
+    <string name="cancel" msgid="6442560571259935130">"ביטול"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"מעתיק קבצים"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"זמן נותר: <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="two">מעתיק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים.</item>
+      <item quantity="many">מעתיק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים.</item>
+      <item quantity="other">מעתיק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים.</item>
+      <item quantity="one">מעתיק קובץ <xliff:g id="COUNT_0">%1$d</xliff:g>.</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index f57a21c..21911cc 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"共有"</string>
     <string name="menu_delete" msgid="8138799623850614177">"削除"</string>
     <string name="menu_select" msgid="8711270657353563424">"「<xliff:g id="DIRECTORY">^1</xliff:g>」を選択"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"すべて選択"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"内部ストレージを表示"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SDカードを表示"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"内部ストレージを非表示"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ファイルを開けません"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"一部のドキュメントを削除できません"</string>
     <string name="share_via" msgid="8966594246261344259">"共有ツール"</string>
+    <string name="cancel" msgid="6442560571259935130">"キャンセル"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index b1e39b8..b8f6b8f 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"გაზიარება"</string>
     <string name="menu_delete" msgid="8138799623850614177">"წაშლა"</string>
     <string name="menu_select" msgid="8711270657353563424">"„<xliff:g id="DIRECTORY">^1</xliff:g>“-ის არჩევა"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"ყველას არჩევა"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"შიდა საცავის ჩვენება"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD ბარათის ჩვენება"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"შიდა მეხსიერების დამალვა"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ფაილის გახსნა ვერ ხერხდება"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"ზოგიერთი დოკუმენტის წაშლა ვერ ხერხდება"</string>
     <string name="share_via" msgid="8966594246261344259">"გაზიარება:"</string>
+    <string name="cancel" msgid="6442560571259935130">"გაუქმება"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index c7e207c..75000f4 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Бөлісу"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Жою"</string>
     <string name="menu_select" msgid="8711270657353563424">"«<xliff:g id="DIRECTORY">^1</xliff:g>» таңдау"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Барлығын таңдау"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Ішкі жадты көрсету"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD картасын көрсету"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ішкі жадты жасыру"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Файлды аша алмады"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Кейбір құжаттарды жою мүмкін болмады"</string>
     <string name="share_via" msgid="8966594246261344259">"арқылы бөлісу"</string>
+    <string name="cancel" msgid="6442560571259935130">"Бас тарту"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index 3055001..fa4a24a 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក​"</string>
     <string name="menu_delete" msgid="8138799623850614177">"លុប"</string>
     <string name="menu_select" msgid="8711270657353563424">"ជ្រើស \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"ជ្រើសរើសទាំងអស់"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"បង្ហាញឧបករណ៍ផ្ទុកខាងក្នុង"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"បង្ហាញកាតអេសឌី"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"លាក់​ឧបករណ៍​​ផ្ទុក​ខាងក្នុង"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"មិន​អាច​បើក​ឯកសារ"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"មិន​អាច​លុប​ឯកសារ​មួយ​ចំនួន"</string>
     <string name="share_via" msgid="8966594246261344259">"ចែករំលែក​តាម"</string>
+    <string name="cancel" msgid="6442560571259935130">"បោះ​បង់​"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
index 508f0e5..edec1da 100644
--- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"ಹಂಚು"</string>
     <string name="menu_delete" msgid="8138799623850614177">"ಅಳಿಸು"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"ಎಲ್ಲವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"ಆಂತರಿಕ ಸಂಗ್ರಹಣೆಯನ್ನು ತೋರಿಸು"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD ಕಾಡ್‌ ಅನ್ನು ತೋರಿಸು"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"ಆಂತರಿಕ ಸಂಗ್ರಹಣೆಯನ್ನು ಮರೆಮಾಡಿ"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ಫೈಲ್ ತೆರೆಯಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"ಕೆಲವು ಡಾಕ್ಯುಮೆಂಟ್‌ಗಳನ್ನು ಅಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
     <string name="share_via" msgid="8966594246261344259">"ಈ ಮೂಲಕ ಹಂಚಿಕೊಳ್ಳಿ"</string>
+    <string name="cancel" msgid="6442560571259935130">"ರದ್ದುಮಾಡು"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index d6f0cbd..c9f6680 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"공유"</string>
     <string name="menu_delete" msgid="8138799623850614177">"삭제"</string>
     <string name="menu_select" msgid="8711270657353563424">"\'<xliff:g id="DIRECTORY">^1</xliff:g>\' 선택"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"모두 선택"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"내부 저장소 표시"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD 카드 표시"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"내부 저장소 숨기기"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"파일을 열 수 없음"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"일부 문서를 삭제할 수 없음"</string>
     <string name="share_via" msgid="8966594246261344259">"공유 방법"</string>
+    <string name="cancel" msgid="6442560571259935130">"취소"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index a4f718b..b77f59b 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Бөлүшүү"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Өчүрүү"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" тандоо"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Бардыгын тандоо"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Ички сактагычты көрсөтүү"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD картаны көрсөтүү"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ички эстутумду жашыруу"</string>
@@ -55,4 +58,11 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Файл ачылбады"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Кээ бир документтерди өчүрүү кыйрады"</string>
     <string name="share_via" msgid="8966594246261344259">"Кийинки аркылуу бөлүшүү:"</string>
+    <!-- no translation found for cancel (6442560571259935130) -->
+    <skip />
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index 8db69c7..3feb613 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"ແບ່ງປັນ"</string>
     <string name="menu_delete" msgid="8138799623850614177">"ລຶບ"</string>
     <string name="menu_select" msgid="8711270657353563424">"ເລືອກ​ \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"ເລືອກທັງຫມົດ"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"ອັດ​ສຳ​ເນົາ​ໃສ່…"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"ສະແດງ​ໂຕເກັບ​ຂໍ້ມູນພາຍໃນ"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"ສະແດງ SD Card"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"ເຊື່ອງ​ໂຕ​ເກັບຂໍ້ມູນ​ພາຍໃນ"</string>
@@ -55,4 +57,11 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ບໍ່ສາມດາເປີດໄຟລ໌ໄດ້"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"ບໍ່ສາມາດລຶບບາງເອກະສານໄດ້"</string>
     <string name="share_via" msgid="8966594246261344259">"ແບ່ງປັນຜ່ານ"</string>
+    <string name="cancel" msgid="6442560571259935130">"ຍົກເລີກ"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"ກຳ​ລັງ​ອັດ​ສຳ​ເນົາ​ໄຟ​ລ໌"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ຍັງ​ເຫຼືອ​ຢູ່"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="other">ກຳ​ລັງ​ອັດ​ສຳ​ເນົາ <xliff:g id="COUNT_1">%1$d</xliff:g> ໄຟ​ລ໌.</item>
+      <item quantity="one">ກຳ​ລັງ​ອັດ​ສຳ​ເນົາ <xliff:g id="COUNT_0">%1$d</xliff:g> ໄຟ​ລ໌.</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 81412c5..ee29e35 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Bendrinti"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Ištrinti"</string>
     <string name="menu_select" msgid="8711270657353563424">"Pasirinkti katalogą „<xliff:g id="DIRECTORY">^1</xliff:g>“"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Pasirinkti viską"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Rodyti vidinę atmintį"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Rodyti SD kortelę"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Slėpti vidinę atmintį"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Nepavyksta atidaryti failo"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nepavyko ištrinti kai kurių dokumentų"</string>
     <string name="share_via" msgid="8966594246261344259">"Bendrinti naudojant"</string>
+    <string name="cancel" msgid="6442560571259935130">"Atšaukti"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index 0cd5812..e1112c2 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Kopīgot"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Dzēst"</string>
     <string name="menu_select" msgid="8711270657353563424">"Atlasīt “<xliff:g id="DIRECTORY">^1</xliff:g>”"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Atlasīt visus"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Rādīt iekšējo atmiņu"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Rādīt SD karti"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Paslēpt iekšējo atmiņu"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Nevar atvērt failu."</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nevar dzēst dažus dokumentus."</string>
     <string name="share_via" msgid="8966594246261344259">"Kopīgot, izmantojot"</string>
+    <string name="cancel" msgid="6442560571259935130">"Atcelt"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index d909741..f9ab373 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Сподели"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Избриши"</string>
     <string name="menu_select" msgid="8711270657353563424">"Одберете „<xliff:g id="DIRECTORY">^1</xliff:g>“"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Избери ги сите"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Прикажи внатрешна мемор."</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Прикажи СД-картичка"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Скриј внатрешна меморија"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Датотеката не се отвора"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Некои документи не може да се избришат"</string>
     <string name="share_via" msgid="8966594246261344259">"Сподели преку"</string>
+    <string name="cancel" msgid="6442560571259935130">"Откажи"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
index 24f4815..43889da 100644
--- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"പങ്കിടുക"</string>
     <string name="menu_delete" msgid="8138799623850614177">"ഇല്ലാതാക്കുക"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" തിരഞ്ഞെടുക്കുക"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"എല്ലാം തിരഞ്ഞെടുക്കുക"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"ആന്തരിക സംഭരണം കാണിക്കുക"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD കാർഡ് കാണിക്കുക"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"ആന്തരിക സംഭരണം മറയ്‌ക്കുക"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ഫയൽ തുറക്കാനായില്ല"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"ചില പ്രമാണങ്ങൾ ഇല്ലാതാക്കാനായില്ല"</string>
     <string name="share_via" msgid="8966594246261344259">"ഇതുവഴി പങ്കിടുക"</string>
+    <string name="cancel" msgid="6442560571259935130">"റദ്ദാക്കുക"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index 141032d..64cc200 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Хуваалцах"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Устгах"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\"-г сонгох"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Бүгдийг сонгох"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Дотоод санг харуулах"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD картыг харуулах"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Дотоод санг нуух"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Файлыг нээх боломжгүй"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Зарим документуудыг устгах боломжгүй"</string>
     <string name="share_via" msgid="8966594246261344259">"Дараахаар дамжуулан хуваалцах"</string>
+    <string name="cancel" msgid="6442560571259935130">"Цуцлах"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index b59ded5..28d29ad 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"सामायिक करा"</string>
     <string name="menu_delete" msgid="8138799623850614177">"हटवा"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" निवडा"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"सर्व निवडा"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"अंतर्गत संचयन दर्शवा"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD कार्ड दर्शवा"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"अंतर्गत संचयन लपवा"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"फाईल उघडू शकत नाही"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"काही दस्‍तऐवज हटविण्‍यात अक्षम"</string>
     <string name="share_via" msgid="8966594246261344259">"द्वारे सामायिक करा"</string>
+    <string name="cancel" msgid="6442560571259935130">"रद्द करा"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index 5330d92..dff0b3b 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Kongsi"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Padam"</string>
     <string name="menu_select" msgid="8711270657353563424">"Pilih \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Pilih Semua"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Papar storan dalaman"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Papar kad SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Sembunyikan storan dlmn"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Tidak dapat membuka fail"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Tidak dapat memadam beberapa dokumen"</string>
     <string name="share_via" msgid="8966594246261344259">"Kongsi melalui"</string>
+    <string name="cancel" msgid="6442560571259935130">"Batal"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml
index 50f8363..6258d10 100644
--- a/packages/DocumentsUI/res/values-my-rMM/strings.xml
+++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"မျှဝေခြင်း"</string>
     <string name="menu_delete" msgid="8138799623850614177">"ဖျက်ပစ်ရန်"</string>
     <string name="menu_select" msgid="8711270657353563424">"ရွေးရန်\"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"အားလုံးရွေးရန်"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"သို့ကူးယူရန်…"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"စက်ရှိစတိုရုံ ပြပါ"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD ကဒ် ပြပါ"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"စက်ရှိစတိုရုံ ဖျောက်ထားပါ"</string>
@@ -55,4 +57,8 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ဖိုင်အား ဖွင့်မရပါ"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"တချို့ စာရွက်စာတန်းများ မဖျက်စီးနိုင်ပါ"</string>
     <string name="share_via" msgid="8966594246261344259">"မှ ဝေမျှပါ"</string>
+    <string name="cancel" msgid="6442560571259935130">"ထားတော့"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"ဖိုင်များကူယူနေသည်"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ကျန်ရှိသည်"</string>
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index beee44f..d4a4717 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Del"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Slett"</string>
     <string name="menu_select" msgid="8711270657353563424">"Velg «<xliff:g id="DIRECTORY">^1</xliff:g>»"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Velg alle"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Vis den interne lagringen"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Vis SD-kortet"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Skjul den interne lagringen"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Kan ikke åpne filen"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Enkelte dokumenter kunne ikke slettes"</string>
     <string name="share_via" msgid="8966594246261344259">"Del via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Avbryt"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
index 4251a7c..af7c1d9 100644
--- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml
+++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"साझेदारी गर्नुहोस्"</string>
     <string name="menu_delete" msgid="8138799623850614177">"मेटाउनुहोस्"</string>
     <string name="menu_select" msgid="8711270657353563424">"चयनगर्नुहोस् \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"सबै चयन गर्नुहोस्"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"आन्तरिक भण्डारण देखाउनुहोस्"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD कार्ड देखाउनुहोस्"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"आन्तरिक भण्डारण लुकाउनुहोस्"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"फाइल खोल्न सक्दैन"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"केही कागजातहरू मेट्न असमर्थ छ"</string>
     <string name="share_via" msgid="8966594246261344259">"माध्यमबाट साझेदारी गर्नुहोस्"</string>
+    <string name="cancel" msgid="6442560571259935130">"रद्द गर्नुहोस्"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index 1fc7dc1..977e5f7 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Delen"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Verwijderen"</string>
     <string name="menu_select" msgid="8711270657353563424">"<xliff:g id="DIRECTORY">^1</xliff:g> selecteren"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Alles selecteren"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Interne opslag weergeven"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD-kaart weergeven"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Interne opslag verbergen"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Kan bestand niet openen"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Kan bepaalde documenten niet verwijderen"</string>
     <string name="share_via" msgid="8966594246261344259">"Delen via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Annuleren"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 5bb7f75..fdb63c6 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Udostępnij"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Usuń"</string>
     <string name="menu_select" msgid="8711270657353563424">"Zaznacz „<xliff:g id="DIRECTORY">^1</xliff:g>”"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Wybierz wszystko"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Pokaż pamięć wewnętrzną"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Pokaż kartę SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ukryj pamięć wewnętrzną"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Nie można otworzyć pliku"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nie można usunąć niektórych dokumentów"</string>
     <string name="share_via" msgid="8966594246261344259">"Udostępnij przez"</string>
+    <string name="cancel" msgid="6442560571259935130">"Anuluj"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index e32dfc9..c36582a 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Partilhar"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Eliminar"</string>
     <string name="menu_select" msgid="8711270657353563424">"Selecionar \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Selecionar tudo"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar mem. armaz. int."</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Mostrar cartão SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ocultar mem. armaz. int."</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Não é possível abrir o ficheiro"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Não é possível eliminar alguns documentos"</string>
     <string name="share_via" msgid="8966594246261344259">"Partilhar através de"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index 2aaa4d2..fcb08a9 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Compartilhar"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Excluir"</string>
     <string name="menu_select" msgid="8711270657353563424">"Selecionar \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Selecionar tudo"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar armaz. interno"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Mostrar cartão SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ocultar armaz. interno"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Não é possível abrir o arquivo"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Não foi possível excluir alguns documentos"</string>
     <string name="share_via" msgid="8966594246261344259">"Compartilhar via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index c5de856..9a5e7bf 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Distribuiți"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Ștergeți"</string>
     <string name="menu_select" msgid="8711270657353563424">"Selectați „<xliff:g id="DIRECTORY">^1</xliff:g>”"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Selectați-le pe toate"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Afișați stocarea internă"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Afișați cardul SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ascundeți stocarea internă"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Fișierul nu poate fi deschis"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Unele documente nu au putut fi șterse"</string>
     <string name="share_via" msgid="8966594246261344259">"Distribuiți prin"</string>
+    <string name="cancel" msgid="6442560571259935130">"Anulați"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index 10de6f0..7bb29a1 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Поделиться"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Удалить"</string>
     <string name="menu_select" msgid="8711270657353563424">"Выбрать папку \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Выбрать все"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Внутренняя память"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD-карта"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Скрыть внутреннюю память"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Не удалось открыть файл"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Не удалось удалить некоторые документы"</string>
     <string name="share_via" msgid="8966594246261344259">"Поделиться"</string>
+    <string name="cancel" msgid="6442560571259935130">"Отмена"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml
index 26e2b1d..b32ba79 100644
--- a/packages/DocumentsUI/res/values-si-rLK/strings.xml
+++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"බෙදාගන්න"</string>
     <string name="menu_delete" msgid="8138799623850614177">"මකන්න"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" තෝරන්න"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"සියල්ල තෝරන්න"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"වෙත පිටපත් කරන්න..."</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"අභ්‍යන්තර ආචයනය පෙන්වන්න"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD කාඩ් පත පෙන්වන්න"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"අභ්‍යන්තර ආචයනය සඟවන්න"</string>
@@ -55,4 +57,11 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ගොනුව විවෘත කළ නොහැක"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"සමහර ලේඛන මැකීමට නොහැකි විය"</string>
     <string name="share_via" msgid="8966594246261344259">"හරහා බෙදාගන්න"</string>
+    <string name="cancel" msgid="6442560571259935130">"අවලංගු කරන්න"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"ගොනු පිටපත් කරමින්"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g>DURATION ඉතිරියි"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="one">ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g> ක් පිටපත් කරමින්.</item>
+      <item quantity="other">ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g> ක් පිටපත් කරමින්.</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index facaf4a..557f8db 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"Zdieľať"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Odstrániť"</string>
     <string name="menu_select" msgid="8711270657353563424">"Vyberte adresár <xliff:g id="DIRECTORY">^1</xliff:g>"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Vybrať všetko"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"Kopírovať do…"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Zobraziť interné úložisko"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Zobraziť kartu SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Skryť interné úložisko"</string>
@@ -55,4 +57,13 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Súbor sa nepodarilo otvoriť"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Niektoré dokumenty sa nepodarilo odstrániť"</string>
     <string name="share_via" msgid="8966594246261344259">"Zdieľať pomocou"</string>
+    <string name="cancel" msgid="6442560571259935130">"Zrušiť"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"Kopírovanie súborov"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"Zostáva: <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="few">Kopírujú sa <xliff:g id="COUNT_1">%1$d</xliff:g> súbory.</item>
+      <item quantity="many">Kopíruje sa <xliff:g id="COUNT_1">%1$d</xliff:g> súboru.</item>
+      <item quantity="other">Kopíruje sa <xliff:g id="COUNT_1">%1$d</xliff:g> súborov.</item>
+      <item quantity="one">Kopíruje sa <xliff:g id="COUNT_0">%1$d</xliff:g> súbor.</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index 865df8b..90f912c 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Skupna raba"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Izbriši"</string>
     <string name="menu_select" msgid="8711270657353563424">"Izbira mape »<xliff:g id="DIRECTORY">^1</xliff:g>«"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Izberi vse"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Pokaži notranjo shrambo"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Pokaži kartico SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Skrij notranjo shrambo"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Datoteke ni mogoče odpreti"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nekaterih dokumentov ni mogoče izbrisati"</string>
     <string name="share_via" msgid="8966594246261344259">"Deli z drugimi prek"</string>
+    <string name="cancel" msgid="6442560571259935130">"Prekliči"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index fd20722..af491e0 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Дели"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Избриши"</string>
     <string name="menu_select" msgid="8711270657353563424">"Изабери „<xliff:g id="DIRECTORY">^1</xliff:g>“"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Изабери све"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Прикажи интерну меморију"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Прикажи SD картицу"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Сакриј интерну меморију"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Није могуће отворити датотеку"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Није могуће избрисати неке документе"</string>
     <string name="share_via" msgid="8966594246261344259">"Делите преко"</string>
+    <string name="cancel" msgid="6442560571259935130">"Откажи"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index a77b75d..cce77d4 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Dela"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Ta bort"</string>
     <string name="menu_select" msgid="8711270657353563424">"Välj <xliff:g id="DIRECTORY">^1</xliff:g>"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Markera alla"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Visa internminne"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Visa SD-kort"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Dölj internminne"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Det går inte att öppna filen"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Det gick inte att ta bort vissa dokument"</string>
     <string name="share_via" msgid="8966594246261344259">"Dela via"</string>
+    <string name="cancel" msgid="6442560571259935130">"Avbryt"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index b46d97f..d062c7a 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"Shiriki"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Futa"</string>
     <string name="menu_select" msgid="8711270657353563424">"Chagua \" <xliff:g id="DIRECTORY">^1</xliff:g> \""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Chagua Zote"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"Nakili kwenda..."</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Onyesha hifadhi ya ndani"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Onyesha kadi ya SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ficha hifadhi ya ndani"</string>
@@ -55,4 +57,11 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Haiwezi kufungua faili"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Imeshindwa kufuta baadhi ya hati"</string>
     <string name="share_via" msgid="8966594246261344259">"Shiriki kupitia"</string>
+    <string name="cancel" msgid="6442560571259935130">"Ghairi"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"Inanakili faili"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"Zimesalia <xliff:g id="DURATION">%s</xliff:g>"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="other">Inanakili faili <xliff:g id="COUNT_1">%1$d</xliff:g>.</item>
+      <item quantity="one">Inanakili faili <xliff:g id="COUNT_0">%1$d</xliff:g>.</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 5b09b97..8c73f5f 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"பகிர்"</string>
     <string name="menu_delete" msgid="8138799623850614177">"நீக்கு"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" ஐத் தேர்ந்தெடு"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"எல்லாவற்றையும் தேர்ந்தெடு"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"அகச் சேமிப்பகத்தைக் காட்டு"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD கார்டைக் காட்டு"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"அகச் சேமிப்பகத்தை மறை"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"கோப்பைத் திறக்க முடியவில்லை"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"சில ஆவணங்களை நீக்க முடியவில்லை"</string>
     <string name="share_via" msgid="8966594246261344259">"இதன் வழியாகப் பகிர்"</string>
+    <string name="cancel" msgid="6442560571259935130">"ரத்துசெய்"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml
index e04724a..01684f3 100644
--- a/packages/DocumentsUI/res/values-te-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"భాగస్వామ్యం చేయి"</string>
     <string name="menu_delete" msgid="8138799623850614177">"తొలగించు"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\"ని ఎంచుకోండి"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"అన్నీ ఎంచుకోండి"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"అంతర్గత నిల్వను చూపు"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD కార్డ్‌ను చూపు"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"అంతర్గత నిల్వను దాచు"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ఫైల్‌ను తెరవడం సాధ్యపడదు"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"కొన్ని పత్రాలను తొలగించడం సాధ్యపడలేదు"</string>
     <string name="share_via" msgid="8966594246261344259">"దీని ద్వారా భాగస్వామ్యం చేయండి"</string>
+    <string name="cancel" msgid="6442560571259935130">"రద్దు చేయండి"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index 5410d37..0de0ef1 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"แชร์"</string>
     <string name="menu_delete" msgid="8138799623850614177">"ลบ"</string>
     <string name="menu_select" msgid="8711270657353563424">"เลือก \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"เลือกทั้งหมด"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"แสดงที่จัดเก็บภายใน"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"แสดงการ์ด SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"ซ่อนที่จัดเก็บภายใน"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"ไม่สามารถเปิดไฟล์ได้"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"ไม่สามารถลบเอกสารบางรายการ"</string>
     <string name="share_via" msgid="8966594246261344259">"แชร์ผ่าน"</string>
+    <string name="cancel" msgid="6442560571259935130">"ยกเลิก"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index 3defd6a..d838a28 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Ibahagi"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Tanggalin"</string>
     <string name="menu_select" msgid="8711270657353563424">"Piliin ang \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Piliin Lahat"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Ipakita internal storage"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Ipakita ang SD card"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Itago internal storage"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Hindi mabuksan ang file"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Hindi matanggal ang ilang dokumento"</string>
     <string name="share_via" msgid="8966594246261344259">"Ibahagi sa pamamagitan ng"</string>
+    <string name="cancel" msgid="6442560571259935130">"Kanselahin"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index 9f0f846..01e73b4 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Paylaş"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Sil"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" dizinini seç"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Tümünü Seç"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Dahili depolamayı göster"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD kartı göster"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Dahili depolamayı gizle"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Dosya açılamıyor"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Bazı dokümanlar silinemiyor"</string>
     <string name="share_via" msgid="8966594246261344259">"Şunu kullanarak paylaş:"</string>
+    <string name="cancel" msgid="6442560571259935130">"İptal"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index 5be1947..acee983 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Поділитися"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Видалити"</string>
     <string name="menu_select" msgid="8711270657353563424">"Вибрати каталог \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Вибрати все"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Показати внутр. пам’ять"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Показати карту SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Сховати внутр. пам’ять"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Не вдалося відкрити файл"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Не вдалося видалити деякі документи"</string>
     <string name="share_via" msgid="8966594246261344259">"Надіслати через"</string>
+    <string name="cancel" msgid="6442560571259935130">"Скасувати"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index 729fc7f..9b5597f 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"اشتراک کریں"</string>
     <string name="menu_delete" msgid="8138799623850614177">"حذف کریں"</string>
     <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" منتخب کریں"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"سبھی منتخب کریں"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"داخلی اسٹوریج دکھائیں"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"‏SD کارڈ دکھائیں"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"داخلی اسٹوریج چھپائیں"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"فائل نہيں کھول سکتے ہیں"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"کچھ دستاویزات کو حذف کرنے سے قاصر"</string>
     <string name="share_via" msgid="8966594246261344259">"اشتراک کریں بذریعہ"</string>
+    <string name="cancel" msgid="6442560571259935130">"منسوخ کریں"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index db35356..76c590a 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"Ulashish"</string>
     <string name="menu_delete" msgid="8138799623850614177">"O‘chirish"</string>
     <string name="menu_select" msgid="8711270657353563424">"“<xliff:g id="DIRECTORY">^1</xliff:g>” jildini tanlash"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Barchasini tanlash"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"...ga nusxalash"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Ichki xotirani ko‘rsatish"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"SD kartani ko‘rsatish"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ichki xotirani berkitish"</string>
@@ -55,4 +57,11 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Fayl ochilmadi"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Ba’zi hujjatlar o‘chirilmadi"</string>
     <string name="share_via" msgid="8966594246261344259">"Quyidagi orqali ulashish"</string>
+    <string name="cancel" msgid="6442560571259935130">"Bekor qilish"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"Fayllar nusxalanmoqda"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> qoldi"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ta fayl nusxalanmoqda</item>
+      <item quantity="one"> <xliff:g id="COUNT_0">%1$d</xliff:g> ta fayl nusxalanmoqda</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index e4bbfda..417346a 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"Chia sẻ"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Xóa"</string>
     <string name="menu_select" msgid="8711270657353563424">"Chọn \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Chọn tất cả"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Hiển thị bộ nhớ trong"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Hiển thị thẻ SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Ẩn bộ nhớ trong"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Không thể mở tệp"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Không thể xóa một số tài liệu"</string>
     <string name="share_via" msgid="8966594246261344259">"Chia sẻ qua"</string>
+    <string name="cancel" msgid="6442560571259935130">"Hủy"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index 4a44250..bacf261 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"分享"</string>
     <string name="menu_delete" msgid="8138799623850614177">"删除"</string>
     <string name="menu_select" msgid="8711270657353563424">"选择“<xliff:g id="DIRECTORY">^1</xliff:g>”"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"全选"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"显示内部存储设备"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"显示SD卡"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"隐藏内部存储设备"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"无法打开文件"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"无法删除部分文档"</string>
     <string name="share_via" msgid="8966594246261344259">"分享方式"</string>
+    <string name="cancel" msgid="6442560571259935130">"取消"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index e245c12..027a31a 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"分享"</string>
     <string name="menu_delete" msgid="8138799623850614177">"刪除"</string>
     <string name="menu_select" msgid="8711270657353563424">"選取「<xliff:g id="DIRECTORY">^1</xliff:g>」"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"全部選取"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"顯示內部儲存空間"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"顯示 SD 卡"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"隱藏內部儲存空間"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"無法開啟檔案"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"無法刪除部分文件"</string>
     <string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
+    <string name="cancel" msgid="6442560571259935130">"取消"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index 464a13e..92ad91e 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -30,6 +30,9 @@
     <string name="menu_share" msgid="3075149983979628146">"共用"</string>
     <string name="menu_delete" msgid="8138799623850614177">"刪除"</string>
     <string name="menu_select" msgid="8711270657353563424">"選取「<xliff:g id="DIRECTORY">^1</xliff:g>」"</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"全選"</string>
+    <!-- no translation found for menu_copy (3612326052677229148) -->
+    <skip />
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"顯示內部儲存空間"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"顯示 SD 卡"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"隱藏內部儲存空間"</string>
@@ -55,4 +58,10 @@
     <string name="toast_no_application" msgid="1339885974067891667">"無法開啟檔案"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"無法刪除部分文件"</string>
     <string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
+    <string name="cancel" msgid="6442560571259935130">"取消"</string>
+    <!-- no translation found for copy_notification_title (6374299806748219777) -->
+    <skip />
+    <!-- no translation found for copy_remaining (6283790937387975095) -->
+    <skip />
+    <!-- no translation found for copy_begin (9071199452634086365) -->
 </resources>
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index b35da3c..dd37993 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -30,6 +30,8 @@
     <string name="menu_share" msgid="3075149983979628146">"Yabelana"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Susa"</string>
     <string name="menu_select" msgid="8711270657353563424">"Khetha i-\"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
+    <string name="menu_select_all" msgid="4320518282375109902">"Khetha konke"</string>
+    <string name="menu_copy" msgid="3612326052677229148">"Kopishela ku…"</string>
     <string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Bonisa isitoreji sangaphakathi"</string>
     <string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Bonisa ikhadi le-SD"</string>
     <string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Fihla isitoreji sangaphakathi"</string>
@@ -55,4 +57,11 @@
     <string name="toast_no_application" msgid="1339885974067891667">"Ayikwazi ukuvula ifayela"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Ayikwazi ukususa amanye amadokhumenti"</string>
     <string name="share_via" msgid="8966594246261344259">"Yabelana nge-"</string>
+    <string name="cancel" msgid="6442560571259935130">"Khansela"</string>
+    <string name="copy_notification_title" msgid="6374299806748219777">"Ikopisha amafayela"</string>
+    <string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> okusele"</string>
+    <plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
+      <item quantity="one">Ikopisha amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>.</item>
+      <item quantity="other">Ikopisha amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>.</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 268ce18..310ccf0 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -46,6 +46,10 @@
     <string name="menu_delete">Delete</string>
     <!-- Menu item title that selects the current directory [CHAR LIMIT=48] -->
     <string name="menu_select">Select \"<xliff:g id="directory" example="My Directory">^1</xliff:g>\"</string>
+    <!-- Menu item title that selects all documents in the current directory [CHAR LIMIT=24] -->
+    <string name="menu_select_all">Select All</string>
+    <!-- Menu item title that copies the selected documents [CHAR LIMIT=24] -->
+    <string name="menu_copy">Copy to\u2026</string>
 
     <!-- Menu item that reveals internal storage built into the device [CHAR LIMIT=24] -->
     <string name="menu_advanced_show" product="nosdcard">Show internal storage</string>
@@ -108,4 +112,16 @@
     <!-- Title of dialog when prompting user to select an app to share documents with [CHAR LIMIT=32] -->
     <string name="share_via">Share via</string>
 
+    <!-- Title of the cancel button [CHAR LIMIT=24] -->
+    <string name="cancel">Cancel</string>
+    <!-- Title of the copy notification [CHAR LIMIT=24] -->
+    <string name="copy_notification_title">Copying files</string>
+    <!-- Text shown on the copy notification to indicate remaining time, in minutes [CHAR LIMIT=24] -->
+    <string name="copy_remaining"><xliff:g id="duration" example="3 minutes">%s</xliff:g> left</string>
+    <!-- Toast shown when a file copy is kicked off -->
+    <plurals name="copy_begin">
+      <item quantity="one">Copying <xliff:g id="count" example="1">%1$d</xliff:g> file.</item>
+      <item quantity="other">Copying <xliff:g id="count" example="3">%1$d</xliff:g> files.</item>
+    </plurals>
+
 </resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 04692f6..bf01bf1 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -43,4 +43,22 @@
         <item name="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
     </style>
 
+    <style name="StandaloneTheme" parent="android:Theme.Light">
+        <item name="android:actionBarWidgetTheme">@null</item>
+        <item name="android:actionBarTheme">@*android:style/ThemeOverlay.Material.Dark.ActionBar</item>
+        <item name="android:actionBarPopupTheme">@*android:style/ThemeOverlay.Material.Light</item>
+
+        <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_900</item>
+        <item name="android:colorPrimary">@*android:color/material_blue_grey_800</item>
+        <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
+
+        <item name="android:listDivider">@*android:drawable/list_divider_material</item>
+
+        <item name="android:windowActionBar">false</item>
+        <item name="android:windowActionModeOverlay">true</item>
+        <item name="android:windowNoTitle">true</item>
+
+        <item name="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
+    </style>
+
 </resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
new file mode 100644
index 0000000..a8a0c1d
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import java.util.HashMap;
+import java.util.List;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.pm.ResolveInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.SparseArray;
+
+import com.android.documentsui.model.DocumentInfo;
+import com.android.documentsui.model.DocumentStack;
+import com.android.documentsui.model.DurableUtils;
+import com.android.documentsui.model.RootInfo;
+import com.google.common.collect.Maps;
+
+abstract class BaseActivity extends Activity {
+
+    public abstract State getDisplayState();
+    public abstract RootInfo getCurrentRoot();
+    public abstract void onStateChanged();
+    public abstract void setRootsDrawerOpen(boolean open);
+    public abstract void onDocumentPicked(DocumentInfo doc);
+    public abstract void onDocumentsPicked(List<DocumentInfo> docs);
+    public abstract DocumentInfo getCurrentDirectory();
+    public abstract void setPending(boolean pending);
+    public abstract void onStackPicked(DocumentStack stack);
+    public abstract void onPickRequested(DocumentInfo pickTarget);
+    public abstract void onAppPicked(ResolveInfo info);
+    public abstract void onRootPicked(RootInfo root, boolean closeDrawer);
+    public abstract void onSaveRequested(DocumentInfo replaceTarget);
+    public abstract void onSaveRequested(String mimeType, String displayName);
+
+    public static BaseActivity get(Fragment fragment) {
+        return (BaseActivity) fragment.getActivity();
+    }
+
+    public static class State implements android.os.Parcelable {
+        public int action;
+        public String[] acceptMimes;
+
+        /** Explicit user choice */
+        public int userMode = MODE_UNKNOWN;
+        /** Derived after loader */
+        public int derivedMode = MODE_LIST;
+
+        /** Explicit user choice */
+        public int userSortOrder = SORT_ORDER_UNKNOWN;
+        /** Derived after loader */
+        public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
+
+        public boolean allowMultiple = false;
+        public boolean showSize = false;
+        public boolean localOnly = false;
+        public boolean forceAdvanced = false;
+        public boolean showAdvanced = false;
+        public boolean stackTouched = false;
+        public boolean restored = false;
+
+        /** Current user navigation stack; empty implies recents. */
+        public DocumentStack stack = new DocumentStack();
+        /** Currently active search, overriding any stack. */
+        public String currentSearch;
+
+        /** Instance state for every shown directory */
+        public HashMap<String, SparseArray<Parcelable>> dirState = Maps.newHashMap();
+
+        public static final int ACTION_OPEN = 1;
+        public static final int ACTION_CREATE = 2;
+        public static final int ACTION_GET_CONTENT = 3;
+        public static final int ACTION_OPEN_TREE = 4;
+        public static final int ACTION_MANAGE = 5;
+        public static final int ACTION_MANAGE_ALL = 6;
+
+        public static final int MODE_UNKNOWN = 0;
+        public static final int MODE_LIST = 1;
+        public static final int MODE_GRID = 2;
+
+        public static final int SORT_ORDER_UNKNOWN = 0;
+        public static final int SORT_ORDER_DISPLAY_NAME = 1;
+        public static final int SORT_ORDER_LAST_MODIFIED = 2;
+        public static final int SORT_ORDER_SIZE = 3;
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeInt(action);
+            out.writeInt(userMode);
+            out.writeStringArray(acceptMimes);
+            out.writeInt(userSortOrder);
+            out.writeInt(allowMultiple ? 1 : 0);
+            out.writeInt(showSize ? 1 : 0);
+            out.writeInt(localOnly ? 1 : 0);
+            out.writeInt(forceAdvanced ? 1 : 0);
+            out.writeInt(showAdvanced ? 1 : 0);
+            out.writeInt(stackTouched ? 1 : 0);
+            out.writeInt(restored ? 1 : 0);
+            DurableUtils.writeToParcel(out, stack);
+            out.writeString(currentSearch);
+            out.writeMap(dirState);
+        }
+
+        public static final Creator<State> CREATOR = new Creator<State>() {
+            @Override
+            public State createFromParcel(Parcel in) {
+                final State state = new State();
+                state.action = in.readInt();
+                state.userMode = in.readInt();
+                state.acceptMimes = in.readStringArray();
+                state.userSortOrder = in.readInt();
+                state.allowMultiple = in.readInt() != 0;
+                state.showSize = in.readInt() != 0;
+                state.localOnly = in.readInt() != 0;
+                state.forceAdvanced = in.readInt() != 0;
+                state.showAdvanced = in.readInt() != 0;
+                state.stackTouched = in.readInt() != 0;
+                state.restored = in.readInt() != 0;
+                DurableUtils.readFromParcel(in, state.stack);
+                state.currentSearch = in.readString();
+                in.readMap(state.dirState, null);
+                return state;
+            }
+
+            @Override
+            public State[] newArray(int size) {
+                return new State[size];
+            }
+        };
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
new file mode 100644
index 0000000..f7d8cc4
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.app.IntentService;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.text.format.DateUtils;
+import android.util.Log;
+
+import com.android.documentsui.model.DocumentInfo;
+
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+
+public class CopyService extends IntentService {
+    public static final String TAG = "CopyService";
+    public static final String EXTRA_SRC_LIST = "com.android.documentsui.SRC_LIST";
+    private static final String EXTRA_CANCEL = "com.android.documentsui.CANCEL";
+
+    private NotificationManager mNotificationManager;
+    private Notification.Builder mProgressBuilder;
+
+    // Jobs are serialized but a job ID is used, to avoid mixing up cancellation requests.
+    private String mJobId;
+    private volatile boolean mIsCancelled;
+    // Parameters of the copy job. Requests to an IntentService are serialized so this code only
+    // needs to deal with one job at a time.
+    private long mBatchSize;
+    private long mBytesCopied;
+    private long mStartTime;
+    private long mLastNotificationTime;
+    // Speed estimation
+    private long mBytesCopiedSample;
+    private long mSampleTime;
+    private long mSpeed;
+    private long mRemainingTime;
+
+    public CopyService() {
+        super("CopyService");
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (intent.hasExtra(EXTRA_CANCEL)) {
+            handleCancel(intent);
+        }
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    @Override
+    protected void onHandleIntent(Intent intent) {
+        if (intent.hasExtra(EXTRA_CANCEL)) {
+            handleCancel(intent);
+            return;
+        }
+
+        ArrayList<DocumentInfo> srcs = intent.getParcelableArrayListExtra(EXTRA_SRC_LIST);
+        // Use the app local files dir as a copy destination for now. This resolves to
+        // /data/data/com.android.documentsui/files.
+        // TODO: Add actual destination picking.
+        File destinationDir = getFilesDir();
+
+        setupCopyJob(srcs, destinationDir);
+
+        ArrayList<String> failedFilenames = new ArrayList<String>();
+        for (int i = 0; i < srcs.size() && !mIsCancelled; ++i) {
+            DocumentInfo src = srcs.get(i);
+            try {
+                copyFile(src, destinationDir);
+            } catch (IOException e) {
+                Log.e(TAG, "Failed to copy " + src.displayName, e);
+                failedFilenames.add(src.displayName);
+            }
+        }
+
+        if (failedFilenames.size() > 0) {
+            // TODO: Display a notification when an error has occurred.
+        }
+
+        // Dismiss the ongoing copy notification when the copy is done.
+        mNotificationManager.cancel(mJobId, 0);
+
+        // TODO: Display a toast if the copy was cancelled.
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+    }
+
+    /**
+     * Sets up the CopyService to start tracking and sending notifications for the given batch of
+     * files.
+     *
+     * @param srcs A list of src files to copy.
+     */
+    private void setupCopyJob(ArrayList<DocumentInfo> srcs, File destinationDir) {
+        // Create an ID for this copy job. Use the timestamp.
+        mJobId = String.valueOf(SystemClock.elapsedRealtime());
+        // Reset the cancellation flag.
+        mIsCancelled = false;
+
+        mProgressBuilder = new Notification.Builder(this)
+                .setContentTitle(getString(R.string.copy_notification_title))
+                .setCategory(Notification.CATEGORY_PROGRESS)
+                .setSmallIcon(R.drawable.ic_menu_copy).setOngoing(true);
+
+        Intent cancelIntent = new Intent(this, CopyService.class);
+        cancelIntent.putExtra(EXTRA_CANCEL, mJobId);
+        mProgressBuilder.addAction(R.drawable.ic_cab_cancel,
+                getString(R.string.cancel), PendingIntent.getService(this, 0,
+                        cancelIntent, PendingIntent.FLAG_ONE_SHOT));
+
+        // TODO: Add a content intent to open the destination folder.
+
+        // Send an initial progress notification.
+        mNotificationManager.notify(mJobId, 0, mProgressBuilder.build());
+
+        // Reset batch parameters.
+        mBatchSize = 0;
+        for (DocumentInfo doc : srcs) {
+            mBatchSize += doc.size;
+        }
+        mBytesCopied = 0;
+        mStartTime = SystemClock.elapsedRealtime();
+        mLastNotificationTime = 0;
+        mBytesCopiedSample = 0;
+        mSampleTime = 0;
+        mSpeed = 0;
+        mRemainingTime = 0;
+
+        // TODO: Check preconditions for copy.
+        // - check that the destination has enough space and is writeable?
+        // - check MIME types?
+    }
+
+    /**
+     * Cancels the current copy job, if its ID matches the given ID.
+     *
+     * @param intent The cancellation intent.
+     */
+    private void handleCancel(Intent intent) {
+        final String cancelledId = intent.getStringExtra(EXTRA_CANCEL);
+        // Do nothing if the cancelled ID doesn't match the current job ID. This prevents racey
+        // cancellation requests from affecting unrelated copy jobs.
+        if (java.util.Objects.equals(mJobId, cancelledId)) {
+            // Set the cancel flag. This causes the copy loops to exit.
+            mIsCancelled = true;
+            // Dismiss the progress notification here rather than in the copy loop. This preserves
+            // interactivity for the user in case the copy loop is stalled.
+            mNotificationManager.cancel(mJobId, 0);
+        }
+    }
+
+    /**
+     * Logs progress on the current copy operation. Displays/Updates the progress notification.
+     *
+     * @param bytesCopied
+     */
+    private void makeProgress(long bytesCopied) {
+        mBytesCopied += bytesCopied;
+        double done = (double) mBytesCopied / mBatchSize;
+        String percent = NumberFormat.getPercentInstance().format(done);
+
+        // Update time estimate
+        long currentTime = SystemClock.elapsedRealtime();
+        long elapsedTime = currentTime - mStartTime;
+
+        // Send out progress notifications once a second.
+        if (currentTime - mLastNotificationTime > 1000) {
+            updateRemainingTimeEstimate(elapsedTime);
+            mProgressBuilder.setProgress(100, (int) (done * 100), false);
+            mProgressBuilder.setContentInfo(percent);
+            if (mRemainingTime > 0) {
+                mProgressBuilder.setContentText(getString(R.string.copy_remaining,
+                        DateUtils.formatDuration(mRemainingTime)));
+            } else {
+                mProgressBuilder.setContentText(null);
+            }
+            mNotificationManager.notify(mJobId, 0, mProgressBuilder.build());
+            mLastNotificationTime = currentTime;
+        }
+    }
+
+    /**
+     * Generates an estimate of the remaining time in the copy.
+     *
+     * @param elapsedTime The time elapsed so far.
+     */
+    private void updateRemainingTimeEstimate(long elapsedTime) {
+        final long sampleDuration = elapsedTime - mSampleTime;
+        final long sampleSpeed = ((mBytesCopied - mBytesCopiedSample) * 1000) / sampleDuration;
+        if (mSpeed == 0) {
+            mSpeed = sampleSpeed;
+        } else {
+            mSpeed = ((3 * mSpeed) + sampleSpeed) / 4;
+        }
+
+        if (mSampleTime > 0 && mSpeed > 0) {
+            mRemainingTime = ((mBatchSize - mBytesCopied) * 1000) / mSpeed;
+        } else {
+            mRemainingTime = 0;
+        }
+
+        mSampleTime = elapsedTime;
+        mBytesCopiedSample = mBytesCopied;
+    }
+
+    /**
+     * Copies a file to a given location.
+     *
+     * @param srcInfo The source file.
+     * @param destination The directory to copy into.
+     * @throws IOException
+     */
+    private void copyFile(DocumentInfo srcInfo, File destinationDir)
+            throws IOException {
+        final Context context = getApplicationContext();
+        final ContentResolver resolver = context.getContentResolver();
+        final File destinationFile = new File(destinationDir, srcInfo.displayName);
+        final Uri destinationUri = Uri.fromFile(destinationFile);
+
+        InputStream source = null;
+        OutputStream destination = null;
+
+        boolean errorOccurred = false;
+        try {
+            source = resolver.openInputStream(srcInfo.derivedUri);
+            destination = resolver.openOutputStream(destinationUri);
+
+            byte[] buffer = new byte[8192];
+            int len;
+            while (!mIsCancelled && ((len = source.read(buffer)) != -1)) {
+                destination.write(buffer, 0, len);
+                makeProgress(len);
+            }
+        } catch (IOException e) {
+            errorOccurred = true;
+            Log.e(TAG, "Error while copying " + srcInfo.displayName, e);
+        } finally {
+            IoUtils.closeQuietly(source);
+            IoUtils.closeQuietly(destination);
+        }
+
+        if (errorOccurred || mIsCancelled) {
+            // Clean up half-copied files.
+            if (!destinationFile.delete()) {
+                Log.w(TAG, "Failed to clean up partially copied file " + srcInfo.displayName);
+            }
+        }
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index ba8c35f..1a17ee0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -70,7 +70,7 @@
             public void onClick(DialogInterface dialog, int which) {
                 final String displayName = text1.getText().toString();
 
-                final DocumentsActivity activity = (DocumentsActivity) getActivity();
+                final BaseActivity activity = (BaseActivity) getActivity();
                 final DocumentInfo cwd = activity.getCurrentDirectory();
 
                 new CreateDirectoryTask(activity, cwd, displayName).executeOnExecutor(
@@ -83,12 +83,12 @@
     }
 
     private class CreateDirectoryTask extends AsyncTask<Void, Void, DocumentInfo> {
-        private final DocumentsActivity mActivity;
+        private final BaseActivity mActivity;
         private final DocumentInfo mCwd;
         private final String mDisplayName;
 
         public CreateDirectoryTask(
-                DocumentsActivity activity, DocumentInfo cwd, String displayName) {
+                BaseActivity activity, DocumentInfo cwd, String displayName) {
             mActivity = activity;
             mCwd = cwd;
             mDisplayName = displayName;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 39c2252..d6d691f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -17,12 +17,12 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.DocumentsActivity.TAG;
-import static com.android.documentsui.DocumentsActivity.State.ACTION_CREATE;
-import static com.android.documentsui.DocumentsActivity.State.ACTION_MANAGE;
-import static com.android.documentsui.DocumentsActivity.State.MODE_GRID;
-import static com.android.documentsui.DocumentsActivity.State.MODE_LIST;
-import static com.android.documentsui.DocumentsActivity.State.MODE_UNKNOWN;
-import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_UNKNOWN;
+import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
+import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
+import static com.android.documentsui.BaseActivity.State.MODE_GRID;
+import static com.android.documentsui.BaseActivity.State.MODE_LIST;
+import static com.android.documentsui.BaseActivity.State.MODE_UNKNOWN;
+import static com.android.documentsui.BaseActivity.State.SORT_ORDER_UNKNOWN;
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
@@ -50,6 +50,7 @@
 import android.os.CancellationSignal;
 import android.os.OperationCanceledException;
 import android.os.Parcelable;
+import android.os.SystemProperties;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.text.format.DateUtils;
@@ -76,7 +77,8 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.BaseActivity.State;
+import com.android.documentsui.CopyService;
 import com.android.documentsui.ProviderExecutor.Preemptable;
 import com.android.documentsui.RecentsProvider.StateColumns;
 import com.android.documentsui.model.DocumentInfo;
@@ -301,13 +303,13 @@
                     state.derivedMode = result.mode;
                 }
                 state.derivedSortOrder = result.sortOrder;
-                ((DocumentsActivity) context).onStateChanged();
+                ((BaseActivity) context).onStateChanged();
 
                 updateDisplayState();
 
                 // When launched into empty recents, show drawer
                 if (mType == TYPE_RECENT_OPEN && mAdapter.isEmpty() && !state.stackTouched) {
-                    ((DocumentsActivity) context).setRootsDrawerOpen(true);
+                    ((BaseActivity) context).setRootsDrawerOpen(true);
                 }
 
                 // Restore any previous instance state
@@ -386,7 +388,7 @@
         // Mode change is just visual change; no need to kick loader, and
         // deliver change event immediately.
         state.derivedMode = state.userMode;
-        ((DocumentsActivity) getActivity()).onStateChanged();
+        ((BaseActivity) getActivity()).onStateChanged();
 
         updateDisplayState();
     }
@@ -441,7 +443,7 @@
                 final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
                 if (isDocumentEnabled(docMimeType, docFlags)) {
                     final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
-                    ((DocumentsActivity) getActivity()).onDocumentPicked(doc);
+                    ((BaseActivity) getActivity()).onDocumentPicked(doc);
                 }
             }
         }
@@ -463,11 +465,14 @@
             final MenuItem open = menu.findItem(R.id.menu_open);
             final MenuItem share = menu.findItem(R.id.menu_share);
             final MenuItem delete = menu.findItem(R.id.menu_delete);
+            final MenuItem copy = menu.findItem(R.id.menu_copy);
 
             final boolean manageMode = state.action == ACTION_MANAGE;
             open.setVisible(!manageMode);
             share.setVisible(manageMode);
             delete.setVisible(manageMode);
+            // Hide the copy feature by default.
+            copy.setVisible(SystemProperties.getBoolean("debug.documentsui.enable_copy", false));
 
             return true;
         }
@@ -487,7 +492,7 @@
 
             final int id = item.getItemId();
             if (id == R.id.menu_open) {
-                DocumentsActivity.get(DirectoryFragment.this).onDocumentsPicked(docs);
+                BaseActivity.get(DirectoryFragment.this).onDocumentsPicked(docs);
                 mode.finish();
                 return true;
 
@@ -501,6 +506,19 @@
                 mode.finish();
                 return true;
 
+            } else if (id == R.id.menu_copy) {
+                onCopyDocuments(docs);
+                mode.finish();
+                return true;
+
+            } else if (id == R.id.menu_select_all) {
+                int count = mCurrentView.getCount();
+                for (int i = 0; i < count; i++) {
+                    mCurrentView.setItemChecked(i, true);
+                }
+                updateDisplayState();
+                return true;
+
             } else {
                 return false;
             }
@@ -615,8 +633,22 @@
         }
     }
 
+    private void onCopyDocuments(List<DocumentInfo> docs) {
+        final Context context = getActivity();
+        final Resources res = context.getResources();
+
+        Intent copyIntent = new Intent(context, CopyService.class);
+        copyIntent.putParcelableArrayListExtra(CopyService.EXTRA_SRC_LIST,
+                new ArrayList<DocumentInfo>(docs));
+
+        Toast.makeText(context,
+                res.getQuantityString(R.plurals.copy_begin, docs.size(), docs.size()),
+                Toast.LENGTH_SHORT).show();
+        context.startService(copyIntent);
+    }
+
     private static State getDisplayState(Fragment fragment) {
-        return ((DocumentsActivity) fragment.getActivity()).getDisplayState();
+        return ((BaseActivity) fragment.getActivity()).getDisplayState();
     }
 
     private static abstract class Footer {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 163615d..8e4ec8c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -17,11 +17,11 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.DocumentsActivity.TAG;
-import static com.android.documentsui.DocumentsActivity.State.MODE_UNKNOWN;
-import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_DISPLAY_NAME;
-import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_LAST_MODIFIED;
-import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_SIZE;
-import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_UNKNOWN;
+import static com.android.documentsui.BaseActivity.State.MODE_UNKNOWN;
+import static com.android.documentsui.BaseActivity.State.SORT_ORDER_DISPLAY_NAME;
+import static com.android.documentsui.BaseActivity.State.SORT_ORDER_LAST_MODIFIED;
+import static com.android.documentsui.BaseActivity.State.SORT_ORDER_SIZE;
+import static com.android.documentsui.BaseActivity.State.SORT_ORDER_UNKNOWN;
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 
 import android.content.AsyncTaskLoader;
@@ -36,7 +36,7 @@
 import android.provider.DocumentsContract.Document;
 import android.util.Log;
 
-import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.RecentsProvider.StateColumns;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.RootInfo;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 8778f11..2245b16 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -20,14 +20,13 @@
 import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
 import static com.android.documentsui.DirectoryFragment.ANIM_SIDE;
 import static com.android.documentsui.DirectoryFragment.ANIM_UP;
-import static com.android.documentsui.DocumentsActivity.State.ACTION_CREATE;
-import static com.android.documentsui.DocumentsActivity.State.ACTION_GET_CONTENT;
-import static com.android.documentsui.DocumentsActivity.State.ACTION_MANAGE;
-import static com.android.documentsui.DocumentsActivity.State.ACTION_OPEN;
-import static com.android.documentsui.DocumentsActivity.State.ACTION_OPEN_TREE;
-import static com.android.documentsui.DocumentsActivity.State.MODE_GRID;
-import static com.android.documentsui.DocumentsActivity.State.MODE_LIST;
-
+import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
+import static com.android.documentsui.BaseActivity.State.ACTION_GET_CONTENT;
+import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
+import static com.android.documentsui.BaseActivity.State.ACTION_OPEN;
+import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_TREE;
+import static com.android.documentsui.BaseActivity.State.MODE_GRID;
+import static com.android.documentsui.BaseActivity.State.MODE_LIST;
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentManager;
@@ -46,15 +45,12 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
 import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v4.widget.DrawerLayout;
 import android.support.v4.widget.DrawerLayout.DrawerListener;
 import android.util.Log;
-import android.util.SparseArray;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -79,7 +75,6 @@
 import com.android.documentsui.model.DocumentStack;
 import com.android.documentsui.model.DurableUtils;
 import com.android.documentsui.model.RootInfo;
-import com.google.common.collect.Maps;
 
 import libcore.io.IoUtils;
 
@@ -87,11 +82,10 @@
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
 import java.util.concurrent.Executor;
 
-public class DocumentsActivity extends Activity {
+public class DocumentsActivity extends BaseActivity {
     public static final String TAG = "Documents";
 
     private static final String EXTRA_STATE = "state";
@@ -203,8 +197,8 @@
             moreApps.setComponent(null);
             moreApps.setPackage(null);
             RootsFragment.show(getFragmentManager(), moreApps);
-        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_CREATE
-                || mState.action == ACTION_OPEN_TREE) {
+        } else if (mState.action == ACTION_OPEN
+                || mState.action == ACTION_CREATE || mState.action == ACTION_OPEN_TREE) {
             RootsFragment.show(getFragmentManager(), null);
         }
 
@@ -389,6 +383,7 @@
         updateActionBar();
     }
 
+    @Override
     public void setRootsDrawerOpen(boolean open) {
         if (!mShowAsDialog) {
             if (open) {
@@ -667,9 +662,7 @@
         invalidateOptionsMenu();
     }
 
-    /**
-     * Update UI to reflect internal state changes not from user.
-     */
+    @Override
     public void onStateChanged() {
         invalidateOptionsMenu();
     }
@@ -690,6 +683,7 @@
         DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
     }
 
+    @Override
     public void setPending(boolean pending) {
         final SaveFragment save = SaveFragment.get(getFragmentManager());
         if (save != null) {
@@ -808,6 +802,7 @@
         }
     };
 
+    @Override
     public RootInfo getCurrentRoot() {
         if (mState.stack.root != null) {
             return mState.stack.root;
@@ -816,6 +811,7 @@
         }
     }
 
+    @Override
     public DocumentInfo getCurrentDirectory() {
         return mState.stack.peek();
     }
@@ -834,6 +830,7 @@
         }
     }
 
+    @Override
     public State getDisplayState() {
         return mState;
     }
@@ -895,6 +892,7 @@
         dumpStack();
     }
 
+    @Override
     public void onStackPicked(DocumentStack stack) {
         try {
             // Update the restored stack to ensure we have freshest data
@@ -909,6 +907,7 @@
         }
     }
 
+    @Override
     public void onRootPicked(RootInfo root, boolean closeDrawer) {
         // Clear entire backstack and start in new root
         mState.stack.root = root;
@@ -955,6 +954,7 @@
         }
     }
 
+    @Override
     public void onAppPicked(ResolveInfo info) {
         final Intent intent = new Intent(getIntent());
         intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_FORWARD_RESULT);
@@ -985,6 +985,7 @@
         }
     }
 
+    @Override
     public void onDocumentPicked(DocumentInfo doc) {
         final FragmentManager fm = getFragmentManager();
         if (doc.isDirectory()) {
@@ -1020,6 +1021,7 @@
         }
     }
 
+    @Override
     public void onDocumentsPicked(List<DocumentInfo> docs) {
         if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
             final int size = docs.size();
@@ -1031,14 +1033,17 @@
         }
     }
 
+    @Override
     public void onSaveRequested(DocumentInfo replaceTarget) {
         new ExistingFinishTask(replaceTarget.derivedUri).executeOnExecutor(getCurrentExecutor());
     }
 
+    @Override
     public void onSaveRequested(String mimeType, String displayName) {
         new CreateFinishTask(mimeType, displayName).executeOnExecutor(getCurrentExecutor());
     }
 
+    @Override
     public void onPickRequested(DocumentInfo pickTarget) {
         final Uri viaUri = DocumentsContract.buildTreeDocumentUri(pickTarget.authority,
                 pickTarget.documentId);
@@ -1188,102 +1193,6 @@
         }
     }
 
-    public static class State implements android.os.Parcelable {
-        public int action;
-        public String[] acceptMimes;
-
-        /** Explicit user choice */
-        public int userMode = MODE_UNKNOWN;
-        /** Derived after loader */
-        public int derivedMode = MODE_LIST;
-
-        /** Explicit user choice */
-        public int userSortOrder = SORT_ORDER_UNKNOWN;
-        /** Derived after loader */
-        public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
-
-        public boolean allowMultiple = false;
-        public boolean showSize = false;
-        public boolean localOnly = false;
-        public boolean forceAdvanced = false;
-        public boolean showAdvanced = false;
-        public boolean stackTouched = false;
-        public boolean restored = false;
-
-        /** Current user navigation stack; empty implies recents. */
-        public DocumentStack stack = new DocumentStack();
-        /** Currently active search, overriding any stack. */
-        public String currentSearch;
-
-        /** Instance state for every shown directory */
-        public HashMap<String, SparseArray<Parcelable>> dirState = Maps.newHashMap();
-
-        public static final int ACTION_OPEN = 1;
-        public static final int ACTION_CREATE = 2;
-        public static final int ACTION_GET_CONTENT = 3;
-        public static final int ACTION_OPEN_TREE = 4;
-        public static final int ACTION_MANAGE = 5;
-
-        public static final int MODE_UNKNOWN = 0;
-        public static final int MODE_LIST = 1;
-        public static final int MODE_GRID = 2;
-
-        public static final int SORT_ORDER_UNKNOWN = 0;
-        public static final int SORT_ORDER_DISPLAY_NAME = 1;
-        public static final int SORT_ORDER_LAST_MODIFIED = 2;
-        public static final int SORT_ORDER_SIZE = 3;
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int flags) {
-            out.writeInt(action);
-            out.writeInt(userMode);
-            out.writeStringArray(acceptMimes);
-            out.writeInt(userSortOrder);
-            out.writeInt(allowMultiple ? 1 : 0);
-            out.writeInt(showSize ? 1 : 0);
-            out.writeInt(localOnly ? 1 : 0);
-            out.writeInt(forceAdvanced ? 1 : 0);
-            out.writeInt(showAdvanced ? 1 : 0);
-            out.writeInt(stackTouched ? 1 : 0);
-            out.writeInt(restored ? 1 : 0);
-            DurableUtils.writeToParcel(out, stack);
-            out.writeString(currentSearch);
-            out.writeMap(dirState);
-        }
-
-        public static final Creator<State> CREATOR = new Creator<State>() {
-            @Override
-            public State createFromParcel(Parcel in) {
-                final State state = new State();
-                state.action = in.readInt();
-                state.userMode = in.readInt();
-                state.acceptMimes = in.readStringArray();
-                state.userSortOrder = in.readInt();
-                state.allowMultiple = in.readInt() != 0;
-                state.showSize = in.readInt() != 0;
-                state.localOnly = in.readInt() != 0;
-                state.forceAdvanced = in.readInt() != 0;
-                state.showAdvanced = in.readInt() != 0;
-                state.stackTouched = in.readInt() != 0;
-                state.restored = in.readInt() != 0;
-                DurableUtils.readFromParcel(in, state.stack);
-                state.currentSearch = in.readString();
-                in.readMap(state.dirState, null);
-                return state;
-            }
-
-            @Override
-            public State[] newArray(int size) {
-                return new State[size];
-            }
-        };
-    }
-
     private void dumpStack() {
         Log.d(TAG, "Current stack: ");
         Log.d(TAG, " * " + mState.stack.root);
@@ -1291,8 +1200,4 @@
             Log.d(TAG, " +-- " + doc);
         }
     }
-
-    public static DocumentsActivity get(Fragment fragment) {
-        return (DocumentsActivity) fragment.getActivity();
-    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
index 5112c92..4b008ca 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
@@ -69,7 +69,7 @@
     private View.OnClickListener mPickListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
-            final DocumentsActivity activity = DocumentsActivity.get(PickFragment.this);
+            final BaseActivity activity = BaseActivity.get(PickFragment.this);
             activity.onPickRequested(mPickTarget);
         }
     };
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
index 34ce42d..f5908c5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
@@ -17,7 +17,7 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.DocumentsActivity.TAG;
-import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_LAST_MODIFIED;
+import static com.android.documentsui.BaseActivity.State.SORT_ORDER_LAST_MODIFIED;
 
 import android.app.ActivityManager;
 import android.content.AsyncTaskLoader;
@@ -34,7 +34,7 @@
 import android.text.format.DateUtils;
 import android.util.Log;
 
-import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.model.RootInfo;
 import com.google.android.collect.Maps;
 import com.google.common.collect.Lists;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index dd75dbd..26aecc5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -45,7 +45,7 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
-import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.RecentsProvider.RecentColumns;
 import com.android.documentsui.model.DocumentStack;
 import com.android.documentsui.model.DurableUtils;
@@ -95,7 +95,7 @@
         mListView.setAdapter(mAdapter);
 
         final RootsCache roots = DocumentsApplication.getRootsCache(context);
-        final State state = ((DocumentsActivity) getActivity()).getDisplayState();
+        final State state = ((BaseActivity) getActivity()).getDisplayState();
 
         mCallbacks = new LoaderCallbacks<List<DocumentStack>>() {
             @Override
@@ -110,7 +110,7 @@
 
                 // When launched into empty recents, show drawer
                 if (mAdapter.isEmpty() && !state.stackTouched) {
-                    ((DocumentsActivity) context).setRootsDrawerOpen(true);
+                    ((BaseActivity) context).setRootsDrawerOpen(true);
                 }
             }
 
@@ -139,7 +139,7 @@
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
             final DocumentStack stack = mAdapter.getItem(position);
-            ((DocumentsActivity) getActivity()).onStackPicked(stack);
+            ((BaseActivity) getActivity()).onStackPicked(stack);
         }
     };
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index d72db1d..ec71a04 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -36,7 +36,7 @@
 import android.provider.DocumentsContract.Root;
 import android.util.Log;
 
-import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.model.RootInfo;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 884cf31..ed5e123 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -16,8 +16,6 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.DocumentsActivity.State.ACTION_GET_CONTENT;
-
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
@@ -43,7 +41,7 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
-import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.RootInfo;
 import com.google.common.collect.Lists;
@@ -101,7 +99,7 @@
 
         final Context context = getActivity();
         final RootsCache roots = DocumentsApplication.getRootsCache(context);
-        final State state = ((DocumentsActivity) context).getDisplayState();
+        final State state = ((BaseActivity) context).getDisplayState();
 
         mCallbacks = new LoaderCallbacks<Collection<RootInfo>>() {
             @Override
@@ -138,9 +136,9 @@
 
     public void onDisplayStateChanged() {
         final Context context = getActivity();
-        final State state = ((DocumentsActivity) context).getDisplayState();
+        final State state = ((BaseActivity) context).getDisplayState();
 
-        if (state.action == ACTION_GET_CONTENT) {
+        if (state.action == State.ACTION_GET_CONTENT) {
             mList.setOnItemLongClickListener(mItemLongClickListener);
         } else {
             mList.setOnItemLongClickListener(null);
@@ -153,7 +151,7 @@
     public void onCurrentRootChanged() {
         if (mAdapter == null) return;
 
-        final RootInfo root = ((DocumentsActivity) getActivity()).getCurrentRoot();
+        final RootInfo root = ((BaseActivity) getActivity()).getCurrentRoot();
         for (int i = 0; i < mAdapter.getCount(); i++) {
             final Object item = mAdapter.getItem(i);
             if (item instanceof RootItem) {
@@ -176,7 +174,7 @@
     private OnItemClickListener mItemListener = new OnItemClickListener() {
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            final DocumentsActivity activity = DocumentsActivity.get(RootsFragment.this);
+            final BaseActivity activity = BaseActivity.get(RootsFragment.this);
             final Item item = mAdapter.getItem(position);
             if (item instanceof RootItem) {
                 activity.onRootPicked(((RootItem) item).root, true);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java
index 8d37cdf..49651b4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java
@@ -19,7 +19,7 @@
 import android.content.AsyncTaskLoader;
 import android.content.Context;
 
-import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.model.RootInfo;
 
 import java.util.Collection;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
index ce98db2..a13fccc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
@@ -113,7 +113,7 @@
     private View.OnClickListener mSaveListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
-            final DocumentsActivity activity = DocumentsActivity.get(SaveFragment.this);
+            final BaseActivity activity = BaseActivity.get(SaveFragment.this);
             if (mReplaceTarget != null) {
                 activity.onSaveRequested(mReplaceTarget);
             } else {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SortingCursorWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/SortingCursorWrapper.java
index 6c8ca20..3ec3d1c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SortingCursorWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SortingCursorWrapper.java
@@ -16,9 +16,9 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_DISPLAY_NAME;
-import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_LAST_MODIFIED;
-import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_SIZE;
+import static com.android.documentsui.BaseActivity.State.SORT_ORDER_DISPLAY_NAME;
+import static com.android.documentsui.BaseActivity.State.SORT_ORDER_LAST_MODIFIED;
+import static com.android.documentsui.BaseActivity.State.SORT_ORDER_SIZE;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java b/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java
new file mode 100644
index 0000000..e01328d
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/StandaloneActivity.java
@@ -0,0 +1,952 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+
+import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
+import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
+import static com.android.documentsui.DirectoryFragment.ANIM_SIDE;
+import static com.android.documentsui.DirectoryFragment.ANIM_UP;
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.ActivityNotFoundException;
+import android.content.ClipData;
+import android.content.ComponentName;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Point;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Debug;
+import android.provider.DocumentsContract;
+import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v4.widget.DrawerLayout.DrawerListener;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuItem.OnActionExpandListener;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.SearchView;
+import android.widget.SearchView.OnQueryTextListener;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.Toolbar;
+
+import com.android.documentsui.RecentsProvider.ResumeColumns;
+import com.android.documentsui.model.DocumentInfo;
+import com.android.documentsui.model.DocumentStack;
+import com.android.documentsui.model.DurableUtils;
+import com.android.documentsui.model.RootInfo;
+
+import libcore.io.IoUtils;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+public class StandaloneActivity extends BaseActivity {
+    public static final String TAG = "StandaloneFileManagement";
+
+    private static final String EXTRA_STATE = "state";
+
+    private static final int CODE_FORWARD = 42;
+
+    private SearchView mSearchView;
+
+    private Toolbar mToolbar;
+    private Spinner mToolbarStack;
+
+    private Toolbar mRootsToolbar;
+
+    private ActionBarDrawerToggle mDrawerToggle;
+
+    private DirectoryContainerView mDirectoryContainer;
+
+    private boolean mIgnoreNextNavigation;
+    private boolean mIgnoreNextClose;
+    private boolean mIgnoreNextCollapse;
+
+    private boolean mSearchExpanded;
+
+    private RootsCache mRoots;
+    private State mState;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        // Debug.waitForDebugger();
+        super.onCreate(icicle);
+
+        mRoots = DocumentsApplication.getRootsCache(this);
+
+        setResult(Activity.RESULT_CANCELED);
+        setContentView(R.layout.activity);
+
+        final Context context = this;
+        final Resources res = getResources();
+
+        // Strongly define our horizontal dimension; we leave vertical as
+        final WindowManager.LayoutParams a = getWindow().getAttributes();
+
+        final Point size = new Point();
+        getWindowManager().getDefaultDisplay().getSize(size);
+        // a.width = (int) res.getFraction(R.dimen.dialog_width, size.x, size.x);
+
+        getWindow().setAttributes(a);
+
+        mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
+
+        if (icicle != null) {
+            mState = icicle.getParcelable(EXTRA_STATE);
+        } else {
+            buildDefaultState();
+        }
+
+        mToolbar = (Toolbar) findViewById(R.id.toolbar);
+        mToolbar.setTitleTextAppearance(context,
+                android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
+
+        mToolbarStack = (Spinner) findViewById(R.id.stack);
+        mToolbarStack.setOnItemSelectedListener(mStackListener);
+
+        mRootsToolbar = (Toolbar) findViewById(R.id.roots_toolbar);
+        if (mRootsToolbar != null) {
+            mRootsToolbar.setTitleTextAppearance(context,
+                    android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
+        }
+
+        setActionBar(mToolbar);
+
+        RootsFragment.show(getFragmentManager(), null);
+        if (!mState.restored) {
+            new RestoreStackTask().execute();
+        } else {
+            onCurrentDirectoryChanged(ANIM_NONE);
+        }
+    }
+
+    private void buildDefaultState() {
+        mState = new State();
+
+        final Intent intent = getIntent();
+        mState.action = State.ACTION_MANAGE_ALL;
+        mState.acceptMimes = new String[] { "*/*" };
+        mState.allowMultiple = true;
+        mState.acceptMimes = new String[] { intent.getType() };
+        mState.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
+        mState.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
+        mState.showAdvanced = mState.forceAdvanced
+                | LocalPreferences.getDisplayAdvancedDevices(this);
+        mState.showSize = true;
+    }
+
+    private class RestoreRootTask extends AsyncTask<Void, Void, RootInfo> {
+        private Uri mRootUri;
+
+        public RestoreRootTask(Uri rootUri) {
+            mRootUri = rootUri;
+        }
+
+        @Override
+        protected RootInfo doInBackground(Void... params) {
+            final String rootId = DocumentsContract.getRootId(mRootUri);
+            return mRoots.getRootOneshot(mRootUri.getAuthority(), rootId);
+        }
+
+        @Override
+        protected void onPostExecute(RootInfo root) {
+            if (isDestroyed()) return;
+            mState.restored = true;
+
+            if (root != null) {
+                onRootPicked(root, true);
+            } else {
+                Log.w(TAG, "Failed to find root: " + mRootUri);
+                finish();
+            }
+        }
+    }
+
+    private class RestoreStackTask extends AsyncTask<Void, Void, Void> {
+        private volatile boolean mRestoredStack;
+        private volatile boolean mExternal;
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            // Restore last stack for calling package
+            final String packageName = getCallingPackageMaybeExtra();
+            final Cursor cursor = getContentResolver()
+                    .query(RecentsProvider.buildResume(packageName), null, null, null, null);
+            try {
+                if (cursor.moveToFirst()) {
+                    mExternal = cursor.getInt(cursor.getColumnIndex(ResumeColumns.EXTERNAL)) != 0;
+                    final byte[] rawStack = cursor.getBlob(
+                            cursor.getColumnIndex(ResumeColumns.STACK));
+                    DurableUtils.readFromArray(rawStack, mState.stack);
+                    mRestoredStack = true;
+                }
+            } catch (IOException e) {
+                Log.w(TAG, "Failed to resume: " + e);
+            } finally {
+                IoUtils.closeQuietly(cursor);
+            }
+
+            if (mRestoredStack) {
+                // Update the restored stack to ensure we have freshest data
+                final Collection<RootInfo> matchingRoots = mRoots.getMatchingRootsBlocking(mState);
+                try {
+                    mState.stack.updateRoot(matchingRoots);
+                    mState.stack.updateDocuments(getContentResolver());
+                } catch (FileNotFoundException e) {
+                    Log.w(TAG, "Failed to restore stack: " + e);
+                    mState.stack.reset();
+                    mRestoredStack = false;
+                }
+            }
+
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            if (isDestroyed()) return;
+            mState.restored = true;
+            onCurrentDirectoryChanged(ANIM_NONE);
+        }
+    }
+
+    @Override
+    protected void onPostCreate(Bundle savedInstanceState) {
+        super.onPostCreate(savedInstanceState);
+        if (mDrawerToggle != null) {
+            mDrawerToggle.syncState();
+        }
+        updateActionBar();
+    }
+
+    @Override
+    public void setRootsDrawerOpen(boolean open) {
+        Log.w(TAG, "Trying to change state of roots drawer to > " + (open ? "open" : "closed"));
+      // throw new UnsupportedOperationException();
+    }
+
+    public void updateActionBar() {
+        final RootInfo root = getCurrentRoot();
+        mToolbar.setNavigationIcon(
+                root != null ? root.loadToolbarIcon(mToolbar.getContext()) : null);
+        mToolbar.setNavigationContentDescription(R.string.drawer_open);
+        mToolbar.setNavigationOnClickListener(null);
+
+        if (mSearchExpanded) {
+            mToolbar.setTitle(null);
+            mToolbarStack.setVisibility(View.GONE);
+            mToolbarStack.setAdapter(null);
+        } else {
+            if (mState.stack.size() <= 1) {
+                mToolbar.setTitle(root.title);
+                mToolbarStack.setVisibility(View.GONE);
+                mToolbarStack.setAdapter(null);
+            } else {
+                mToolbar.setTitle(null);
+                mToolbarStack.setVisibility(View.VISIBLE);
+                mToolbarStack.setAdapter(mStackAdapter);
+
+                mIgnoreNextNavigation = true;
+                mToolbarStack.setSelection(mStackAdapter.getCount() - 1);
+            }
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        getMenuInflater().inflate(R.menu.activity, menu);
+
+        for (int i = 0; i < menu.size(); i++) {
+            final MenuItem item = menu.getItem(i);
+            switch (item.getItemId()) {
+                case R.id.menu_advanced:
+                case R.id.menu_file_size:
+                    break;
+                default:
+                    item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+            }
+        }
+
+        final MenuItem searchMenu = menu.findItem(R.id.menu_search);
+        mSearchView = (SearchView) searchMenu.getActionView();
+        mSearchView.setOnQueryTextListener(new OnQueryTextListener() {
+            @Override
+            public boolean onQueryTextSubmit(String query) {
+                mSearchExpanded = true;
+                mState.currentSearch = query;
+                mSearchView.clearFocus();
+                onCurrentDirectoryChanged(ANIM_NONE);
+                return true;
+            }
+
+            @Override
+            public boolean onQueryTextChange(String newText) {
+                return false;
+            }
+        });
+
+        searchMenu.setOnActionExpandListener(new OnActionExpandListener() {
+            @Override
+            public boolean onMenuItemActionExpand(MenuItem item) {
+                mSearchExpanded = true;
+                updateActionBar();
+                return true;
+            }
+
+            @Override
+            public boolean onMenuItemActionCollapse(MenuItem item) {
+                mSearchExpanded = false;
+                if (mIgnoreNextCollapse) {
+                    mIgnoreNextCollapse = false;
+                    return true;
+                }
+
+                mState.currentSearch = null;
+                onCurrentDirectoryChanged(ANIM_NONE);
+                return true;
+            }
+        });
+
+        mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
+            @Override
+            public boolean onClose() {
+                mSearchExpanded = false;
+                if (mIgnoreNextClose) {
+                    mIgnoreNextClose = false;
+                    return false;
+                }
+
+                mState.currentSearch = null;
+                onCurrentDirectoryChanged(ANIM_NONE);
+                return false;
+            }
+        });
+
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+
+        final FragmentManager fm = getFragmentManager();
+
+        final RootInfo root = getCurrentRoot();
+        final DocumentInfo cwd = getCurrentDirectory();
+
+        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
+        final MenuItem search = menu.findItem(R.id.menu_search);
+        final MenuItem sort = menu.findItem(R.id.menu_sort);
+        final MenuItem sortSize = menu.findItem(R.id.menu_sort_size);
+        final MenuItem grid = menu.findItem(R.id.menu_grid);
+        final MenuItem list = menu.findItem(R.id.menu_list);
+        final MenuItem advanced = menu.findItem(R.id.menu_advanced);
+        final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
+
+        sort.setVisible(cwd != null);
+        grid.setVisible(mState.derivedMode != State.MODE_GRID);
+        list.setVisible(mState.derivedMode != State.MODE_LIST);
+
+        if (mState.currentSearch != null) {
+            // Search uses backend ranking; no sorting
+            sort.setVisible(false);
+
+            search.expandActionView();
+
+            mSearchView.setIconified(false);
+            mSearchView.clearFocus();
+            mSearchView.setQuery(mState.currentSearch, false);
+        } else {
+            mIgnoreNextClose = true;
+            mSearchView.setIconified(true);
+            mSearchView.clearFocus();
+
+            mIgnoreNextCollapse = true;
+            search.collapseActionView();
+        }
+
+        // Only sort by size when visible
+        sortSize.setVisible(mState.showSize);
+
+        fileSize.setVisible(true);
+        search.setVisible(true);
+        createDir.setVisible(true);
+        advanced.setVisible(true);
+
+        advanced.setTitle(LocalPreferences.getDisplayAdvancedDevices(this)
+                ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
+        fileSize.setTitle(LocalPreferences.getDisplayFileSize(this)
+                ? R.string.menu_file_size_hide : R.string.menu_file_size_show);
+
+
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (mDrawerToggle != null && mDrawerToggle.onOptionsItemSelected(item)) {
+            return true;
+        }
+
+        final int id = item.getItemId();
+        if (id == android.R.id.home) {
+            onBackPressed();
+            return true;
+        } else if (id == R.id.menu_create_dir) {
+            CreateDirectoryFragment.show(getFragmentManager());
+            return true;
+        } else if (id == R.id.menu_search) {
+            return false;
+        } else if (id == R.id.menu_sort_name) {
+            setUserSortOrder(State.SORT_ORDER_DISPLAY_NAME);
+            return true;
+        } else if (id == R.id.menu_sort_date) {
+            setUserSortOrder(State.SORT_ORDER_LAST_MODIFIED);
+            return true;
+        } else if (id == R.id.menu_sort_size) {
+            setUserSortOrder(State.SORT_ORDER_SIZE);
+            return true;
+        } else if (id == R.id.menu_grid) {
+            setUserMode(State.MODE_GRID);
+            return true;
+        } else if (id == R.id.menu_list) {
+            setUserMode(State.MODE_LIST);
+            return true;
+        } else if (id == R.id.menu_advanced) {
+            setDisplayAdvancedDevices(!LocalPreferences.getDisplayAdvancedDevices(this));
+            return true;
+        } else if (id == R.id.menu_file_size) {
+            setDisplayFileSize(!LocalPreferences.getDisplayFileSize(this));
+            return true;
+        } else {
+            return super.onOptionsItemSelected(item);
+        }
+    }
+
+    private void setDisplayAdvancedDevices(boolean display) {
+        LocalPreferences.setDisplayAdvancedDevices(this, display);
+        mState.showAdvanced = mState.forceAdvanced | display;
+        RootsFragment.get(getFragmentManager()).onDisplayStateChanged();
+        invalidateOptionsMenu();
+    }
+
+    private void setDisplayFileSize(boolean display) {
+        LocalPreferences.setDisplayFileSize(this, display);
+        mState.showSize = display;
+        DirectoryFragment.get(getFragmentManager()).onDisplayStateChanged();
+        invalidateOptionsMenu();
+    }
+
+    @Override
+    public void onStateChanged() {
+        invalidateOptionsMenu();
+    }
+
+    /**
+     * Set state sort order based on explicit user action.
+     */
+    private void setUserSortOrder(int sortOrder) {
+        mState.userSortOrder = sortOrder;
+        DirectoryFragment.get(getFragmentManager()).onUserSortOrderChanged();
+    }
+
+    /**
+     * Set state mode based on explicit user action.
+     */
+    private void setUserMode(int mode) {
+        mState.userMode = mode;
+        DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
+    }
+
+    @Override
+    public void setPending(boolean pending) {
+        final SaveFragment save = SaveFragment.get(getFragmentManager());
+        if (save != null) {
+            save.setPending(pending);
+        }
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (!mState.stackTouched) {
+            super.onBackPressed();
+            return;
+        }
+
+        final int size = mState.stack.size();
+        if (size > 1) {
+            mState.stack.pop();
+            onCurrentDirectoryChanged(ANIM_UP);
+        } else {
+            super.onBackPressed();
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle state) {
+        super.onSaveInstanceState(state);
+        state.putParcelable(EXTRA_STATE, mState);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle state) {
+        super.onRestoreInstanceState(state);
+    }
+
+    private BaseAdapter mStackAdapter = new BaseAdapter() {
+        @Override
+        public int getCount() {
+            return mState.stack.size();
+        }
+
+        @Override
+        public DocumentInfo getItem(int position) {
+            return mState.stack.get(mState.stack.size() - position - 1);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = LayoutInflater.from(parent.getContext())
+                        .inflate(R.layout.item_subdir_title, parent, false);
+            }
+
+            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+            final DocumentInfo doc = getItem(position);
+
+            if (position == 0) {
+                final RootInfo root = getCurrentRoot();
+                title.setText(root.title);
+            } else {
+                title.setText(doc.displayName);
+            }
+
+            return convertView;
+        }
+
+        @Override
+        public View getDropDownView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = LayoutInflater.from(parent.getContext())
+                        .inflate(R.layout.item_subdir, parent, false);
+            }
+
+            final ImageView subdir = (ImageView) convertView.findViewById(R.id.subdir);
+            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+            final DocumentInfo doc = getItem(position);
+
+            if (position == 0) {
+                final RootInfo root = getCurrentRoot();
+                title.setText(root.title);
+                subdir.setVisibility(View.GONE);
+            } else {
+                title.setText(doc.displayName);
+                subdir.setVisibility(View.VISIBLE);
+            }
+
+            return convertView;
+        }
+    };
+
+    private OnItemSelectedListener mStackListener = new OnItemSelectedListener() {
+        @Override
+        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+            if (mIgnoreNextNavigation) {
+                mIgnoreNextNavigation = false;
+                return;
+            }
+
+            while (mState.stack.size() > position + 1) {
+                mState.stackTouched = true;
+                mState.stack.pop();
+            }
+            onCurrentDirectoryChanged(ANIM_UP);
+        }
+
+        @Override
+        public void onNothingSelected(AdapterView<?> parent) {
+            // Ignored
+        }
+    };
+
+    @Override
+    public RootInfo getCurrentRoot() {
+        if (mState.stack.root != null) {
+            return mState.stack.root;
+        } else {
+            return mRoots.getRecentsRoot();
+        }
+    }
+
+    public DocumentInfo getCurrentDirectory() {
+        return mState.stack.peek();
+    }
+
+    private String getCallingPackageMaybeExtra() {
+        final String extra = getIntent().getStringExtra(DocumentsContract.EXTRA_PACKAGE_NAME);
+        return (extra != null) ? extra : getCallingPackage();
+    }
+
+    public Executor getCurrentExecutor() {
+        final DocumentInfo cwd = getCurrentDirectory();
+        if (cwd != null && cwd.authority != null) {
+            return ProviderExecutor.forAuthority(cwd.authority);
+        } else {
+            return AsyncTask.THREAD_POOL_EXECUTOR;
+        }
+    }
+
+    @Override
+    public State getDisplayState() {
+        return mState;
+    }
+
+    private void onCurrentDirectoryChanged(int anim) {
+        final FragmentManager fm = getFragmentManager();
+        final RootInfo root = getCurrentRoot();
+        final DocumentInfo cwd = getCurrentDirectory();
+
+        mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
+
+        if (cwd == null) {
+            DirectoryFragment.showRecentsOpen(fm, anim);
+
+            // Start recents in grid when requesting visual things
+            final boolean visualMimes = MimePredicate.mimeMatches(
+                    MimePredicate.VISUAL_MIMES, mState.acceptMimes);
+            mState.userMode = visualMimes ? State.MODE_GRID : State.MODE_LIST;
+            mState.derivedMode = mState.userMode;
+        } else {
+            if (mState.currentSearch != null) {
+                // Ongoing search
+                DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
+            } else {
+                // Normal boring directory
+                DirectoryFragment.showNormal(fm, root, cwd, anim);
+            }
+        }
+
+        final RootsFragment roots = RootsFragment.get(fm);
+        if (roots != null) {
+            roots.onCurrentRootChanged();
+        }
+
+        updateActionBar();
+        invalidateOptionsMenu();
+        dumpStack();
+    }
+
+    @Override
+    public void onStackPicked(DocumentStack stack) {
+        try {
+            // Update the restored stack to ensure we have freshest data
+            stack.updateDocuments(getContentResolver());
+
+            mState.stack = stack;
+            mState.stackTouched = true;
+            onCurrentDirectoryChanged(ANIM_SIDE);
+
+        } catch (FileNotFoundException e) {
+            Log.w(TAG, "Failed to restore stack: " + e);
+        }
+    }
+
+    @Override
+    public void onRootPicked(RootInfo root, boolean closeDrawer) {
+        // Clear entire backstack and start in new root
+        mState.stack.root = root;
+        mState.stack.clear();
+        mState.stackTouched = true;
+
+        if (!mRoots.isRecentsRoot(root)) {
+            new PickRootTask(root).executeOnExecutor(getCurrentExecutor());
+        } else {
+            onCurrentDirectoryChanged(ANIM_SIDE);
+        }
+    }
+
+    private class PickRootTask extends AsyncTask<Void, Void, DocumentInfo> {
+        private RootInfo mRoot;
+
+        public PickRootTask(RootInfo root) {
+            mRoot = root;
+        }
+
+        @Override
+        protected DocumentInfo doInBackground(Void... params) {
+            try {
+                final Uri uri = DocumentsContract.buildDocumentUri(
+                        mRoot.authority, mRoot.documentId);
+                return DocumentInfo.fromUri(getContentResolver(), uri);
+            } catch (FileNotFoundException e) {
+                Log.w(TAG, "Failed to find root", e);
+                return null;
+            }
+        }
+
+        @Override
+        protected void onPostExecute(DocumentInfo result) {
+            if (result != null) {
+                mState.stack.push(result);
+                mState.stackTouched = true;
+                onCurrentDirectoryChanged(ANIM_SIDE);
+            }
+        }
+    }
+
+    @Override
+    public void onAppPicked(ResolveInfo info) {
+        final Intent intent = new Intent(getIntent());
+        intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+        intent.setComponent(new ComponentName(
+                info.activityInfo.applicationInfo.packageName, info.activityInfo.name));
+        startActivityForResult(intent, CODE_FORWARD);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        Log.d(TAG, "onActivityResult() code=" + resultCode);
+
+        // Only relay back results when not canceled; otherwise stick around to
+        // let the user pick another app/backend.
+        if (requestCode == CODE_FORWARD && resultCode != RESULT_CANCELED) {
+
+            // Remember that we last picked via external app
+            final String packageName = getCallingPackageMaybeExtra();
+            final ContentValues values = new ContentValues();
+            values.put(ResumeColumns.EXTERNAL, 1);
+            getContentResolver().insert(RecentsProvider.buildResume(packageName), values);
+
+            // Pass back result to original caller
+            setResult(resultCode, data);
+            finish();
+        } else {
+            super.onActivityResult(requestCode, resultCode, data);
+        }
+    }
+
+    @Override
+    public void onDocumentPicked(DocumentInfo doc) {
+        final FragmentManager fm = getFragmentManager();
+        if (doc.isDirectory()) {
+            mState.stack.push(doc);
+            mState.stackTouched = true;
+            onCurrentDirectoryChanged(ANIM_DOWN);
+        } else {
+            // Fall back to viewing
+            final Intent view = new Intent(Intent.ACTION_VIEW);
+            view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            view.setData(doc.derivedUri);
+
+            try {
+                startActivity(view);
+            } catch (ActivityNotFoundException ex2) {
+                Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
+            }
+        }
+    }
+
+    public void onDocumentsPicked(List<DocumentInfo> docs) {
+        // TODO
+    }
+
+    @Override
+    public void onSaveRequested(DocumentInfo replaceTarget) {
+        new ExistingFinishTask(replaceTarget.derivedUri).executeOnExecutor(getCurrentExecutor());
+    }
+
+    @Override
+    public void onSaveRequested(String mimeType, String displayName) {
+        new CreateFinishTask(mimeType, displayName).executeOnExecutor(getCurrentExecutor());
+    }
+
+    @Override
+    public void onPickRequested(DocumentInfo pickTarget) {
+        final Uri viaUri = DocumentsContract.buildTreeDocumentUri(pickTarget.authority,
+                pickTarget.documentId);
+        new PickFinishTask(viaUri).executeOnExecutor(getCurrentExecutor());
+    }
+
+    private void saveStackBlocking() {
+        final ContentResolver resolver = getContentResolver();
+        final ContentValues values = new ContentValues();
+
+        final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
+
+        // Remember location for next app launch
+        final String packageName = getCallingPackageMaybeExtra();
+        values.clear();
+        values.put(ResumeColumns.STACK, rawStack);
+        values.put(ResumeColumns.EXTERNAL, 0);
+        resolver.insert(RecentsProvider.buildResume(packageName), values);
+    }
+
+    private void onFinished(Uri... uris) {
+        Log.d(TAG, "onFinished() " + Arrays.toString(uris));
+
+        final Intent intent = new Intent();
+        if (uris.length == 1) {
+            intent.setData(uris[0]);
+        } else if (uris.length > 1) {
+            final ClipData clipData = new ClipData(
+                    null, mState.acceptMimes, new ClipData.Item(uris[0]));
+            for (int i = 1; i < uris.length; i++) {
+                clipData.addItem(new ClipData.Item(uris[i]));
+            }
+            intent.setClipData(clipData);
+        }
+
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+
+        setResult(Activity.RESULT_OK, intent);
+        finish();
+    }
+
+    private class CreateFinishTask extends AsyncTask<Void, Void, Uri> {
+        private final String mMimeType;
+        private final String mDisplayName;
+
+        public CreateFinishTask(String mimeType, String displayName) {
+            mMimeType = mimeType;
+            mDisplayName = displayName;
+        }
+
+        @Override
+        protected void onPreExecute() {
+            setPending(true);
+        }
+
+        @Override
+        protected Uri doInBackground(Void... params) {
+            final ContentResolver resolver = getContentResolver();
+            final DocumentInfo cwd = getCurrentDirectory();
+
+            ContentProviderClient client = null;
+            Uri childUri = null;
+            try {
+                client = DocumentsApplication.acquireUnstableProviderOrThrow(
+                        resolver, cwd.derivedUri.getAuthority());
+                childUri = DocumentsContract.createDocument(
+                        client, cwd.derivedUri, mMimeType, mDisplayName);
+            } catch (Exception e) {
+                Log.w(TAG, "Failed to create document", e);
+            } finally {
+                ContentProviderClient.releaseQuietly(client);
+            }
+
+            if (childUri != null) {
+                saveStackBlocking();
+            }
+
+            return childUri;
+        }
+
+        @Override
+        protected void onPostExecute(Uri result) {
+            if (result != null) {
+                onFinished(result);
+            } else {
+                Toast.makeText(StandaloneActivity.this, R.string.save_error, Toast.LENGTH_SHORT)
+                        .show();
+            }
+
+            setPending(false);
+        }
+    }
+
+    private class ExistingFinishTask extends AsyncTask<Void, Void, Void> {
+        private final Uri[] mUris;
+
+        public ExistingFinishTask(Uri... uris) {
+            mUris = uris;
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            saveStackBlocking();
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            onFinished(mUris);
+        }
+    }
+
+    private class PickFinishTask extends AsyncTask<Void, Void, Void> {
+        private final Uri mUri;
+
+        public PickFinishTask(Uri uri) {
+            mUri = uri;
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            saveStackBlocking();
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            onFinished(mUri);
+        }
+    }
+
+    private void dumpStack() {
+        Log.d(TAG, "Current stack: ");
+        Log.d(TAG, " * " + mState.stack.root);
+        for (DocumentInfo doc : mState.stack) {
+            Log.d(TAG, " +-- " + doc);
+        }
+    }
+
+    public static BaseActivity get(Fragment fragment) {
+        return (BaseActivity) fragment.getActivity();
+    }
+}
diff --git a/packages/IntentFilterVerifier/Android.mk b/packages/IntentFilterVerifier/Android.mk
new file mode 100644
index 0000000..99feda5
--- /dev/null
+++ b/packages/IntentFilterVerifier/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Build the IntentFilterVerifier.
+include $(CLEAR_VARS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+        volley \
+
+LOCAL_JAVA_LIBRARIES += org.apache.http.legacy
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := IntentFilterVerifier
+
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_PROGUARD_FLAGS := $(proguard.flags)
+
+include $(BUILD_PACKAGE)
+
+# Build the test package.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/IntentFilterVerifier/AndroidManifest.xml b/packages/IntentFilterVerifier/AndroidManifest.xml
new file mode 100644
index 0000000..3829cc5
--- /dev/null
+++ b/packages/IntentFilterVerifier/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.verifier.intentfilter"
+        coreApp="true">
+    <uses-permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+
+    <application
+            android:label="@string/service_name"
+            android:allowBackup="false">
+
+        <receiver
+                android:name="com.android.verifier.intentfilter.IntentVerificationReceiver"
+                android:permission="android.permission.BIND_INTENT_FILTER_VERIFIER" >
+            <intent-filter
+                    android:priority="-1" >
+                <action android:name="android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION" />
+                <data android:mimeType="application/vnd.android.package-archive" />
+            </intent-filter>
+        </receiver>
+
+        <service android:name=".IntentVerificationService"
+                 android:label="@string/service_name"
+                 android:exported="false"/>
+
+    </application>
+
+</manifest>
diff --git a/packages/IntentFilterVerifier/CleanSpec.mk b/packages/IntentFilterVerifier/CleanSpec.mk
new file mode 100644
index 0000000..e4575ae
--- /dev/null
+++ b/packages/IntentFilterVerifier/CleanSpec.mk
@@ -0,0 +1,49 @@
+# 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# *****************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THE BANNER
+# *****************************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ******************************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
+# ******************************************************************
diff --git a/packages/IntentFilterVerifier/proguard.flags b/packages/IntentFilterVerifier/proguard.flags
new file mode 100644
index 0000000..6e4bec3
--- /dev/null
+++ b/packages/IntentFilterVerifier/proguard.flags
@@ -0,0 +1 @@
+-verbose
\ No newline at end of file
diff --git a/packages/IntentFilterVerifier/res/values/strings.xml b/packages/IntentFilterVerifier/res/values/strings.xml
new file mode 100644
index 0000000..22f3cd5
--- /dev/null
+++ b/packages/IntentFilterVerifier/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Package name shown to users when they look at installed applications
+         and running processes. This service verifies packages that are
+         requested to be installed. [CHAR LIMIT=50] -->
+    <string name="service_name">Basic Intent Filter Verification Service</string>
+
+</resources>
diff --git a/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationReceiver.java b/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationReceiver.java
new file mode 100644
index 0000000..de25f8c
--- /dev/null
+++ b/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationReceiver.java
@@ -0,0 +1,90 @@
+/*
+ * 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.verifier.intentfilter;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.Slog;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class IntentVerificationReceiver extends BroadcastReceiver {
+    static final String TAG = IntentVerificationReceiver.class.getName();
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final String action = intent.getAction();
+        if (Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION.equals(action)) {
+            Bundle extras = intent.getExtras();
+            if (extras != null) {
+                int verificationId = extras.getInt(
+                        PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_ID);
+                String hosts = extras.getString(
+                        PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_HOSTS);
+
+                Log.d(TAG, "Received IntentFilter verification broadcast with verificationId: "
+                        + verificationId);
+
+                if (canDoVerification(context)) {
+                    Intent serviceIntent = new Intent(context, IntentVerificationService.class);
+                    serviceIntent.fillIn(intent, 0);
+                    serviceIntent.putExtras(intent.getExtras());
+
+                    Slog.d(TAG, "Starting Intent Verification Service.");
+
+                    context.startService(serviceIntent);
+                } else {
+                    sendVerificationFailure(context, verificationId, hosts);
+                }
+            }
+
+        } else {
+            Log.w(TAG, "Unexpected action: " + action);
+        }
+    }
+
+    private void sendVerificationFailure(Context context, int verificationId, String hosts) {
+        List<String> list = Arrays.asList(hosts.split(" "));
+        context.getPackageManager().verifyIntentFilter(
+                verificationId, PackageManager.INTENT_FILTER_VERIFICATION_FAILURE, list);
+
+        Log.d(TAG, "No network! Failing IntentFilter verification with verificationId: " +
+                verificationId + " and hosts: " + hosts);
+    }
+
+    private boolean canDoVerification(Context context) {
+        return hasNetwork(context);
+    }
+
+    public boolean hasNetwork(Context context) {
+        ConnectivityManager cm =
+                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        if (cm != null) {
+            NetworkInfo info = cm.getActiveNetworkInfo();
+            return (info != null) && info.isConnected();
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationRequest.java b/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationRequest.java
new file mode 100644
index 0000000..8f9c86f
--- /dev/null
+++ b/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationRequest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.verifier.intentfilter;
+
+import com.android.volley.Response;
+import com.android.volley.toolbox.JsonArrayRequest;
+import org.json.JSONArray;
+
+public class IntentVerificationRequest extends JsonArrayRequest {
+
+    public IntentVerificationRequest(String url, Response.Listener<JSONArray> listener,
+            Response.ErrorListener errorListener) {
+        super(url, listener, errorListener);
+    }
+}
diff --git a/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationService.java b/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationService.java
new file mode 100644
index 0000000..3e4db6c
--- /dev/null
+++ b/packages/IntentFilterVerifier/src/com/android/verifier/intentfilter/IntentVerificationService.java
@@ -0,0 +1,468 @@
+/*
+ * 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.verifier.intentfilter;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Slog;
+import com.android.volley.RequestQueue;
+import com.android.volley.Response;
+import com.android.volley.VolleyError;
+import com.android.volley.toolbox.Volley;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+public class IntentVerificationService extends Service {
+    private static final String TAG = "IntentVerificationService";
+
+    private static final String WELL_KNOWN_ASSOCIATIONS_JSON = "/.well-known/associations.json";
+    private static final String DEFAULT_SCHEME = "https";
+
+    private static final String JSON_KEY_TARGET = "target";
+    private static final String JSON_KEY_NAMESPACE = "namespace";
+    private static final String JSON_KEY_PACKAGE_NAME = "package_name";
+    private static final String JSON_KEY_CERT_FINGERPRINTS = "sha256_cert_fingerprints";
+
+    private static final String JSON_VAL_ANDROID_APP = "android_app";
+
+    private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+            'A', 'B', 'C', 'D', 'E', 'F' };
+
+    private ConnectivityManager mConnectivityManager;
+    private Looper mHandlerLooper;
+    private VerificationHandler mHandler;
+    private RequestQueue mRequestQueue;
+
+    private static class VerificationState {
+        public final int verificationId;
+        public final String hosts;
+        public final String packageName;
+        public final Set<String> fingerprints;
+        public int responseCode = PackageManager.INTENT_FILTER_VERIFICATION_SUCCESS;
+        public int counter;
+        public int numberOfHosts;
+        public ArrayList<String> failedHosts = new ArrayList<>();
+
+        private final Object lock = new Object();
+
+        public VerificationState(int id, String h, String p, Set<String> fps) {
+            verificationId = id;
+            hosts = h;
+            packageName = p;
+            fingerprints = fps;
+            numberOfHosts = hosts.split(" ").length;
+        }
+        public boolean setResponseCodeAndCheckMax(int code) {
+            synchronized (lock) {
+                if (code == PackageManager.INTENT_FILTER_VERIFICATION_FAILURE) {
+                    responseCode = code;
+                    counter++;
+                } else if (code == PackageManager.INTENT_FILTER_VERIFICATION_SUCCESS) {
+                    counter++;
+                }
+                return (counter == numberOfHosts);
+            }
+        }
+
+        public void addFailedHost(String host) {
+            synchronized (failedHosts) {
+                failedHosts.add(host);
+            }
+        }
+
+        public ArrayList<String> getFailedHosts() {
+            return failedHosts;
+        }
+    }
+
+    private HashMap<Integer, VerificationState> mVerificationMap =
+            new HashMap<Integer, VerificationState>();
+
+    private class VerificationHandler extends Handler {
+        private static final int MSG_STOP_SERVICE = 0;
+        private static final int MSG_VERIFY_INTENT_START = 1;
+        private static final int MSG_VERIFY_INTENT_DONE = 2;
+
+        private static final long SHUTDOWN_DELAY_MILLIS = 8 * 1000;
+
+        private final Context mContext;
+
+        public VerificationHandler(Context context, Looper looper) {
+            super(looper);
+
+            mContext = context;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_VERIFY_INTENT_START:
+                    final Intent intent = (Intent) msg.obj;
+                    Bundle extras = intent.getExtras();
+                    boolean immediate = false;
+
+                    if (extras != null) {
+                        immediate = doVerification(extras);
+                    }
+
+                    // There was no network, so we can stop soon
+                    if (immediate) {
+                        stopDelayed();
+                    }
+                    break;
+
+                case MSG_VERIFY_INTENT_DONE:
+                    VerificationState vs = (VerificationState) msg.obj;
+                    processVerificationDone(mContext, vs);
+                    clearVerificationState(vs);
+                    break;
+
+                case MSG_STOP_SERVICE:
+                    stopSelf();
+                    break;
+
+                default:
+                    Slog.i(TAG, "Unknown message posted " + msg.toString());
+                    break;
+
+            }
+        }
+
+        private void stopDelayed() {
+            removeMessages(MSG_STOP_SERVICE);
+            sendEmptyMessageDelayed(MSG_STOP_SERVICE, SHUTDOWN_DELAY_MILLIS);
+        }
+    }
+
+    private VerificationState getVerificationState(int id, String hosts, String packageName,
+            Set<String> fingerprints) {
+        synchronized (mVerificationMap) {
+            VerificationState vs = mVerificationMap.get(id);
+            if (vs == null) {
+                vs = new VerificationState(id, hosts, packageName, fingerprints);
+            }
+            return vs;
+        }
+    }
+
+    private void clearVerificationState(VerificationState vs) {
+        mVerificationMap.remove(vs);
+    }
+
+    private boolean doVerification(Bundle extras) {
+        String scheme = extras.getString(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_URI_SCHEME);
+        if (TextUtils.isEmpty(scheme)) {
+            scheme = DEFAULT_SCHEME;
+        }
+
+        int verificationId = extras.getInt(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_ID);
+        String hosts = extras.getString(PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_HOSTS);
+        String packageName = extras.getString(
+                PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_PACKAGE_NAME);
+
+        Set<String> fingerprints = getFingerprints(packageName);
+
+        Log.d(TAG, "Received IntentFilter verification broadcast with verificationId:" +
+                verificationId + " hosts:'" + hosts + "' scheme:" + scheme);
+
+        VerificationState vs = getVerificationState(verificationId, hosts, packageName,
+                fingerprints);
+
+        if (hasNetwork()) {
+            sendNetworkVerifications(scheme, vs);
+            return false;
+        }
+
+        // No network, so fail immediately
+        sendFailureResponseIfNeeded(vs);
+
+        return true;
+    }
+
+    private Set<String> getFingerprints(String packageName) {
+        Context context = getApplicationContext();
+        try {
+            Signature[] signatures = context.getPackageManager().getPackageInfo(packageName,
+                    PackageManager.GET_SIGNATURES).signatures;
+            if (signatures.length > 0) {
+                HashSet<String> result = new HashSet<String>();
+                for (Signature sig : signatures) {
+                    String fingerprint = computeNormalizedSha256Fingerprint(sig.toByteArray());
+                    result.add(fingerprint);
+                }
+                return result;
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "Cannot get signatures for package name: " + packageName);
+        }
+        return Collections.EMPTY_SET;
+    }
+
+    private static String computeNormalizedSha256Fingerprint(byte[] signature) {
+        MessageDigest digester;
+        try {
+            digester = MessageDigest.getInstance("SHA-256");
+        } catch (NoSuchAlgorithmException e) {
+            throw new AssertionError("No SHA-256 implementation found.");
+        }
+        digester.update(signature);
+        return byteArrayToHexString(digester.digest());
+    }
+
+    private static String byteArrayToHexString(byte[] array) {
+        if (array.length == 0) {
+            return "";
+        }
+        char[] buf = new char[array.length * 3 - 1];
+
+        int bufIndex = 0;
+        for (int i = 0; i < array.length; i++) {
+            byte b = array[i];
+            if (i > 0) {
+                buf[bufIndex++] = ':';
+            }
+            buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
+            buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
+        }
+        return new String(buf);
+    }
+
+    private static String getAssociationPath() {
+        return WELL_KNOWN_ASSOCIATIONS_JSON;
+    }
+
+    private void sendNetworkVerifications(String scheme, final VerificationState vs) {
+        final int verificationId = vs.verificationId;
+        final String hosts = vs.hosts;
+
+        String[] array = hosts.split(" ");
+        for (final String host : array) {
+            try {
+                final URL url = new URL(scheme, host, getAssociationPath());
+                final String urlStr = url.toString();
+                Log.d(TAG, "Using verification URL: " + urlStr);
+                IntentVerificationRequest req = new IntentVerificationRequest(urlStr,
+                    new Response.Listener<JSONArray>() {
+                        @Override
+                        public void onResponse(JSONArray response) {
+                            Log.d(TAG, "From: " + urlStr + " received response: "
+                                    + response.toString());
+                            handleResponse(vs, host, response);
+                        }
+                    }, new Response.ErrorListener() {
+                        @Override
+                        public void onErrorResponse(VolleyError error) {
+                            Slog.d(TAG, "From: " + urlStr + " got error: " + error.getMessage()
+                                    + (error.networkResponse != null ? " with status code: "
+                                    + error.networkResponse.statusCode : ""));
+                            handleError(vs, host);
+                        }
+                    }
+                );
+                mRequestQueue.add(req);
+            } catch (MalformedURLException e) {
+                Log.w(TAG, "Cannot send verificationId: " + verificationId + " to host: " + host);
+            }
+        }
+    }
+
+    private void handleError(VerificationState vs, String host) {
+        vs.addFailedHost(host);
+        sendFailureResponseIfNeeded(vs);
+    }
+
+    private void handleResponse(VerificationState vs, String host, JSONArray response) {
+        try {
+            if (response.length() == 0) {
+                Log.d(TAG, "Domain response is empty!");
+                handleError(vs, host);
+                return;
+            }
+
+            JSONObject firstRelation = (JSONObject) response.get(0);
+            if (firstRelation == null) {
+                Log.d(TAG, "Domain response is should have a relation!");
+                handleError(vs, host);
+                return;
+            }
+
+            JSONObject target = (JSONObject) firstRelation.get(JSON_KEY_TARGET);
+            if (target == null) {
+                Log.d(TAG, "Domain response target is empty!");
+                handleError(vs, host);
+                return;
+            }
+
+            String nameSpace = target.getString(JSON_KEY_NAMESPACE);
+            if (TextUtils.isEmpty(nameSpace) || !nameSpace.equals(JSON_VAL_ANDROID_APP)) {
+                Log.d(TAG, "Domain response target name space is not valid: " + nameSpace);
+                handleError(vs, host);
+                return;
+            }
+
+            String packageName = target.getString(JSON_KEY_PACKAGE_NAME);
+            JSONArray certFingerprints = target.getJSONArray(JSON_KEY_CERT_FINGERPRINTS);
+
+            // Early exits is the JSON response is not correct for the package name or signature
+            if (TextUtils.isEmpty(packageName)) {
+                Log.d(TAG, "Domain response has empty package name!");
+                handleError(vs, host);
+                return;
+            }
+            if (certFingerprints.length() == 0) {
+                Log.d(TAG, "Domain response has empty cert signature!");
+                handleError(vs, host);
+                return;
+            }
+            // Now do the real test on package name and signature
+            if (!packageName.equalsIgnoreCase(vs.packageName)) {
+                Log.d(TAG, "Domain response has package name mismatch!" + packageName +
+                        " vs " + vs.packageName);
+                handleError(vs, host);
+                return;
+            }
+            final int count = certFingerprints.length();
+            for (int i = 0; i < count; i++) {
+                String fingerprint = certFingerprints.getString(i);
+                if (!vs.fingerprints.contains(fingerprint)) {
+                    Log.d(TAG, "Domain response has cert fingerprint mismatch! " +
+                            "The domain fingerprint '" + fingerprint + "' is not from the App");
+                    handleError(vs, host);
+                    return;
+                }
+            }
+            sendSuccessResponseIfNeeded(vs);
+        } catch (JSONException e) {
+            Log.d(TAG, "Domain response is not well formed", e);
+            handleError(vs, host);
+        }
+    }
+
+    private void sendSuccessResponseIfNeeded(VerificationState vs) {
+        if (vs.setResponseCodeAndCheckMax(PackageManager.INTENT_FILTER_VERIFICATION_SUCCESS)) {
+            sendMessage(vs);
+        }
+    }
+
+    private void sendFailureResponseIfNeeded(VerificationState vs) {
+        if (vs.setResponseCodeAndCheckMax(PackageManager.INTENT_FILTER_VERIFICATION_FAILURE)) {
+            sendMessage(vs);
+        }
+    }
+
+    private void sendMessage(VerificationState vs) {
+        Message msg = mHandler.obtainMessage(VerificationHandler.MSG_VERIFY_INTENT_DONE);
+        msg.obj = vs;
+        mHandler.sendMessage(msg);
+    }
+
+    private void processVerificationDone(Context context, VerificationState state) {
+        int verificationId = state.verificationId;
+        String hosts = state.hosts;
+        int responseCode = state.responseCode;
+
+        final PackageManager pm = context.getPackageManager();
+
+        // Callback the PackageManager
+        pm.verifyIntentFilter(verificationId, responseCode, state.getFailedHosts());
+        Log.d(TAG, "IntentFilter with verificationId: " + verificationId + " and hosts: " +
+                hosts + " got verification code: " + responseCode);
+    }
+
+    /**
+     * We only connect to this service from the same process.
+     */
+    public class LocalBinder extends Binder {
+        IntentVerificationService getService() { return IntentVerificationService.this; }
+    }
+
+    private final IBinder mBinder = new LocalBinder();
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        Slog.i(TAG, "Received start id " + startId + ": " + intent);
+
+        final Message msg = mHandler.obtainMessage(VerificationHandler.MSG_VERIFY_INTENT_START);
+        msg.obj = intent;
+        mHandler.sendMessage(msg);
+
+        return START_STICKY;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        Slog.d(TAG, "Starting up...");
+
+        final HandlerThread handlerThread = new HandlerThread("IntentVerificationService");
+        handlerThread.start();
+        mHandlerLooper = handlerThread.getLooper();
+
+        mHandler = new VerificationHandler(getApplicationContext(), mHandlerLooper);
+
+        mRequestQueue = Volley.newRequestQueue(this);
+        mRequestQueue.start();
+
+        mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+
+        Slog.d(TAG, "Shutting down...");
+
+        mHandlerLooper.quit();
+        mRequestQueue.stop();
+    }
+
+    private boolean hasNetwork() {
+        NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
+        return (info != null) && info.isConnected();
+    }
+}
diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk
index 96ed2e7..9083212 100644
--- a/packages/Keyguard/Android.mk
+++ b/packages/Keyguard/Android.mk
@@ -22,6 +22,8 @@
 
 LOCAL_CERTIFICATE := platform
 
+LOCAL_JAVA_LIBRARIES := SettingsLib
+
 LOCAL_PRIVILEGED_MODULE := true
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
@@ -30,4 +32,4 @@
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
-#include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+#include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/Keyguard/res/values-af/strings.xml b/packages/Keyguard/res/values-af/strings.xml
index e4b543b..c93f03b 100644
--- a/packages/Keyguard/res/values-af/strings.xml
+++ b/packages/Keyguard/res/values-af/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kode is aanvaar!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Geen diens nie."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knoppie vir wissel van invoermetode."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-am/strings.xml b/packages/Keyguard/res/values-am/strings.xml
index c54656e..248d12c 100644
--- a/packages/Keyguard/res/values-am/strings.xml
+++ b/packages/Keyguard/res/values-am/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"ኮዱ ተቀባይነት አግኝቷል!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"ከአገልግሎት መስጫ ክልል ውጪ።"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"የግቤት ስልት አዝራር ቀይር"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ar/strings.xml b/packages/Keyguard/res/values-ar/strings.xml
index 153f08e..92e5a96 100644
--- a/packages/Keyguard/res/values-ar/strings.xml
+++ b/packages/Keyguard/res/values-ar/strings.xml
@@ -117,4 +117,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"تم قبول الرمز!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"لا تتوفر خدمة"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"زر تبديل طريقة الإدخال."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-bg/strings.xml b/packages/Keyguard/res/values-bg/strings.xml
index 5dcb82c..c8d4391 100644
--- a/packages/Keyguard/res/values-bg/strings.xml
+++ b/packages/Keyguard/res/values-bg/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Кодът е приет!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Няма покритие."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Бутон за превключване на метода на въвеждане."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-bn-rBD/strings.xml b/packages/Keyguard/res/values-bn-rBD/strings.xml
index 2b13a07..dabe18d 100644
--- a/packages/Keyguard/res/values-bn-rBD/strings.xml
+++ b/packages/Keyguard/res/values-bn-rBD/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"কোড স্বীকৃত হয়েছে!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"কোনো পরিষেবা নেই৷"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ইনপুট পদ্ধতির বোতাম পরিবর্তন করুন৷"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ca/strings.xml b/packages/Keyguard/res/values-ca/strings.xml
index e675c7a..3af9f0a 100644
--- a/packages/Keyguard/res/values-ca/strings.xml
+++ b/packages/Keyguard/res/values-ca/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"S\'ha acceptat el codi."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Sense servei."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botó de canvi del mètode d\'entrada."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-cs/strings.xml b/packages/Keyguard/res/values-cs/strings.xml
index e1fa6f9..b3bae64 100644
--- a/packages/Keyguard/res/values-cs/strings.xml
+++ b/packages/Keyguard/res/values-cs/strings.xml
@@ -113,4 +113,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kód byl přijat."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Žádný signál."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačítko přepnutí metody zadávání"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml
index 77e8ce3..b330d16 100644
--- a/packages/Keyguard/res/values-da/strings.xml
+++ b/packages/Keyguard/res/values-da/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Koden blev accepteret."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen dækning."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Skift indtastningsmetode-knappen."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-de/strings.xml b/packages/Keyguard/res/values-de/strings.xml
index e21961d..d92acd5 100644
--- a/packages/Keyguard/res/values-de/strings.xml
+++ b/packages/Keyguard/res/values-de/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Code akzeptiert"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Kein Dienst"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Schaltfläche zum Ändern der Eingabemethode"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-el/strings.xml b/packages/Keyguard/res/values-el/strings.xml
index 7084c84..2a255a7 100644
--- a/packages/Keyguard/res/values-el/strings.xml
+++ b/packages/Keyguard/res/values-el/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Αποδεκτός κωδικός!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Καμία υπηρεσία."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Κουμπί εναλλαγής μεθόδου εισόδου"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-en-rAU/strings.xml b/packages/Keyguard/res/values-en-rAU/strings.xml
index ee5da13..55c33d9 100644
--- a/packages/Keyguard/res/values-en-rAU/strings.xml
+++ b/packages/Keyguard/res/values-en-rAU/strings.xml
@@ -109,4 +109,5 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepted"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"No service."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
+    <string name="airplane_mode" msgid="3122107900897202805">"Aeroplane mode"</string>
 </resources>
diff --git a/packages/Keyguard/res/values-en-rGB/strings.xml b/packages/Keyguard/res/values-en-rGB/strings.xml
index ee5da13..55c33d9 100644
--- a/packages/Keyguard/res/values-en-rGB/strings.xml
+++ b/packages/Keyguard/res/values-en-rGB/strings.xml
@@ -109,4 +109,5 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepted"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"No service."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
+    <string name="airplane_mode" msgid="3122107900897202805">"Aeroplane mode"</string>
 </resources>
diff --git a/packages/Keyguard/res/values-en-rIN/strings.xml b/packages/Keyguard/res/values-en-rIN/strings.xml
index ee5da13..55c33d9 100644
--- a/packages/Keyguard/res/values-en-rIN/strings.xml
+++ b/packages/Keyguard/res/values-en-rIN/strings.xml
@@ -109,4 +109,5 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepted"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"No service."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
+    <string name="airplane_mode" msgid="3122107900897202805">"Aeroplane mode"</string>
 </resources>
diff --git a/packages/Keyguard/res/values-es-rUS/strings.xml b/packages/Keyguard/res/values-es-rUS/strings.xml
index b34dd05..86da3b4 100644
--- a/packages/Keyguard/res/values-es-rUS/strings.xml
+++ b/packages/Keyguard/res/values-es-rUS/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceptado"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Sin servicio"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-es/strings.xml b/packages/Keyguard/res/values-es/strings.xml
index be3c113..0bc19c4 100644
--- a/packages/Keyguard/res/values-es/strings.xml
+++ b/packages/Keyguard/res/values-es/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceptado"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Sin servicio"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-et-rEE/strings.xml b/packages/Keyguard/res/values-et-rEE/strings.xml
index 402fc14..e4dc8f3 100644
--- a/packages/Keyguard/res/values-et-rEE/strings.xml
+++ b/packages/Keyguard/res/values-et-rEE/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kood on õige."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Teenus puudub."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Sisestusmeetodi vahetamise nupp."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-eu-rES/strings.xml b/packages/Keyguard/res/values-eu-rES/strings.xml
index 86850bb..7f5c0aa 100644
--- a/packages/Keyguard/res/values-eu-rES/strings.xml
+++ b/packages/Keyguard/res/values-eu-rES/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kodea onartu da!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Zerbitzurik gabe."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Idazketa-metodoa aldatzeko botoia."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-fa/strings.xml b/packages/Keyguard/res/values-fa/strings.xml
index 367c411..e2f349d 100644
--- a/packages/Keyguard/res/values-fa/strings.xml
+++ b/packages/Keyguard/res/values-fa/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"کد پذیرفته شد!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"خدماتی وجود ندارد."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"کلید تغییر روش ورود متن."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-fi/strings.xml b/packages/Keyguard/res/values-fi/strings.xml
index 68f7016..5153297 100644
--- a/packages/Keyguard/res/values-fi/strings.xml
+++ b/packages/Keyguard/res/values-fi/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Koodi hyväksytty!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Ei yhteyttä."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Syöttötavan vaihtopainike."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-fr-rCA/strings.xml b/packages/Keyguard/res/values-fr-rCA/strings.xml
index 2c24f7a..bfe02da 100644
--- a/packages/Keyguard/res/values-fr-rCA/strings.xml
+++ b/packages/Keyguard/res/values-fr-rCA/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepté"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Aucun service"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-fr/strings.xml b/packages/Keyguard/res/values-fr/strings.xml
index 77a2d06..1f7e5b8 100644
--- a/packages/Keyguard/res/values-fr/strings.xml
+++ b/packages/Keyguard/res/values-fr/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepté."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Aucun service"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-gl-rES/strings.xml b/packages/Keyguard/res/values-gl-rES/strings.xml
index 8e8f5c5..fc52bc5 100644
--- a/packages/Keyguard/res/values-gl-rES/strings.xml
+++ b/packages/Keyguard/res/values-gl-rES/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceptado"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Non hai servizo."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Cambiar o botón do método de entrada."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-hi/strings.xml b/packages/Keyguard/res/values-hi/strings.xml
index 0cd65b8..36573c8 100644
--- a/packages/Keyguard/res/values-hi/strings.xml
+++ b/packages/Keyguard/res/values-hi/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"कोड स्वीकार किया गया!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"कोई सेवा नहीं."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धति‍ बटन स्विच करें."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-hr/strings.xml b/packages/Keyguard/res/values-hr/strings.xml
index 71410c5..68e0dbc 100644
--- a/packages/Keyguard/res/values-hr/strings.xml
+++ b/packages/Keyguard/res/values-hr/strings.xml
@@ -111,4 +111,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kôd je prihvaćen!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Nema usluge."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za promjenu načina unosa."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-hu/strings.xml b/packages/Keyguard/res/values-hu/strings.xml
index dd43dba..538add3 100644
--- a/packages/Keyguard/res/values-hu/strings.xml
+++ b/packages/Keyguard/res/values-hu/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kód elfogadva."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Nincs szolgáltatás."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Beviteli mód váltása gomb."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-hy-rAM/strings.xml b/packages/Keyguard/res/values-hy-rAM/strings.xml
index e56642a..80c5512 100644
--- a/packages/Keyguard/res/values-hy-rAM/strings.xml
+++ b/packages/Keyguard/res/values-hy-rAM/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Կոդն ընդունվեց:"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Ծառայություն չկա:"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Միացնել մուտքագրման եղանակի կոճակը:"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-in/strings.xml b/packages/Keyguard/res/values-in/strings.xml
index 29a56ef..8963940 100644
--- a/packages/Keyguard/res/values-in/strings.xml
+++ b/packages/Keyguard/res/values-in/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kode Diterima!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Tidak ada layanan."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tombol beralih metode masukan."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-is-rIS/strings.xml b/packages/Keyguard/res/values-is-rIS/strings.xml
index 5741cd0..1054e60 100644
--- a/packages/Keyguard/res/values-is-rIS/strings.xml
+++ b/packages/Keyguard/res/values-is-rIS/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Númer samþykkt!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Ekkert símasamband."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Hnappur til að skipta um innsláttaraðferð."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-it/strings.xml b/packages/Keyguard/res/values-it/strings.xml
index c5c476c..8aed187 100644
--- a/packages/Keyguard/res/values-it/strings.xml
+++ b/packages/Keyguard/res/values-it/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Codice accettato."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Nessun servizio."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Pulsante per cambiare metodo di immissione."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-iw/strings.xml b/packages/Keyguard/res/values-iw/strings.xml
index a856ccb..8cb7888 100644
--- a/packages/Keyguard/res/values-iw/strings.xml
+++ b/packages/Keyguard/res/values-iw/strings.xml
@@ -113,4 +113,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"הקוד התקבל!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"אין קליטה."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"לחצן החלפת שיטת קלט."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ja/strings.xml b/packages/Keyguard/res/values-ja/strings.xml
index 5c76034..d3205d8 100644
--- a/packages/Keyguard/res/values-ja/strings.xml
+++ b/packages/Keyguard/res/values-ja/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"コードが承認されました。"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"通信サービスはありません。"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"入力方法の切り替えボタン。"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ka-rGE/strings.xml b/packages/Keyguard/res/values-ka-rGE/strings.xml
index e9c77fd..940a17e 100644
--- a/packages/Keyguard/res/values-ka-rGE/strings.xml
+++ b/packages/Keyguard/res/values-ka-rGE/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"კოდი მიღებულია!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"არ არის სერვისი."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"შეყვანის მეთოდის გადართვის ღილაკი."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-kk-rKZ/strings.xml b/packages/Keyguard/res/values-kk-rKZ/strings.xml
index 85443f6..587c87b 100644
--- a/packages/Keyguard/res/values-kk-rKZ/strings.xml
+++ b/packages/Keyguard/res/values-kk-rKZ/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Код қабылданды!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Қызмет көрсетілмейді."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Енгізу әдісі түймесін ауыстыру."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml
index be72fd6..1d14812 100644
--- a/packages/Keyguard/res/values-km-rKH/strings.xml
+++ b/packages/Keyguard/res/values-km-rKH/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"បាន​ទទួល​យក​លេខ​កូដ​!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"គ្មាន​សេវា​"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ប្ដូរ​ប៊ូតុង​វិធីសាស្ត្រ​បញ្ចូល។"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-kn-rIN/strings.xml b/packages/Keyguard/res/values-kn-rIN/strings.xml
index cfa1ac0..9afd36c 100644
--- a/packages/Keyguard/res/values-kn-rIN/strings.xml
+++ b/packages/Keyguard/res/values-kn-rIN/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"ಕೋಡ್ ಅಂಗೀಕೃತವಾಗಿದೆ!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"ಯಾವುದೇ ಸೇವೆಯಿಲ್ಲ."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ಇನ್‌ಪುಟ್ ವಿಧಾನ ಬದಲಿಸು ಬಟನ್."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ko/strings.xml b/packages/Keyguard/res/values-ko/strings.xml
index 1ef0c19..aa4a388 100644
--- a/packages/Keyguard/res/values-ko/strings.xml
+++ b/packages/Keyguard/res/values-ko/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"코드 승인 완료"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"서비스 불가"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"입력 방법 버튼을 전환합니다."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ky-rKG/strings.xml b/packages/Keyguard/res/values-ky-rKG/strings.xml
index 430c19a..0045a3c 100644
--- a/packages/Keyguard/res/values-ky-rKG/strings.xml
+++ b/packages/Keyguard/res/values-ky-rKG/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Код кабыл алынды!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Байланыш жок."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Киргизүү ыкмасын которуу баскычы."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-lo-rLA/strings.xml b/packages/Keyguard/res/values-lo-rLA/strings.xml
index 17c1c5b..a8a35e2 100644
--- a/packages/Keyguard/res/values-lo-rLA/strings.xml
+++ b/packages/Keyguard/res/values-lo-rLA/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"ລະ​ຫັດ​ຖືກຕອບຮັບແລ້ວ!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"ບໍ່ມີບໍລິການ"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ປຸ່ມສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-lt/strings.xml b/packages/Keyguard/res/values-lt/strings.xml
index 6d7dcc7..bafa7c3 100644
--- a/packages/Keyguard/res/values-lt/strings.xml
+++ b/packages/Keyguard/res/values-lt/strings.xml
@@ -113,4 +113,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kodas priimtas."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Nėra paslaugos."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Perjungti įvesties metodo mygtuką."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-lv/strings.xml b/packages/Keyguard/res/values-lv/strings.xml
index e1da889..5aee3c9 100644
--- a/packages/Keyguard/res/values-lv/strings.xml
+++ b/packages/Keyguard/res/values-lv/strings.xml
@@ -111,4 +111,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kods ir pieņemts!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Nav pakalpojuma."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ievades metodes maiņas poga."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-mk-rMK/strings.xml b/packages/Keyguard/res/values-mk-rMK/strings.xml
index 717671b..fc9be77 100644
--- a/packages/Keyguard/res/values-mk-rMK/strings.xml
+++ b/packages/Keyguard/res/values-mk-rMK/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Кодот е прифатен!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Нема услуга."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Копче за префрање метод на внес."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ml-rIN/strings.xml b/packages/Keyguard/res/values-ml-rIN/strings.xml
index f39a6b7..a63ce8e 100644
--- a/packages/Keyguard/res/values-ml-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ml-rIN/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"കോഡ് അംഗികരിച്ചു!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"സേവനമൊന്നുമില്ല."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ടൈപ്പുചെയ്യൽ രീതി ബട്ടൺ മാറുക."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-mn-rMN/strings.xml b/packages/Keyguard/res/values-mn-rMN/strings.xml
index 2f24901..713d3e6 100644
--- a/packages/Keyguard/res/values-mn-rMN/strings.xml
+++ b/packages/Keyguard/res/values-mn-rMN/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Код зөвшөөрөгдлөө!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Үйлчилгээ байхгүй."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Оруулах аргыг сэлгэх товч."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-mr-rIN/strings.xml b/packages/Keyguard/res/values-mr-rIN/strings.xml
index a86bf60..4206a45 100644
--- a/packages/Keyguard/res/values-mr-rIN/strings.xml
+++ b/packages/Keyguard/res/values-mr-rIN/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"कोड स्‍वीकारला!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"सेवा नाही."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धत स्‍विच करा बटण."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ms-rMY/strings.xml b/packages/Keyguard/res/values-ms-rMY/strings.xml
index 3d4dee4..f00db08 100644
--- a/packages/Keyguard/res/values-ms-rMY/strings.xml
+++ b/packages/Keyguard/res/values-ms-rMY/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kod Diterima!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Tiada perkhidmatan."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Butang tukar kaedah input."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-my-rMM/strings.xml b/packages/Keyguard/res/values-my-rMM/strings.xml
index 4432ceb..c9b0ff0 100644
--- a/packages/Keyguard/res/values-my-rMM/strings.xml
+++ b/packages/Keyguard/res/values-my-rMM/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"ကုဒ်နံပါတ်ကို လက်ခံလိုက်ပါသည်"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"ဆားဗစ် မရှိပါ"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ထည့်သွင်းခြင်းခလုတ်အား ပြောင်းခြင်း"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-nb/strings.xml b/packages/Keyguard/res/values-nb/strings.xml
index efc25cf..eab4d47 100644
--- a/packages/Keyguard/res/values-nb/strings.xml
+++ b/packages/Keyguard/res/values-nb/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Koden er godkjent."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen tjeneste."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bytt knapp for inndatametode."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ne-rNP/strings.xml b/packages/Keyguard/res/values-ne-rNP/strings.xml
index 7f6843a..8467729 100644
--- a/packages/Keyguard/res/values-ne-rNP/strings.xml
+++ b/packages/Keyguard/res/values-ne-rNP/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"कोड स्वीकृत!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"कुनै सेवा छैन।"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट विधि बटन स्विच गर्नुहोस्।"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-nl/strings.xml b/packages/Keyguard/res/values-nl/strings.xml
index 3a8d91c..f46c311 100644
--- a/packages/Keyguard/res/values-nl/strings.xml
+++ b/packages/Keyguard/res/values-nl/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Code geaccepteerd."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Geen service"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knop voor wijzigen invoermethode."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-pl/strings.xml b/packages/Keyguard/res/values-pl/strings.xml
index 40cd5e6..60c67ae 100644
--- a/packages/Keyguard/res/values-pl/strings.xml
+++ b/packages/Keyguard/res/values-pl/strings.xml
@@ -113,4 +113,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kod został zaakceptowany."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Brak usługi."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Przycisk przełączania metody wprowadzania."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-pt-rPT/strings.xml b/packages/Keyguard/res/values-pt-rPT/strings.xml
index 9068898..a9bcb0e 100644
--- a/packages/Keyguard/res/values-pt-rPT/strings.xml
+++ b/packages/Keyguard/res/values-pt-rPT/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceite!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Sem serviço."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alternar botão de método de introdução."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-pt/strings.xml b/packages/Keyguard/res/values-pt/strings.xml
index 690b693..3ed2b63 100644
--- a/packages/Keyguard/res/values-pt/strings.xml
+++ b/packages/Keyguard/res/values-pt/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceito."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Sem serviço."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alterar botão do método de entrada."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ro/strings.xml b/packages/Keyguard/res/values-ro/strings.xml
index 0c11689..eb4ab59 100644
--- a/packages/Keyguard/res/values-ro/strings.xml
+++ b/packages/Keyguard/res/values-ro/strings.xml
@@ -111,4 +111,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Cod acceptat!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Fără serviciu."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Buton pentru comutarea metodei de introducere."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ru/strings.xml b/packages/Keyguard/res/values-ru/strings.xml
index 48fd4f6..5f8dbd2 100644
--- a/packages/Keyguard/res/values-ru/strings.xml
+++ b/packages/Keyguard/res/values-ru/strings.xml
@@ -113,4 +113,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Код принят"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Нет сигнала."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка переключения способа ввода."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-si-rLK/strings.xml b/packages/Keyguard/res/values-si-rLK/strings.xml
index 740b0ea..e8e504d 100644
--- a/packages/Keyguard/res/values-si-rLK/strings.xml
+++ b/packages/Keyguard/res/values-si-rLK/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"කේතය පිළිගැණුනි!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"සේවාව නැත."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ආදාන ක්‍රමය මාරු කිරීමේ බොත්තම."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml
index 2fbe838..8990cfc 100644
--- a/packages/Keyguard/res/values-sk/strings.xml
+++ b/packages/Keyguard/res/values-sk/strings.xml
@@ -113,4 +113,5 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kód bol prijatý!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Žiadny signál"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačidlo prepnutia metódy vstupu."</string>
+    <string name="airplane_mode" msgid="3122107900897202805">"Režim v lietadle"</string>
 </resources>
diff --git a/packages/Keyguard/res/values-sl/strings.xml b/packages/Keyguard/res/values-sl/strings.xml
index a79d99a..900d9bb 100644
--- a/packages/Keyguard/res/values-sl/strings.xml
+++ b/packages/Keyguard/res/values-sl/strings.xml
@@ -113,4 +113,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Koda je sprejeta."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Ni storitve."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za preklop načina vnosa."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-sr/strings.xml b/packages/Keyguard/res/values-sr/strings.xml
index b7c439b..01f795e 100644
--- a/packages/Keyguard/res/values-sr/strings.xml
+++ b/packages/Keyguard/res/values-sr/strings.xml
@@ -111,4 +111,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Кôд је прихваћен!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Офлајн сте."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Дугме Промени метод уноса."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-sv/strings.xml b/packages/Keyguard/res/values-sv/strings.xml
index 75adc2c..c3c3b34 100644
--- a/packages/Keyguard/res/values-sv/strings.xml
+++ b/packages/Keyguard/res/values-sv/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Koden godkändes!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen tjänst."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knapp för byte av inmatningsmetod."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml
index 886c22e..98b2a6e 100644
--- a/packages/Keyguard/res/values-sw/strings.xml
+++ b/packages/Keyguard/res/values-sw/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Msimbo Umekubaliwa!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Hakuna huduma."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Swichi kitufe cha mbinu ingizi."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ta-rIN/strings.xml b/packages/Keyguard/res/values-ta-rIN/strings.xml
index 89c1480..233849a 100644
--- a/packages/Keyguard/res/values-ta-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ta-rIN/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"குறியீடு ஏற்கப்பட்டது!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"சேவை இல்லை."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"உள்ளீட்டு முறையை மாற்றும் பொத்தான்."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-te-rIN/strings.xml b/packages/Keyguard/res/values-te-rIN/strings.xml
index 2f51742..3b789d3 100644
--- a/packages/Keyguard/res/values-te-rIN/strings.xml
+++ b/packages/Keyguard/res/values-te-rIN/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"కోడ్ ఆమోదించబడింది!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"సేవ లేదు."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ఇన్‌పుట్ పద్ధతి మార్చే బటన్."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-th/strings.xml b/packages/Keyguard/res/values-th/strings.xml
index 6d0d026..5466c02 100644
--- a/packages/Keyguard/res/values-th/strings.xml
+++ b/packages/Keyguard/res/values-th/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"รหัสได้รับการยอมรับ!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"ไม่มีบริการ"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ปุ่มสลับวิธีการป้อนข้อมูล"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-tl/strings.xml b/packages/Keyguard/res/values-tl/strings.xml
index 8125efe..c2f13a6 100644
--- a/packages/Keyguard/res/values-tl/strings.xml
+++ b/packages/Keyguard/res/values-tl/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Tinanggap ang Code!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Walang serbisyo."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ilipat ang button na pamamaraan ng pag-input."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-tr/strings.xml b/packages/Keyguard/res/values-tr/strings.xml
index aa32baa..33479d9 100644
--- a/packages/Keyguard/res/values-tr/strings.xml
+++ b/packages/Keyguard/res/values-tr/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kod Kabul Edildi!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Hizmet yok."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Giriş yöntemini değiştirme düğmesi."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-uk/strings.xml b/packages/Keyguard/res/values-uk/strings.xml
index 9e52283..dd85582 100644
--- a/packages/Keyguard/res/values-uk/strings.xml
+++ b/packages/Keyguard/res/values-uk/strings.xml
@@ -113,4 +113,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Код прийнято."</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Зв’язку немає."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка перемикання методу введення."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-ur-rPK/strings.xml b/packages/Keyguard/res/values-ur-rPK/strings.xml
index 5cd54c0..ab3c229 100644
--- a/packages/Keyguard/res/values-ur-rPK/strings.xml
+++ b/packages/Keyguard/res/values-ur-rPK/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"کوڈ قبول کر لیا گیا!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"کوئی سروس نہیں ہے۔"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"اندراج کا طریقہ سوئچ کرنے کا بٹن۔"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-uz-rUZ/strings.xml b/packages/Keyguard/res/values-uz-rUZ/strings.xml
index a6852a7..0b83b9d 100644
--- a/packages/Keyguard/res/values-uz-rUZ/strings.xml
+++ b/packages/Keyguard/res/values-uz-rUZ/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Kod qabul qilindi!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Aloqa yo‘q."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Kiritish uslubi tugmasini almashtirish."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index 5727900..51adada 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Mã được chấp nhận!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Không có dịch vụ."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Nút chuyển phương thức nhập."</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml
index a93b54b..2e2e202 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"代码正确!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"无服务。"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"输入法切换按钮。"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-zh-rHK/strings.xml b/packages/Keyguard/res/values-zh-rHK/strings.xml
index 55a6a5e..716f8b7 100644
--- a/packages/Keyguard/res/values-zh-rHK/strings.xml
+++ b/packages/Keyguard/res/values-zh-rHK/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"密碼正確!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"沒有服務。"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-zh-rTW/strings.xml b/packages/Keyguard/res/values-zh-rTW/strings.xml
index 66c665f..a66cbfa 100644
--- a/packages/Keyguard/res/values-zh-rTW/strings.xml
+++ b/packages/Keyguard/res/values-zh-rTW/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"密碼正確!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"沒有服務。"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values-zu/strings.xml b/packages/Keyguard/res/values-zu/strings.xml
index be8900a..140c597 100644
--- a/packages/Keyguard/res/values-zu/strings.xml
+++ b/packages/Keyguard/res/values-zu/strings.xml
@@ -109,4 +109,6 @@
     <string name="kg_pin_accepted" msgid="1448241673570020097">"Ikhodi yamukelwe!"</string>
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Ayikho isevisi."</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Vula indlela yokungena yenkinobho"</string>
+    <!-- no translation found for airplane_mode (3122107900897202805) -->
+    <skip />
 </resources>
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index 5047330..9469ee7 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -300,4 +300,7 @@
     <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">Switch input method button.</string>
 
+    <!-- Description of airplane mode -->
+    <string name="airplane_mode">Airplane mode</string>
+
 </resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/CarrierText.java b/packages/Keyguard/src/com/android/keyguard/CarrierText.java
index 7d0b81d..4fbcc1e 100644
--- a/packages/Keyguard/src/com/android/keyguard/CarrierText.java
+++ b/packages/Keyguard/src/com/android/keyguard/CarrierText.java
@@ -35,6 +35,7 @@
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.IccCardConstants.State;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.settingslib.WirelessUtils;
 
 public class CarrierText extends TextView {
     private static final boolean DEBUG = KeyguardConstants.DEBUG;
@@ -146,6 +147,9 @@
                         getContext().getText(R.string.keyguard_missing_sim_message_short), text);
             }
         }
+        if (WirelessUtils.isAirplaneModeOn(mContext)) {
+            displayText = getContext().getString(R.string.airplane_mode);
+        }
         setText(displayText);
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 3627e3e..7d5bf6b 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -36,7 +36,10 @@
  * allows the user to return to the call.
  */
 public class EmergencyButton extends Button {
-    private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
+    private static final Intent INTENT_EMERGENCY_DIAL = new Intent()
+            .setAction("com.android.phone.EmergencyDialer.DIAL")
+            .setPackage("com.android.phone")
+            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
 
     KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
@@ -112,12 +115,9 @@
                 mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
             }
         } else {
-            final boolean bypassHandler = true;
-            KeyguardUpdateMonitor.getInstance(mContext).reportEmergencyCallAction(bypassHandler);
-            Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-            getContext().startActivityAsUser(intent,
+            KeyguardUpdateMonitor.getInstance(mContext).reportEmergencyCallAction(
+                    true /* bypassHandler */);
+            getContext().startActivityAsUser(INTENT_EMERGENCY_DIAL,
                     new UserHandle(mLockPatternUtils.getCurrentUser()));
         }
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 396fe4f..82dec30 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -40,6 +40,7 @@
 
 import android.media.AudioManager;
 import android.os.BatteryManager;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.IRemoteCallback;
 import android.os.Message;
@@ -51,9 +52,11 @@
 import com.android.internal.telephony.IccCardConstants.State;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
-import android.service.fingerprint.FingerprintManager;
-import android.service.fingerprint.FingerprintManagerReceiver;
-import android.service.fingerprint.FingerprintUtils;
+
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
+import android.hardware.fingerprint.FingerprintUtils;
+import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
@@ -109,10 +112,11 @@
     private static final int MSG_SCREEN_TURNED_ON = 319;
     private static final int MSG_SCREEN_TURNED_OFF = 320;
     private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322;
-    private static final int MSG_FINGERPRINT_PROCESSED = 323;
-    private static final int MSG_FINGERPRINT_ACQUIRED = 324;
-    private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 325;
-    private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 326;
+    private static final int MSG_FINGERPRINT_AUTHENTICATED = 323;
+    private static final int MSG_FINGERPRINT_ERROR = 324;
+    private static final int MSG_FINGERPRINT_HELP = 325;
+    private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 326;
+    private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 327;
 
     private static KeyguardUpdateMonitor sInstance;
 
@@ -201,11 +205,14 @@
                 case MSG_SCREEN_TURNED_ON:
                     handleScreenTurnedOn();
                     break;
-                case MSG_FINGERPRINT_ACQUIRED:
-                    handleFingerprintAcquired(msg.arg1);
+                case MSG_FINGERPRINT_AUTHENTICATED:
+                    handleFingerprintAuthenticated(msg.arg1, msg.arg2);
                     break;
-                case MSG_FINGERPRINT_PROCESSED:
-                    handleFingerprintProcessed(msg.arg1);
+                case MSG_FINGERPRINT_HELP:
+                    handleFingerprintHelp(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
+                    break;
+                case MSG_FINGERPRINT_ERROR:
+                    handleFingerprintError(msg.arg1 /* msgId */, (String) msg.obj /* errString */);
                     break;
                 case MSG_FACE_UNLOCK_STATE_CHANGED:
                     handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
@@ -227,7 +234,7 @@
 
     private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
     private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
-    private SparseBooleanArray mUserFingerprintRecognized = new SparseBooleanArray();
+    private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
     private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
 
     @Override
@@ -314,18 +321,18 @@
         }
     }
 
-    private void onFingerprintRecognized(int userId) {
-        mUserFingerprintRecognized.put(userId, true);
+    private void onFingerprintAuthenticated(int userId) {
+        mUserFingerprintAuthenticated.put(userId, true);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
-                cb.onFingerprintRecognized(userId);
+                cb.onFingerprintAuthenticated(userId);
             }
         }
     }
 
-    private void handleFingerprintProcessed(int fingerprintId) {
-        if (fingerprintId == 0) return; // not a valid fingerprint
+    private void handleFingerprintAuthenticated(int fingerId, int groupId) {
+        if (fingerId == 0) return; // not a valid fingerprint
 
         final int userId;
         try {
@@ -341,17 +348,28 @@
         final ContentResolver res = mContext.getContentResolver();
         final int ids[] = FingerprintUtils.getFingerprintIdsForUser(res, userId);
         for (int i = 0; i < ids.length; i++) {
-            if (ids[i] == fingerprintId) {
-                onFingerprintRecognized(userId);
+            // TODO: fix once HAL supports storing group id
+            final boolean isCorrectUser = true || (groupId == userId);
+            if (ids[i] == fingerId && isCorrectUser) {
+                onFingerprintAuthenticated(userId);
             }
         }
     }
 
-    private void handleFingerprintAcquired(int info) {
+    private void handleFingerprintHelp(int msgId, String helpString) {
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
-                cb.onFingerprintAcquired(info);
+                cb.onFingerprintHelp(msgId, helpString);
+            }
+        }
+    }
+
+    private void handleFingerprintError(int msgId, String errString) {
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onFingerprintError(msgId, errString);
             }
         }
     }
@@ -387,7 +405,7 @@
 
     public boolean getUserHasTrust(int userId) {
         return !isTrustDisabled(userId) && mUserHasTrust.get(userId)
-                || mUserFingerprintRecognized.get(userId);
+                || mUserFingerprintAuthenticated.get(userId);
     }
 
     public boolean getUserTrustIsManaged(int userId) {
@@ -464,23 +482,29 @@
             }
         }
     };
-    private FingerprintManagerReceiver mFingerprintManagerReceiver =
-            new FingerprintManagerReceiver() {
-        @Override
-        public void onProcessed(int fingerprintId) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_PROCESSED, fingerprintId, 0).sendToTarget();
-        };
+
+    private FingerprintManager.AuthenticationCallback mAuthenticationCallback
+            = new AuthenticationCallback() {
 
         @Override
-        public void onAcquired(int info) {
-            mHandler.obtainMessage(MSG_FINGERPRINT_ACQUIRED, info, 0).sendToTarget();
+        public void onAuthenticationSucceeded(AuthenticationResult result) {
+            mHandler.obtainMessage(MSG_FINGERPRINT_AUTHENTICATED,
+                    result.getFingerprint().getFingerId(),
+                    result.getFingerprint().getGroupId()).sendToTarget();
         }
 
         @Override
-        public void onError(int error) {
-            if (DEBUG) Log.w(TAG, "FingerprintManager reported error: " + error);
+        public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
+            mHandler.obtainMessage(MSG_FINGERPRINT_HELP, helpMsgId, 0, helpString).sendToTarget();
+        }
+
+        @Override
+        public void onAuthenticationError(int errMsgId, CharSequence errString) {
+            mHandler.obtainMessage(MSG_FINGERPRINT_ERROR, errMsgId, 0, errString);
         }
     };
+    private CancellationSignal mFingerprintCancelSignal;
+    private FingerprintManager mFpm;
 
     /**
      * When we receive a
@@ -606,6 +630,7 @@
                 cb.onScreenTurnedOn();
             }
         }
+        startListeningForFingerprint(mContext);
     }
 
     protected void handleScreenTurnedOff(int arg1) {
@@ -617,6 +642,7 @@
                 cb.onScreenTurnedOff(arg1);
             }
         }
+        stopListeningForFingerprint();
     }
 
     /**
@@ -705,9 +731,25 @@
         TrustManager trustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
         trustManager.registerTrustListener(this);
 
-        FingerprintManager fpm;
-        fpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
-        fpm.startListening(mFingerprintManagerReceiver);
+        mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
+        startListeningForFingerprint(context);
+    }
+
+    private void startListeningForFingerprint(Context context) {
+        if (mFpm != null && mFpm.isHardwareDetected()) {
+            if (mFingerprintCancelSignal == null) {
+                mFingerprintCancelSignal = new CancellationSignal();
+            } else {
+                mFingerprintCancelSignal.cancel();
+            }
+            mFpm.authenticate(null, mAuthenticationCallback, mFingerprintCancelSignal, 0);
+        }
+    }
+
+    private void stopListeningForFingerprint() {
+        if (mFingerprintCancelSignal != null) {
+            mFingerprintCancelSignal.cancel();
+        }
     }
 
     private boolean isDeviceProvisionedInSettingsDb() {
@@ -1152,7 +1194,7 @@
     }
 
     public void clearFingerprintRecognized() {
-        mUserFingerprintRecognized.clear();
+        mUserFingerprintAuthenticated.clear();
     }
 
     public void reportFailedUnlockAttempt() {
@@ -1239,7 +1281,7 @@
         mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
     }
 
-    public void dispatchScreenTurndOff(int why) {
+    public void dispatchScreenTurnedOff(int why) {
         synchronized(this) {
             mScreenOn = false;
         }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index f0e2389..8d2562d 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -19,6 +19,7 @@
 import android.graphics.Bitmap;
 import android.media.AudioManager;
 import android.os.SystemClock;
+import android.hardware.fingerprint.FingerprintManager;
 import android.telephony.TelephonyManager;
 import android.view.WindowManagerPolicy;
 
@@ -176,14 +177,24 @@
 
     /**
      * Called when a fingerprint is recognized.
-     * @param userId
+     * @param userId the user id for which the fingerprint was authenticated
      */
-    public void onFingerprintRecognized(int userId) { }
+    public void onFingerprintAuthenticated(int userId) { }
 
     /**
-     * Called when fingerprint is acquired but not yet recognized
+     * Called when fingerprint provides help string (e.g. "Try again")
+     * @param msgId
+     * @param helpString
      */
-    public void onFingerprintAcquired(int info) { }
+    public void onFingerprintHelp(int msgId, String helpString) { }
+
+    /**
+     * Called when fingerprint provides an semi-permanent error message
+     * (e.g. "Hardware not available").
+     * @param msgId one of the error messages listed in {@link FingerprintManager}
+     * @param errString
+     */
+    public void onFingerprintError(int msgId, String errString) { }
 
     /**
      * Called when the state of face unlock changed.
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 5d8c3c6..13d5543 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -69,7 +69,7 @@
       <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> प्रिंट कार्य</item>
       <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> प्रिंट कार्य</item>
     </plurals>
-    <string name="cancel" msgid="4373674107267141885">"रहने दें"</string>
+    <string name="cancel" msgid="4373674107267141885">"अभी नहीं"</string>
     <string name="restart" msgid="2472034227037808749">"पुन: आरंभ करें"</string>
     <string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिंटर के लिए कोई कनेक्शन नहीं"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"अज्ञात"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
old mode 100755
new mode 100644
index e1cb878..dd2368f
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -104,6 +104,7 @@
 
     // See mConnectAttempted
     private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000;
+    private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000;
 
     /** Auto-connect after pairing only if locally initiated. */
     private boolean mConnectAfterPairing;
@@ -525,19 +526,25 @@
      */
     void onUuidChanged() {
         updateProfiles();
+        ParcelUuid[] uuids = mDevice.getUuids();
+
+        long timeout = MAX_UUID_DELAY_FOR_AUTO_CONNECT;
+        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) {
+            timeout = MAX_HOGP_DELAY_FOR_AUTO_CONNECT;
+        }
 
         if (DEBUG) {
-            Log.e(TAG, "onUuidChanged: Time since last connect"
+            Log.d(TAG, "onUuidChanged: Time since last connect"
                     + (SystemClock.elapsedRealtime() - mConnectAttempted));
         }
 
         /*
-         * If a connect was attempted earlier without any UUID, we will do the
-         * connect now.
+         * If a connect was attempted earlier without any UUID, we will do the connect now.
+         * Otherwise, allow the connect on UUID change.
          */
         if (!mProfiles.isEmpty()
-                && (mConnectAttempted + MAX_UUID_DELAY_FOR_AUTO_CONNECT) > SystemClock
-                        .elapsedRealtime()) {
+                && ((mConnectAttempted + timeout) > SystemClock.elapsedRealtime()
+                || (mConnectAttempted == 0))) {
             connectWithoutResettingTimer(false);
         }
         dispatchAttributesChanged();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 729efcb..0b6ab99 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -61,10 +61,18 @@
 import java.util.Set;
 
 /**
- * Database helper class for {@link SettingsProvider}.
- * Mostly just has a bit {@link #onCreate} to initialize the database.
+ * Legacy settings database helper class for {@link SettingsProvider}.
+ *
+ * IMPORTANT: Do not add any more upgrade steps here as the global,
+ * secure, and system settings are no longer stored in a database
+ * but are kept in memory and persisted to XML.
+ *
+ * See: SettingsProvider.UpgradeController#onUpgradeLocked
+ *
+ * @deprecated The implementation is frozen.  Do not add any new code to this class!
  */
-public class DatabaseHelper extends SQLiteOpenHelper {
+@Deprecated
+class DatabaseHelper extends SQLiteOpenHelper {
     private static final String TAG = "SettingsProvider";
     private static final String DATABASE_NAME = "settings.db";
 
@@ -1932,19 +1940,14 @@
             upgradeVersion = 118;
         }
 
-        /**
+        /*
          * IMPORTANT: Do not add any more upgrade steps here as the global,
          * secure, and system settings are no longer stored in a database
-         * but are kept in memory and persisted to XML. The correct places
-         * for adding upgrade steps are:
+         * but are kept in memory and persisted to XML.
          *
-         * Global: SettingsProvider.UpgradeController#onUpgradeGlobalSettings
-         * Secure: SettingsProvider.UpgradeController#onUpgradeSecureSettings
-         * System: SettingsProvider.UpgradeController#onUpgradeSystemSettings
+         * See: SettingsProvider.UpgradeController#onUpgradeLocked
          */
 
-        // *** Remember to update DATABASE_VERSION above!
-
         if (upgradeVersion != currentVersion) {
             recreateDatabase(db, oldVersion, upgradeVersion, currentVersion);
         }
@@ -2386,6 +2389,14 @@
 
             loadIntegerSetting(stmt, Settings.System.POINTER_SPEED,
                     R.integer.def_pointer_speed);
+
+            /*
+             * IMPORTANT: Do not add any more upgrade steps here as the global,
+             * secure, and system settings are no longer stored in a database
+             * but are kept in memory and persisted to XML.
+             *
+             * See: SettingsProvider.UpgradeController#onUpgradeLocked
+             */
         } finally {
             if (stmt != null) stmt.close();
         }
@@ -2517,6 +2528,14 @@
 
             loadIntegerSetting(stmt, Settings.Secure.SLEEP_TIMEOUT,
                     R.integer.def_sleep_timeout);
+
+            /*
+             * IMPORTANT: Do not add any more upgrade steps here as the global,
+             * secure, and system settings are no longer stored in a database
+             * but are kept in memory and persisted to XML.
+             *
+             * See: SettingsProvider.UpgradeController#onUpgradeLocked
+             */
         } finally {
             if (stmt != null) stmt.close();
         }
@@ -2693,7 +2712,14 @@
                     R.bool.def_guest_user_enabled);
             loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED,
                     ImsConfig.FeatureValueConstants.ON);
-            // --- New global settings start here
+
+            /*
+             * IMPORTANT: Do not add any more upgrade steps here as the global,
+             * secure, and system settings are no longer stored in a database
+             * but are kept in memory and persisted to XML.
+             *
+             * See: SettingsProvider.UpgradeController#onUpgradeLocked
+             */
         } finally {
             if (stmt != null) stmt.close();
         }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 2c63647..0d61606 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1502,15 +1502,15 @@
         public void onPackageRemovedLocked(String packageName, int userId) {
             final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
             SettingsState globalSettings = mSettingsStates.get(globalKey);
-            globalSettings.onPackageRemovedLocked(packageName);
+            if (globalSettings != null) globalSettings.onPackageRemovedLocked(packageName);
 
             final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
             SettingsState secureSettings = mSettingsStates.get(secureKey);
-            secureSettings.onPackageRemovedLocked(packageName);
+            if (secureSettings != null) secureSettings.onPackageRemovedLocked(packageName);
 
             final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
             SettingsState systemSettings = mSettingsStates.get(systemKey);
-            systemSettings.onPackageRemovedLocked(packageName);
+            if (systemSettings != null) systemSettings.onPackageRemovedLocked(packageName);
         }
 
         private SettingsState peekSettingsStateLocked(int key) {
@@ -1806,7 +1806,7 @@
                 final int oldVersion = secureSettings.getVersionLocked();
                 final int newVersion = SETTINGS_VERSION;
 
-                // If up do data - done.
+                // If up do date - done.
                 if (oldVersion == newVersion) {
                     return;
                 }
@@ -1859,40 +1859,43 @@
                 return getSettingsLocked(SETTINGS_TYPE_SYSTEM, userId);
             }
 
+            /**
+             * You must perform all necessary mutations to bring the settings
+             * for this user from the old to the new version. When you add a new
+             * upgrade step you *must* update SETTINGS_VERSION.
+             *
+             * This is an example of moving a setting from secure to global.
+             *
+             * // v119: Example settings changes.
+             * if (currentVersion == 118) {
+             *     if (userId == UserHandle.USER_OWNER) {
+             *         // Remove from the secure settings.
+             *         SettingsState secureSettings = getSecureSettingsLocked(userId);
+             *         String name = "example_setting_to_move";
+             *         String value = secureSettings.getSetting(name);
+             *         secureSettings.deleteSetting(name);
+             *
+             *         // Add to the global settings.
+             *         SettingsState globalSettings = getGlobalSettingsLocked();
+             *         globalSettings.insertSetting(name, value, SettingsState.SYSTEM_PACKAGE_NAME);
+             *     }
+             *
+             *     // Update the current version.
+             *     currentVersion = 119;
+             * }
+             */
             private int onUpgradeLocked(int userId, int oldVersion, int newVersion) {
                 if (DEBUG) {
                     Slog.w(LOG_TAG, "Upgrading settings for user: " + userId + " from version: "
                             + oldVersion + " to version: " + newVersion);
                 }
 
-                // You must perform all necessary mutations to bring the settings
-                // for this user from the old to the new version. When you add a new
-                // upgrade step you *must* update SETTINGS_VERSION.
+                int currentVersion = oldVersion;
 
-                /**
-                 * This is an example of moving a setting from secure to global.
-                 *
-                 * int currentVersion = oldVersion;
-                 * if (currentVersion == 118) {
-                 *     // Remove from the secure settings.
-                 *     SettingsState secureSettings = getSecureSettingsLocked(userId);
-                 *     String name = "example_setting_to_move";
-                 *     String value = secureSettings.getSetting(name);
-                 *     secureSettings.deleteSetting(name);
-                 *
-                 *     // Add to the global settings.
-                 *     SettingsState globalSettings = getGlobalSettingsLocked();
-                 *     globalSettings.insertSetting(name, value, SettingsState.SYSTEM_PACKAGE_NAME);
-                 *
-                 *     // Update the current version.
-                 *     currentVersion = 119;
-                 * }
-                 *
-                 * // Return the current version.
-                 * return currentVersion;
-                 */
+                // vXXX: Add new settings above this point.
 
-                return SettingsState.VERSION_UNDEFINED;
+                // Return the current version.
+                return currentVersion;
             }
         }
     }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 3bf6828..c7092b3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -416,78 +416,48 @@
 
     private void parseStateLocked(XmlPullParser parser)
             throws IOException, XmlPullParserException {
-        parser.next();
-        skipEmptyTextTags(parser);
-        expect(parser, XmlPullParser.START_TAG, TAG_SETTINGS);
+        final int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals(TAG_SETTINGS)) {
+                parseSettingsLocked(parser);
+            }
+        }
+    }
+
+    private void parseSettingsLocked(XmlPullParser parser)
+            throws IOException, XmlPullParserException {
 
         mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTR_VERSION));
 
-        parser.next();
-
-        while (parseSettingLocked(parser)) {
-            parser.next();
-        }
-
-        skipEmptyTextTags(parser);
-        expect(parser, XmlPullParser.END_TAG, TAG_SETTINGS);
-    }
-
-    private boolean parseSettingLocked(XmlPullParser parser)
-            throws IOException, XmlPullParserException {
-        skipEmptyTextTags(parser);
-        if (!accept(parser, XmlPullParser.START_TAG, TAG_SETTING)) {
-            return false;
-        }
-
-        String id = parser.getAttributeValue(null, ATTR_ID);
-        String name = parser.getAttributeValue(null, ATTR_NAME);
-        String value = parser.getAttributeValue(null, ATTR_VALUE);
-        String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
-        mSettings.put(name, new Setting(name, unpackValue(value),
-                unpackValue(packageName), id));
-
-        if (DEBUG_PERSISTENCE) {
-            Slog.i(LOG_TAG, "[RESTORED] " + name + "=" + value);
-        }
-
-        parser.next();
-
-        skipEmptyTextTags(parser);
-        expect(parser, XmlPullParser.END_TAG, TAG_SETTING);
-
-        return true;
-    }
-
-    private void expect(XmlPullParser parser, int type, String tag)
-            throws IOException, XmlPullParserException {
-        if (!accept(parser, type, tag)) {
-            throw new XmlPullParserException("Expected event: " + type
-                    + " and tag: " + tag + " but got event: " + parser.getEventType()
-                    + " and tag:" + parser.getName());
-        }
-    }
-
-    private void skipEmptyTextTags(XmlPullParser parser)
-            throws IOException, XmlPullParserException {
-        while (accept(parser, XmlPullParser.TEXT, null)
-                && parser.isWhitespace()) {
-            parser.next();
-        }
-    }
-
-    private boolean accept(XmlPullParser parser, int type, String tag)
-            throws IOException, XmlPullParserException {
-        if (parser.getEventType() != type) {
-            return false;
-        }
-        if (tag != null) {
-            if (!tag.equals(parser.getName())) {
-                return false;
+        final int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
             }
-        } else if (parser.getName() != null) {
-            return false;
+
+            String tagName = parser.getName();
+            if (tagName.equals(TAG_SETTING)) {
+                String id = parser.getAttributeValue(null, ATTR_ID);
+                String name = parser.getAttributeValue(null, ATTR_NAME);
+                String value = parser.getAttributeValue(null, ATTR_VALUE);
+                String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+                mSettings.put(name, new Setting(name, unpackValue(value),
+                        unpackValue(packageName), id));
+
+                if (DEBUG_PERSISTENCE) {
+                    Slog.i(LOG_TAG, "[RESTORED] " + name + "=" + value);
+                }
+            }
         }
-        return true;
     }
 
     private final class MyHandler extends Handler {
diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java
index 0485334..0f8ccd7 100644
--- a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java
+++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java
@@ -17,8 +17,8 @@
 package com.android.sharedstoragebackup;
 
 import android.app.Service;
-import android.app.backup.BackupDataOutput;
 import android.app.backup.FullBackup;
+import android.app.backup.FullBackupDataOutput;
 import android.app.backup.IBackupManager;
 import android.content.Intent;
 import android.os.Environment;
@@ -67,7 +67,7 @@
                                 Log.i(TAG, obbList.size() + " files to back up");
                             }
                             final String rootPath = obbDir.getCanonicalPath();
-                            final BackupDataOutput out = new BackupDataOutput(outFd);
+                            final FullBackupDataOutput out = new FullBackupDataOutput(data);
                             for (File f : obbList) {
                                 final String filePath = f.getCanonicalPath();
                                 if (DEBUG) {
@@ -92,7 +92,7 @@
                 }
 
                 try {
-                    callbackBinder.opComplete(token);
+                    callbackBinder.opComplete(token, 0);
                 } catch (RemoteException e) {
                 }
             }
@@ -119,7 +119,7 @@
                 Log.i(TAG, "Exception restoring OBB " + path, e);
             } finally {
                 try {
-                    callbackBinder.opComplete(token);
+                    callbackBinder.opComplete(token, 0);
                 } catch (RemoteException e) {
                 }
             }
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 3c44245..9d16501 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -105,6 +105,18 @@
                 android:resource="@xml/file_provider_paths" />
         </provider>
 
+        <provider
+            android:name=".BugreportStorageProvider"
+            android:authorities="com.android.shell.documents"
+            android:grantUriPermissions="true"
+            android:exported="true"
+            android:permission="android.permission.MANAGE_DOCUMENTS"
+            android:enabled="false">
+            <intent-filter>
+                <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
+            </intent-filter>
+        </provider>
+
         <activity
             android:name=".BugreportWarningActivity"
             android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
diff --git a/packages/Shell/res/values-af/strings.xml b/packages/Shell/res/values-af/strings.xml
index 8c4f75f..43beb57 100644
--- a/packages/Shell/res/values-af/strings.xml
+++ b/packages/Shell/res/values-af/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Raak om jou foutverslag te deel"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Foutverslae bevat data van die stelsel se verskillende loglêers af, insluitend persoonlike en private inligting. Deel foutverslae net met programme en mense wat jy vertrou."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Wys hierdie boodskap volgende keer"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Foutverslae"</string>
 </resources>
diff --git a/packages/Shell/res/values-am/strings.xml b/packages/Shell/res/values-am/strings.xml
index af84a09..e86ecf8 100644
--- a/packages/Shell/res/values-am/strings.xml
+++ b/packages/Shell/res/values-am/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"የሳንካ ሪፖርትዎን ለማጋራት ይንክኩ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"የሳንካ ሪፖርቶች የግል መረጃን ጨምሮ ከበርካታ የስርዓቱ ምዝግብ ማስታወሻዎች የመጣ ውሂብን ይዟል። የሳንካ ሪፖርቶች ለሚያምኗቸው መተግበሪያዎችን እና ሰዎችን ብቻ ያጋሩ።"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ይህን መልዕክት በሚቀጥለው ጊዜ አሳይ"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"የሳንካ ሪፖርቶች"</string>
 </resources>
diff --git a/packages/Shell/res/values-ar/strings.xml b/packages/Shell/res/values-ar/strings.xml
index 69d7d3f..0fcf019 100644
--- a/packages/Shell/res/values-ar/strings.xml
+++ b/packages/Shell/res/values-ar/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"المس لمشاركة تقرير الأخطاء"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"تحتوي تقارير الأخطاء على بيانات من ملفات سجلات النظام المتنوعة، بما في ذلك معلومات شخصية وخاصة. لا تشارك تقارير الأخطاء إلا مع التطبيقات والأشخاص الموثوق بهم."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"إظهار هذه الرسالة في المرة القادمة"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"تقارير الأخطاء"</string>
 </resources>
diff --git a/packages/Shell/res/values-bg/strings.xml b/packages/Shell/res/values-bg/strings.xml
index f7ae49c..2d779b6 100644
--- a/packages/Shell/res/values-bg/strings.xml
+++ b/packages/Shell/res/values-bg/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Докоснете, за да споделите отчета си за програмни грешки"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Отчетите за програмни грешки съдържат данни от различни регистрационни файлове на системата, включително лична и поверителна информация. Споделяйте ги само с приложения и хора, на които имате доверие."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Това съобщение да се показва следващия път"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Отчети за програмни грешки"</string>
 </resources>
diff --git a/packages/Shell/res/values-bn-rBD/strings.xml b/packages/Shell/res/values-bn-rBD/strings.xml
index 5e8cec4..76da84b 100644
--- a/packages/Shell/res/values-bn-rBD/strings.xml
+++ b/packages/Shell/res/values-bn-rBD/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"আপনার ত্রুটির প্রতিবেদন ভাগ করতে স্পর্শ করুন"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ত্রুটির প্রতিবেদনগুলিতে থাকা ডেটা, সিস্টেমের বিভিন্ন লগ ফাইলগুলি থেকে আসে, যাতে ব্যক্তিগত এবং গোপনীয় তথ্য অন্তর্ভুক্ত থাকে৷ আপনি বিশ্বাস করেন শুধুমাত্র এমন অ্যাপ্লিকেশান এবং ব্যক্তিদের সাথে ত্রুটির প্রতিবেদনগুলি ভাগ করুন৷"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"এই বার্তাটি পরের বার দেখান"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"ত্রুটির প্রতিবেদনগুলি"</string>
 </resources>
diff --git a/packages/Shell/res/values-ca/strings.xml b/packages/Shell/res/values-ca/strings.xml
index fa4d1f3..327fdc2 100644
--- a/packages/Shell/res/values-ca/strings.xml
+++ b/packages/Shell/res/values-ca/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toca aquí per compartir el teu informe d\'error."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Els informes d\'error contenen dades dels diferents fitxers de registre del sistema, inclosa informació privada i personal. Comparteix els informes d\'error només amb les aplicacions i amb les persones en qui confies."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostra aquest missatge la propera vegada"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes d\'error"</string>
 </resources>
diff --git a/packages/Shell/res/values-cs/strings.xml b/packages/Shell/res/values-cs/strings.xml
index d321159..3e36c6f 100644
--- a/packages/Shell/res/values-cs/strings.xml
+++ b/packages/Shell/res/values-cs/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Chybové hlášení můžete sdílet klepnutím."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Chybová hlášení obsahují data z různých souborů protokolů systému včetně osobních a soukromých informací. Chybová hlášení sdílejte pouze s aplikacemi a uživateli, kterým důvěřujete."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobrazit tuto zprávu příště"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Zprávy o chybách"</string>
 </resources>
diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml
index 3e58bc2..8925b85 100644
--- a/packages/Shell/res/values-da/strings.xml
+++ b/packages/Shell/res/values-da/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Tryk for at dele din fejlrapport"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Fejlrapporter indeholder data fra systemets forskellige logfiler, f.eks. personlige og private oplysninger. Del kun fejlrapporter med apps og personer, du har tillid til."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Vis denne underretning næste gang"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Fejlrapporter"</string>
 </resources>
diff --git a/packages/Shell/res/values-de/strings.xml b/packages/Shell/res/values-de/strings.xml
index f7387ff..19d58fe 100644
--- a/packages/Shell/res/values-de/strings.xml
+++ b/packages/Shell/res/values-de/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Tippen, um Fehlerbericht zu teilen"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Fehlerberichte enthalten Daten aus verschiedenen Protokolldateien des Systems, darunter auch personenbezogene und private Daten. Teilen Sie Fehlerberichte nur mit Apps und Personen, denen Sie vertrauen."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Diese Nachricht nächstes Mal zeigen"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Fehlerberichte"</string>
 </resources>
diff --git a/packages/Shell/res/values-el/strings.xml b/packages/Shell/res/values-el/strings.xml
index 529b420..5fadaa4 100644
--- a/packages/Shell/res/values-el/strings.xml
+++ b/packages/Shell/res/values-el/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Αγγίξτε για να μοιραστείτε τη αναφορά σφαλμάτων"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Οι αναφορές σφαλμάτων περιέχουν δεδομένα από τα διάφορα αρχεία καταγραφής του συστήματος, συμπεριλαμβανομένων προσωπικών και ιδιωτικών πληροφοριών. Να μοιράζεστε αναφορές σφαλμάτων μόνο με εφαρμογές και άτομα που εμπιστεύεστε."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Εμφάνιση αυτού του μηνύματος την επόμενη φορά"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Αναφορές σφαλμάτων"</string>
 </resources>
diff --git a/packages/Shell/res/values-en-rAU/strings.xml b/packages/Shell/res/values-en-rAU/strings.xml
index fab4223..b50fc2a 100644
--- a/packages/Shell/res/values-en-rAU/strings.xml
+++ b/packages/Shell/res/values-en-rAU/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Touch to share your bug report"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Bug reports"</string>
 </resources>
diff --git a/packages/Shell/res/values-en-rGB/strings.xml b/packages/Shell/res/values-en-rGB/strings.xml
index fab4223..b50fc2a 100644
--- a/packages/Shell/res/values-en-rGB/strings.xml
+++ b/packages/Shell/res/values-en-rGB/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Touch to share your bug report"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Bug reports"</string>
 </resources>
diff --git a/packages/Shell/res/values-en-rIN/strings.xml b/packages/Shell/res/values-en-rIN/strings.xml
index fab4223..b50fc2a 100644
--- a/packages/Shell/res/values-en-rIN/strings.xml
+++ b/packages/Shell/res/values-en-rIN/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Touch to share your bug report"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Bug reports"</string>
 </resources>
diff --git a/packages/Shell/res/values-es-rUS/strings.xml b/packages/Shell/res/values-es-rUS/strings.xml
index d01561c..06edfdc 100644
--- a/packages/Shell/res/values-es-rUS/strings.xml
+++ b/packages/Shell/res/values-es-rUS/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toca para compartir tu informe de errores."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Los informes de errores contienen datos de los distintos archivos de registro del sistema, incluida la información personal y privada. Comparte los informes de errores únicamente con aplicaciones y personas en las que confíes."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar este mensaje la próxima vez"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de errores"</string>
 </resources>
diff --git a/packages/Shell/res/values-es/strings.xml b/packages/Shell/res/values-es/strings.xml
index 19bfc25..3398ca3 100644
--- a/packages/Shell/res/values-es/strings.xml
+++ b/packages/Shell/res/values-es/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toca para compartir tu informe de error"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Los informes de errores contienen datos de los distintos archivos de registro del sistema, incluida información personal y privada. Comparte los informes de errores únicamente con aplicaciones y usuarios en los que confíes."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar este mensaje la próxima vez"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de error"</string>
 </resources>
diff --git a/packages/Shell/res/values-et-rEE/strings.xml b/packages/Shell/res/values-et-rEE/strings.xml
index 7de367d..549ee26 100644
--- a/packages/Shell/res/values-et-rEE/strings.xml
+++ b/packages/Shell/res/values-et-rEE/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Veaaruande jagamiseks puudutage"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Veaaruanded sisaldavad andmeid erinevatest süsteemi logifailidest, sh isiklikku ja privaatset teavet. Jagage veaaruandeid ainult usaldusväärsete rakenduste ja inimestega."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Kuva see sõnum järgmisel korral"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Veaaruanded"</string>
 </resources>
diff --git a/packages/Shell/res/values-eu-rES/strings.xml b/packages/Shell/res/values-eu-rES/strings.xml
index 0c42cab..048ab8e 100644
--- a/packages/Shell/res/values-eu-rES/strings.xml
+++ b/packages/Shell/res/values-eu-rES/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Akatsen txostena partekatzeko, ukitu"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Akatsen txostenek sistemaren erregistro-fitxategietako datuak dauzkate, informazio pertsonala eta pribatua barne. Akatsen txostenak partekatzen badituzu, partekatu soilik aplikazio eta pertsona fidagarriekin."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Erakutsi mezu hau hurrengoan"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Akatsen txostenak"</string>
 </resources>
diff --git a/packages/Shell/res/values-fa/strings.xml b/packages/Shell/res/values-fa/strings.xml
index a737a77..f42ba81 100644
--- a/packages/Shell/res/values-fa/strings.xml
+++ b/packages/Shell/res/values-fa/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"جهت اشتراک‌گذاری گزارش اشکال خود لمس کنید"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"گزارش‌های اشکال حاوی داده‌هایی از فایل‌های گزارش مختلف در سیستم هستند، شامل اطلاعات شخصی و خصوصی. گزارش‌های اشکال را فقط با افراد و برنامه‌های مورد اعتماد خود به اشتراک بگذارید."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"دفعه بعد این پیام نشان داده شود"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"گزارش اشکال"</string>
 </resources>
diff --git a/packages/Shell/res/values-fi/strings.xml b/packages/Shell/res/values-fi/strings.xml
index 247cb6f..26003b3 100644
--- a/packages/Shell/res/values-fi/strings.xml
+++ b/packages/Shell/res/values-fi/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Jaa virheraportti koskettamalla tätä"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Virheraportit sisältävät järjestelmän lokitietoja, ja niihin voi sisältyä henkilökohtaisia ja yksityisiä tietoja. Jaa virheraportteja vain luotettaville sovelluksille ja käyttäjille."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Näytä tämä viesti seuraavalla kerralla"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Virheraportit"</string>
 </resources>
diff --git a/packages/Shell/res/values-fr-rCA/strings.xml b/packages/Shell/res/values-fr-rCA/strings.xml
index d82ec95..b4b81ec 100644
--- a/packages/Shell/res/values-fr-rCA/strings.xml
+++ b/packages/Shell/res/values-fr-rCA/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Appuyer ici pour partager votre rapport de bogue"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bogue contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bogue qu\'avec les applications et les personnes que vous estimez fiables."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapports de bogues"</string>
 </resources>
diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml
index c52dd8d..e801054 100644
--- a/packages/Shell/res/values-fr/strings.xml
+++ b/packages/Shell/res/values-fr/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Appuyez ici pour partager le rapport de bug"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bug contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bug qu\'avec les applications et les personnes que vous estimez fiables."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapports d\'erreur"</string>
 </resources>
diff --git a/packages/Shell/res/values-gl-rES/strings.xml b/packages/Shell/res/values-gl-rES/strings.xml
index 8d01a8b..5690c9e 100644
--- a/packages/Shell/res/values-gl-rES/strings.xml
+++ b/packages/Shell/res/values-gl-rES/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toca aquí para compartir o teu informe de erros"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os informes de erros conteñen datos dos distintos ficheiros de rexistro do sistema, incluída información persoal e privada. Comparte os informes de erros unicamente con aplicacións e persoas de confianza."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensaxe a próxima vez"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de erros"</string>
 </resources>
diff --git a/packages/Shell/res/values-hi/strings.xml b/packages/Shell/res/values-hi/strings.xml
index daf6553..aee1121 100644
--- a/packages/Shell/res/values-hi/strings.xml
+++ b/packages/Shell/res/values-hi/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"अपनी बग रिपोर्ट साझा करने के लिए स्पर्श करें"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"बग रिपोर्ट में व्यक्तिगत और निजी जानकारी सहित, सिस्टम की विभिन्न लॉग फ़ाइलों का डेटा होता है. बग रिपोर्ट केवल विश्वसनीय ऐप्स  और व्यक्तियों से ही साझा करें."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"यह संदेश अगली बार दिखाएं"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रिपोर्ट"</string>
 </resources>
diff --git a/packages/Shell/res/values-hr/strings.xml b/packages/Shell/res/values-hr/strings.xml
index da01dd8..cf122ab 100644
--- a/packages/Shell/res/values-hr/strings.xml
+++ b/packages/Shell/res/values-hr/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Dodirnite za dijeljenje prijave programske pogreške"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Prijave programskih pogrešaka sadržavaju podatke iz različitih datoteka zapisnika sustava, uključujući osobne i privatne informacije. Prijave programskih pogrešaka dijelite samo s aplikacijama i osobama koje smatrate pouzdanima."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Prikaži tu poruku sljedeći put"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Izvješća o programskim pogreškama"</string>
 </resources>
diff --git a/packages/Shell/res/values-hu/strings.xml b/packages/Shell/res/values-hu/strings.xml
index 0ebdc3d..f0bc227 100644
--- a/packages/Shell/res/values-hu/strings.xml
+++ b/packages/Shell/res/values-hu/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Érintse meg a programhiba-jelentés megosztásához"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"A programhiba-jelentések a rendszer különféle naplófájljaiból származó adatokat tartalmaznak, köztük személyes és magánjellegű információkat is. Csak olyan alkalmazásokkal és személyekkel osszon meg programhiba-jelentéseket, amelyekben vagy akikben megbízik."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Üzenet mutatása legközelebb"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Hibajelentések"</string>
 </resources>
diff --git a/packages/Shell/res/values-hy-rAM/strings.xml b/packages/Shell/res/values-hy-rAM/strings.xml
index 80b1ccb..a254192 100644
--- a/packages/Shell/res/values-hy-rAM/strings.xml
+++ b/packages/Shell/res/values-hy-rAM/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Հպեք` ձեր վրիպակի մասին զեկույցը տարածելու համար"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Վրիպակի զեկույցները պարունակում են տվյալներ համակարգի տարբեր մուտքի ֆայլերից, այդ թվում նաև անհատական ​​և գաղտնի տեղեկություններ: Վրիպակի զեկույցները կիսեք միայն այն հավելվածների և մարդկանց հետ, որոնց վստահում եք:"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Այս հաղորդագրությունը ցույց տալ հաջորդ անգամ"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Վրիպակների հաշվետվություններ"</string>
 </resources>
diff --git a/packages/Shell/res/values-in/strings.xml b/packages/Shell/res/values-in/strings.xml
index b1c7293..627fc5e 100644
--- a/packages/Shell/res/values-in/strings.xml
+++ b/packages/Shell/res/values-in/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Sentuh untuk membagikan laporan bug Anda"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Laporan bug berisi data dari berbagai file log sistem, termasuk informasi pribadi dan rahasia. Hanya bagikan laporan bug dengan aplikasi dan orang yang Anda percaya."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tampilkan pesan ini lain kali"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Laporan bug"</string>
 </resources>
diff --git a/packages/Shell/res/values-is-rIS/strings.xml b/packages/Shell/res/values-is-rIS/strings.xml
index 3f4fd3b..dbd39c4 100644
--- a/packages/Shell/res/values-is-rIS/strings.xml
+++ b/packages/Shell/res/values-is-rIS/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Snertu til að deila villutilkynningunni"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Villutilkynningar innihalda gögn úr hinum ýmsu annálsskrám kerfisins, þ. á m. persónuleg gögn og trúnaðarupplýsingar. Deildu villutilkynningum eingöngu með forritum og fólki sem þú treystir."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Sýna þessi skilaboð næst"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Villutilkynningar"</string>
 </resources>
diff --git a/packages/Shell/res/values-it/strings.xml b/packages/Shell/res/values-it/strings.xml
index 9e86aff..cd63891 100644
--- a/packages/Shell/res/values-it/strings.xml
+++ b/packages/Shell/res/values-it/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Tocca per condividere la segnalazione di bug"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Le segnalazioni di bug contengono dati da vari file di log del sistema, incluse informazioni personali e private. Condividi le segnalazioni di bug solo con app e persone attendibili."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostra questo messaggio la prossima volta"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapporti sui bug"</string>
 </resources>
diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml
index 4e06d03..39c784f 100644
--- a/packages/Shell/res/values-iw/strings.xml
+++ b/packages/Shell/res/values-iw/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"גע כדי לשתף את דוח הבאגים שלך"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"דוחות על באגים כוללים נתונים מקובצי היומן השונים במערכת, כולל מידע אישי ופרטי. שתף דוחות באגים רק עם אפליקציות ואנשים שאתה סומך עליהם."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"הצג את ההודעה הזו בפעם הבאה"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"דוחות באגים"</string>
 </resources>
diff --git a/packages/Shell/res/values-ja/strings.xml b/packages/Shell/res/values-ja/strings.xml
index 1b24f31..48be802 100644
--- a/packages/Shell/res/values-ja/strings.xml
+++ b/packages/Shell/res/values-ja/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"バグレポートを共有するにはタップします"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"バグレポートには、個人の非公開情報など、システムのさまざまなログファイルのデータが含まれます。共有する場合は信頼するアプリとユーザーのみを選択してください。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"このメッセージを次回も表示する"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"バグレポート"</string>
 </resources>
diff --git a/packages/Shell/res/values-ka-rGE/strings.xml b/packages/Shell/res/values-ka-rGE/strings.xml
index 977e9aa..bb539d0 100644
--- a/packages/Shell/res/values-ka-rGE/strings.xml
+++ b/packages/Shell/res/values-ka-rGE/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"შეეხეთ თქვენი ხარვეზების ანგარიშის გასაზიარებლად"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ხარვეზის ანგარიშები მოიცავს მონაცემებს სხვადასხვა სისტემური ჟურნალის ფაილებიდან, მათ შორის პირად და კონფიდენციალურ ინფორმაციას."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"შემდგომში აჩვენე ეს შეტყობინება"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"შეცდომების ანგარიშები"</string>
 </resources>
diff --git a/packages/Shell/res/values-kk-rKZ/strings.xml b/packages/Shell/res/values-kk-rKZ/strings.xml
index 9969eff..b22ca45 100644
--- a/packages/Shell/res/values-kk-rKZ/strings.xml
+++ b/packages/Shell/res/values-kk-rKZ/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Бөліс үшін, вирус туралы баянатты түртіңіз."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Вирус туралы баянатта жүйеде тіркелген әртүрлі файлдар туралы деректер болады, оған жеке және құпия ақпарат та кіреді. Вирус баянаттарын сенімді қолданбалар және сенімді адамдармен ғана бөлісіңіз."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Бұл хабарды келесі жолы көрсетіңіз"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Қате туралы баяндамалар"</string>
 </resources>
diff --git a/packages/Shell/res/values-km-rKH/strings.xml b/packages/Shell/res/values-km-rKH/strings.xml
index 04e3170..50c893b 100644
--- a/packages/Shell/res/values-km-rKH/strings.xml
+++ b/packages/Shell/res/values-km-rKH/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"ប៉ះ​ ដើម្បី​ចែក​រំលែក​របាយការណ៍​កំហុស​របស់​អ្នក"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"របាយការណ៍​កំហុស​រួមមាន​ឯកសារ​កំណត់​ហេតុ​ផ្សេងៗ​របស់​ប្រព័ន្ធ រួមមាន​ព័ត៌មាន​ផ្ទាល់ខ្លួន និង​ឯកជន។ ចែករំលែក​របាយការណ៍​កំហុស​ជា​មួយ​កម្មវិធី និង​មនុស្ស​ដែល​អ្នក​ទុក​ចិត្ត។"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"បង្ហាញ​សារ​នេះ​ពេល​ក្រោយ"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"រាយការណ៍ពីកំហុស"</string>
 </resources>
diff --git a/packages/Shell/res/values-kn-rIN/strings.xml b/packages/Shell/res/values-kn-rIN/strings.xml
index 42e9eaa..7ab6abf 100644
--- a/packages/Shell/res/values-kn-rIN/strings.xml
+++ b/packages/Shell/res/values-kn-rIN/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"ನಿಮ್ಮ ದೋಷದ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಸ್ಪರ್ಶಿಸಿ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ವೈಯಕ್ತಿಕ ಮತ್ತು ಖಾಸಗಿ ಮಾಹಿತಿಯು ಸೇರಿದಂತೆ, ಸಿಸ್ಟಂನ ಹಲವಾರು ಲಾಗ್ ಫೈಲ್‌ಗಳಿಂದ ಡೇಟಾವನ್ನು ದೋಷದ ವರದಿಗಳು ಒಳಗೊಂಡಿವೆ. ನೀವು ನಂಬುವಂತಹ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಜನರೊಂದಿಗೆ ಮಾತ್ರ ದೋಷದ ವರದಿಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಿ."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ಈ ಸಂದೇಶವನ್ನು ಮುಂದಿನ ಬಾರಿ ತೋರಿಸಿ"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"ದೋಷ ವರದಿಗಳು"</string>
 </resources>
diff --git a/packages/Shell/res/values-ko/strings.xml b/packages/Shell/res/values-ko/strings.xml
index 3e0dd0b..da0b31f 100644
--- a/packages/Shell/res/values-ko/strings.xml
+++ b/packages/Shell/res/values-ko/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"버그 신고서를 공유하려면 터치하세요."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"버그 신고서는 시스템의 다양한 로그 파일 데이터(예: 개인 및 비공개 정보)를 포함합니다. 신뢰할 수 있는 앱과 사용자에게만 버그 신고서를 공유하세요."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"다음에 이 메시지 표시"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"버그 신고"</string>
 </resources>
diff --git a/packages/Shell/res/values-ky-rKG/strings.xml b/packages/Shell/res/values-ky-rKG/strings.xml
index 6d9ace7..7183f77 100644
--- a/packages/Shell/res/values-ky-rKG/strings.xml
+++ b/packages/Shell/res/values-ky-rKG/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Ката тууралуу билдирүүңүздү жөнөтүш үчүн, тийиңиз"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Ката тууралуу билдирүүлөр системанын ар кандай лог файлдарынын берилиштерин камтыйт, аларга өздүк жана купуя маалыматтар дагы кирет. Ката тууралуу билдирүүлөрдү сиз ишенген колдонмолор жана адамдар менен гана бөлүшүңүз."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Бул билдирүү кийин көрсөтүлсүн"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Мүчүлүштүктөрдү кабарлоолор"</string>
 </resources>
diff --git a/packages/Shell/res/values-lo-rLA/strings.xml b/packages/Shell/res/values-lo-rLA/strings.xml
index b2724ad..fcc58e9 100644
--- a/packages/Shell/res/values-lo-rLA/strings.xml
+++ b/packages/Shell/res/values-lo-rLA/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"ແຕະເພື່ອສົ່ງການລາຍງານປັນຫາຂອງທ່ານ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ການລາຍງານຂໍ້ຜິດພາດປະກອບມີ ຂໍ້ມູນຈາກໄຟລ໌ບັນທຶກຂອງລະບົບຫຼາຍໄຟລ໌, ຮວມທັງຂໍ້ມູນສ່ວນໂຕນຳ. ທ່ານຕ້ອງແບ່ງປັນລາຍງານຂໍ້ຜິດພາດໃຫ້ແອັບຯ ແລະຄົນທີ່ທ່ານເຊື່ອຖືໄດ້ເທົ່ານັ້ນ."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ສະແດງຂໍ້ຄວາມນີ້ອີກໃນເທື່ອຕໍ່ໄປ"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"ລາຍ​ງານ​ບັນ​ຫາ"</string>
 </resources>
diff --git a/packages/Shell/res/values-lt/strings.xml b/packages/Shell/res/values-lt/strings.xml
index a78b1db..51655a4 100644
--- a/packages/Shell/res/values-lt/strings.xml
+++ b/packages/Shell/res/values-lt/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Palieskite, kad bendrintumėte riktų ataskaitą"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Riktų ataskaitose pateikiami duomenys iš įvairių sistemos žurnalo failų, įskaitant asmeninę ir privačią informaciją. Riktų ataskaitas bendrinkite tik su patikimomis programomis ir žmonėmis."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Rodyti šį pranešimą kitą kartą"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Riktų ataskaitos"</string>
 </resources>
diff --git a/packages/Shell/res/values-lv/strings.xml b/packages/Shell/res/values-lv/strings.xml
index 430cb8d..cf1a75a 100644
--- a/packages/Shell/res/values-lv/strings.xml
+++ b/packages/Shell/res/values-lv/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Pieskarieties, lai kopīgotu kļūdu pārskatu."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Kļūdu pārskatā ir iekļauti dati no dažādiem sistēmas žurnālfailiem, tostarp personas dati un privāta informācija. Kļūdu pārskatus ieteicams kopīgot tikai ar uzticamām lietotnēm un lietotājiem."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Rādīt šo ziņojumu nākamajā reizē"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Kļūdu ziņojumi"</string>
 </resources>
diff --git a/packages/Shell/res/values-mk-rMK/strings.xml b/packages/Shell/res/values-mk-rMK/strings.xml
index e6c2c92..785a841 100644
--- a/packages/Shell/res/values-mk-rMK/strings.xml
+++ b/packages/Shell/res/values-mk-rMK/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Допри да се сподели твојот извештај за грешка"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Извештаите за грешка содржат податоци од разни датотеки за евиденција на системот, вклучувајќи лични и приватни информации. Извештаите за грешка споделувајте ги само со апликации и луѓе на коишто им верувате."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Прикажи ја поракава следниот пат"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Извештаи за грешки"</string>
 </resources>
diff --git a/packages/Shell/res/values-ml-rIN/strings.xml b/packages/Shell/res/values-ml-rIN/strings.xml
index 5f3e0b6..8fa6d67c 100644
--- a/packages/Shell/res/values-ml-rIN/strings.xml
+++ b/packages/Shell/res/values-ml-rIN/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ സ്‌പർശിക്കുക"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"വ്യക്തിഗതവും സ്വകാര്യവുമായ വിവരങ്ങൾ ഉൾപ്പെടെ, സിസ്റ്റത്തിന്റെ നിരവധി ലോഗ് ഫയലുകളിൽ നിന്നുള്ള ഡാറ്റ, ബഗ് റിപ്പോർട്ടുകളിൽ അടങ്ങിയിരിക്കുന്നു. നിങ്ങൾ വിശ്വസിക്കുന്ന അപ്ലിക്കേഷനുകൾക്കും ആളുകൾക്കും മാത്രം ബഗ് റിപ്പോർട്ടുകൾ പങ്കിടുക."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ഈ സന്ദേശം അടുത്ത തവണ ദൃശ്യമാക്കുക"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"ബഗ് റിപ്പോർട്ടുകൾ"</string>
 </resources>
diff --git a/packages/Shell/res/values-mn-rMN/strings.xml b/packages/Shell/res/values-mn-rMN/strings.xml
index 4637f2d..4010072 100644
--- a/packages/Shell/res/values-mn-rMN/strings.xml
+++ b/packages/Shell/res/values-mn-rMN/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Та алдааны мэдэгдлийг хуваалцах бол хүрнэ үү"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Алдааны репорт нь хувийн болон нууц мэдээлэл зэргийг агуулсан системийн төрөл бүрийн лог файлын датаг агуулна. Алдааны репортыг зөвхөн итгэлтэй апп болон хүмүүст хуваалцана уу."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Энэ мессежийг дараагийн удаа харуулах"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Гэмтлийн тухай тайлан"</string>
 </resources>
diff --git a/packages/Shell/res/values-mr-rIN/strings.xml b/packages/Shell/res/values-mr-rIN/strings.xml
index ca3c4b3..c4993fc 100644
--- a/packages/Shell/res/values-mr-rIN/strings.xml
+++ b/packages/Shell/res/values-mr-rIN/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"आपला दोष अहवाल सामायिक करण्‍यासाठी स्‍पर्श करा"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"दोष अहवालांमध्‍ये वैयक्तिक आणि खाजगी माहितीसह, सिस्‍टमच्‍या अनेक लॉग फायलींमधील डेटा असतो. केवळ आपला विश्वास असलेल्‍या अ‍ॅप्‍स आणि लोकांसह दोष अहवाल सामायिक करा."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"पुढील वेळी हा संदेश दर्शवा"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"दोष अहवाल"</string>
 </resources>
diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml
index d7bdc78..f3e4f7e 100644
--- a/packages/Shell/res/values-ms-rMY/strings.xml
+++ b/packages/Shell/res/values-ms-rMY/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Sentuh untuk berkongsi laporan pepijat anda"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Laporan pepijat mengandungi data dari pelbagai fail log sistem, termasuk maklumat peribadi dan sulit. Kongsikan laporan pepijat hanya dengan apl dan orang yang anda percayai."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tunjukkan mesej ini pada masa akan datang"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Laporan pepijat"</string>
 </resources>
diff --git a/packages/Shell/res/values-my-rMM/strings.xml b/packages/Shell/res/values-my-rMM/strings.xml
index 6cac668..d223bd9 100644
--- a/packages/Shell/res/values-my-rMM/strings.xml
+++ b/packages/Shell/res/values-my-rMM/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"အမှားအယွင်း မှတ်တမ်းကို မျှဝေရန် ထိလိုက်ပါ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"အမှားအယွင်း မှတ်တမ်းမှာ ပါရှိသော အချက်အလက်များမှာ ကိုယ်ရေးကိုယ်တာ နဲ့ လုံခြုံရေး အချက်အလက်များပါဝင်သော စနစ်မှ ပြုလုပ်မှု မှတ်တမ်းများ ဖြစ်ပါသည်၊ အမှားအယွင်း မှတ်တမ်းများကို ယုံကြည်ရသော အပလီကေးရှင်းများနဲ့ လူများကိုသာ ပေးဝေပြသမှု လုပ်ပါရန်။"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ဤစာတန်းကို နောက်တစ်ခါတွင် ပြရန်"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"ချို့ယွင်းမှု အစီရင်ခံစာများ"</string>
 </resources>
diff --git a/packages/Shell/res/values-nb/strings.xml b/packages/Shell/res/values-nb/strings.xml
index 657a209..c00e2d0 100644
--- a/packages/Shell/res/values-nb/strings.xml
+++ b/packages/Shell/res/values-nb/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Trykk for å dele feilrapporten din"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Feilrapporter inkluderer data fra systemets forskjellige loggfiler. Dette omfatter personlig og privat informasjon. Du bør bare dele feilrapporter med apper og folk du stoler på."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Vis denne meldingen neste gang"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Feilrapporter"</string>
 </resources>
diff --git a/packages/Shell/res/values-ne-rNP/strings.xml b/packages/Shell/res/values-ne-rNP/strings.xml
index a5514822..7344889 100644
--- a/packages/Shell/res/values-ne-rNP/strings.xml
+++ b/packages/Shell/res/values-ne-rNP/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"तपाईंको बग रिपोर्ट साझेदारी गर्न छुनुहोस्"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"बग रिपोर्टहरूमा प्रणालीका विभिन्न लग फाइलहरूबाट व्यक्तिगत तथा नीजि सूचनासहितको डेटा रहन्छ।  बग रिपोर्टहरू अनुप्रयोगहरू र तपाईँले विश्वास गरेका व्यक्तिहरूसँग मात्र साझेदारी गर्नुहोस्।"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"यो सन्देश अर्को पटक देखाउनुहोस्"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रिपोर्टहरू"</string>
 </resources>
diff --git a/packages/Shell/res/values-nl/strings.xml b/packages/Shell/res/values-nl/strings.xml
index 51ae329..2936387 100644
--- a/packages/Shell/res/values-nl/strings.xml
+++ b/packages/Shell/res/values-nl/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Raak aan om uw foutenrapport te delen"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Foutenrapporten bevatten gegevens uit de verschillende logbestanden van het systeem, waaronder persoonlijke en privégegevens. Deel foutenrapporten alleen met apps en mensen die u vertrouwt."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Dit bericht de volgende keer weergeven"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Foutenrapporten"</string>
 </resources>
diff --git a/packages/Shell/res/values-pl/strings.xml b/packages/Shell/res/values-pl/strings.xml
index 2c810d6..266f070 100644
--- a/packages/Shell/res/values-pl/strings.xml
+++ b/packages/Shell/res/values-pl/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Kliknij, by udostępnić raport o błędach"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Raporty o błędach zawierają dane z różnych plików dzienników systemu, w tym dane osobowe i prywatne. Udostępniaj je tylko aplikacjom i osobom, którym ufasz."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaż ten komunikat następnym razem"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Zgłoszenia błędów"</string>
 </resources>
diff --git a/packages/Shell/res/values-pt-rPT/strings.xml b/packages/Shell/res/values-pt-rPT/strings.xml
index 7a833d6..648ef94 100644
--- a/packages/Shell/res/values-pt-rPT/strings.xml
+++ b/packages/Shell/res/values-pt-rPT/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toque para partilhar o relatório de erros"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de erros incluem dados de vários ficheiros de registo do sistema, nomeadamente informações pessoais e privadas. Partilhe relatórios de erros apenas com aplicações e pessoas fidedignas."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de erros"</string>
 </resources>
diff --git a/packages/Shell/res/values-pt/strings.xml b/packages/Shell/res/values-pt/strings.xml
index c166bf3..e04d600 100644
--- a/packages/Shell/res/values-pt/strings.xml
+++ b/packages/Shell/res/values-pt/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toque para compartilhar seu relatório de bugs"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de bugs contêm dados de diversos arquivos de registro do sistema, inclusive informações pessoais e particulares. Compartilhe relatórios de bugs somente com apps e pessoas nos quais você confia."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de bugs"</string>
 </resources>
diff --git a/packages/Shell/res/values-ro/strings.xml b/packages/Shell/res/values-ro/strings.xml
index 537ba3d..aab29b7 100644
--- a/packages/Shell/res/values-ro/strings.xml
+++ b/packages/Shell/res/values-ro/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Atingeți pentru a permite accesul la raportul despre erori"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Rapoartele despre erori conțin date din diferite fișiere de jurnal ale sistemului, inclusiv informații private și personale. Permiteți accesul la rapoartele despre erori numai aplicațiilor și persoanelor în care aveți încredere."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afișați acest mesaj data viitoare"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapoarte de erori"</string>
 </resources>
diff --git a/packages/Shell/res/values-ru/strings.xml b/packages/Shell/res/values-ru/strings.xml
index 77a8cd0..1f1444d 100644
--- a/packages/Shell/res/values-ru/strings.xml
+++ b/packages/Shell/res/values-ru/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Нажмите, чтобы отправить отчет об ошибках"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Отчеты об ошибках содержат данные различных системных журналов и могут включать личную информацию. Рекомендуем открывать к ним доступ только лицам и приложениям, заслуживающим доверие."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Показать это сообщение в следующий раз"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Отчеты об ошибках"</string>
 </resources>
diff --git a/packages/Shell/res/values-si-rLK/strings.xml b/packages/Shell/res/values-si-rLK/strings.xml
index 34d7f82..4244f2b 100644
--- a/packages/Shell/res/values-si-rLK/strings.xml
+++ b/packages/Shell/res/values-si-rLK/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"ඔබගේ දෝෂ වාර්තාව බෙදා ගැනීමට ස්පර්ශ කරන්න"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"පුද්ගලික සහ පෞද්ගලික තොරතුරු ඇතුළත්ව පද්ධතියේ විවිධ ලොග් ගොනු වල දත්ත දෝෂ වාර්තාවේ අඩංගු වේ. ඔබට විශ්වාසවන්ත යෙදුම් සහ පුද්ගලයින් සමඟ පමණක් දෝෂ වාර්තා බෙදා ගන්න."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ඊළඟ වෙලාවේ මෙම පණිවිඩය පෙන්වන්න"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"දෝෂ වාර්තා"</string>
 </resources>
diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index 0d6940d..a79059d 100644
--- a/packages/Shell/res/values-sk/strings.xml
+++ b/packages/Shell/res/values-sk/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Hlásenie o chybách môžete zdielať klepnutím"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Správy o chybách obsahujú údaje z rôznych súborov denníkov systému vrátane osobných a súkromných informácií. Zdieľajte ich iba s dôveryhodnými aplikáciami a ľuďmi."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobraziť túto správu nabudúce"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Hlásenia o chybe"</string>
 </resources>
diff --git a/packages/Shell/res/values-sl/strings.xml b/packages/Shell/res/values-sl/strings.xml
index b2caa07..8c3bedc 100644
--- a/packages/Shell/res/values-sl/strings.xml
+++ b/packages/Shell/res/values-sl/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Dotaknite se, če želite deliti sporočilo o napaki z drugimi"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Poročila o napakah vsebujejo podatke iz različnih dnevniških datotek sistema, vključno z osebnimi in zasebnimi podatki. Poročila o napakah delite samo z aplikacijami in ljudmi, ki jim zaupate."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaži to sporočilo naslednjič"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Poročila o napakah"</string>
 </resources>
diff --git a/packages/Shell/res/values-sr/strings.xml b/packages/Shell/res/values-sr/strings.xml
index 9e4e595..763bd2b 100644
--- a/packages/Shell/res/values-sr/strings.xml
+++ b/packages/Shell/res/values-sr/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Додирните да бисте делили извештај о грешци"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Извештаји о грешкама садрже податке из различитих системских датотека евиденције, укључујући личне и приватне податке. Делите извештаје о грешкама само са апликацијама и људима у које имате поверења."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Прикажи ову поруку следећи пут"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Извештаји о грешкама"</string>
 </resources>
diff --git a/packages/Shell/res/values-sv/strings.xml b/packages/Shell/res/values-sv/strings.xml
index c26a7ce..47ee2f7 100644
--- a/packages/Shell/res/values-sv/strings.xml
+++ b/packages/Shell/res/values-sv/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Tryck om du vill dela felrapporten"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Felrapporter innehåller data från systemets olika loggfiler, inklusive personliga och privata uppgifter. Dela bara felrapporter med personer du litar på."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Visa det här meddelandet nästa gång"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Felrapporter"</string>
 </resources>
diff --git a/packages/Shell/res/values-sw/strings.xml b/packages/Shell/res/values-sw/strings.xml
index 4553328..0d12cc9 100644
--- a/packages/Shell/res/values-sw/strings.xml
+++ b/packages/Shell/res/values-sw/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Gusa ili ushiriki ripoti yako ya hitilafu"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Ripoti ya hitilafu ina data kutoka kwenye faili za kumbukumbu mbalimbali za mfumo, pamoja na maelezo ya kibinafsi na faragha. Shiriki ripoti ya hitilafu na programu na watu unaowaamini pekee."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Onyesha ujumbe huu wakati mwingine"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Ripoti za hitilafu"</string>
 </resources>
diff --git a/packages/Shell/res/values-ta-rIN/strings.xml b/packages/Shell/res/values-ta-rIN/strings.xml
index d94555d..cd0462b 100644
--- a/packages/Shell/res/values-ta-rIN/strings.xml
+++ b/packages/Shell/res/values-ta-rIN/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"உங்கள் பிழை அறிக்கையைப் பகிர, தொடவும்"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"பிழை அறிக்கைகளில், சொந்த வாழ்க்கை மற்றும் தனிப்பட்ட தகவல் உள்பட கணினியின் பல்வேறு பதிவுகளில் உள்ள தரவு இருக்கும். நீங்கள் நம்பும் பயன்பாடுகள் மற்றும் நபர்களுடன் மட்டும் பிழை அறிக்கைகளைப் பகிரவும்."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"இந்தச் செய்தியை அடுத்த முறைக் காட்டு"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"பிழை அறிக்கைகள்"</string>
 </resources>
diff --git a/packages/Shell/res/values-te-rIN/strings.xml b/packages/Shell/res/values-te-rIN/strings.xml
index 6b5710b..127f602 100644
--- a/packages/Shell/res/values-te-rIN/strings.xml
+++ b/packages/Shell/res/values-te-rIN/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి తాకండి"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"బగ్ నివేదికలు వ్యక్తిగతమైన మరియు రహస్యమైన సమాచారంతో సహా సిస్టమ్ యొక్క విభిన్న లాగ్ ఫైల్‌ల్లోని డేటాను కలిగి ఉంటాయి. కనుక బగ్ నివేదికలను మీరు విశ్వసించే అనువర్తనాలు మరియు వ్యక్తులతో మాత్రమే భాగస్వామ్యం చేయండి."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"తదుపరిసారి ఈ సందేశాన్ని చూపు"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"బగ్ నివేదికలు"</string>
 </resources>
diff --git a/packages/Shell/res/values-th/strings.xml b/packages/Shell/res/values-th/strings.xml
index 0702952..2bc8f0d 100644
--- a/packages/Shell/res/values-th/strings.xml
+++ b/packages/Shell/res/values-th/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"รายงานข้อบกพร่องมีข้อมูลจากไฟล์บันทึกต่างๆ ของระบบ รวมถึงข้อมูลส่วนตัว แชร์รายงานข้อบกพร่องกับแอปและบุคคลที่คุณไว้ใจเท่านั้น"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"แสดงข้อความนี้ในครั้งต่อไป"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"รายงานข้อบกพร่อง"</string>
 </resources>
diff --git a/packages/Shell/res/values-tl/strings.xml b/packages/Shell/res/values-tl/strings.xml
index 8d42ecd..a5c0e8a 100644
--- a/packages/Shell/res/values-tl/strings.xml
+++ b/packages/Shell/res/values-tl/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Pindutin upang ibahagi ang iyong ulat ng bug"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Naglalaman ang mga ulat ng bug ng data mula sa iba\'t ibang file ng log ng system, kabilang ang personal at pribadong impormasyon. Magbahagi lang ng mga ulat ng bug sa apps at mga tao na pinagkakatiwalaan mo."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Ipakita ang mensaheng ito sa susunod"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Mga ulat sa bug"</string>
 </resources>
diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml
index ed0697e..67390b7 100644
--- a/packages/Shell/res/values-tr/strings.xml
+++ b/packages/Shell/res/values-tr/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Hata raporunuzu paylaşmak için dokunun"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Hata raporları, kişisel ve özel bilgiler dahil olmak üzere sistemin çeşitli günlük dosyalarından veriler içerir. Hata raporlarını sadece güvendiğiniz uygulamalar ve kişilerle paylaşın."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bir dahaki sefere bu iletiyi göster"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Hata raporları"</string>
 </resources>
diff --git a/packages/Shell/res/values-uk/strings.xml b/packages/Shell/res/values-uk/strings.xml
index f9f5bb3..f8f1798 100644
--- a/packages/Shell/res/values-uk/strings.xml
+++ b/packages/Shell/res/values-uk/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Торкніться, щоб надіслати звіт про помилки"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Звіти про помилки містять дані з різних файлів журналу системи, зокрема особисті та конфіденційні. Надсилайте звіт про помилки лише тим, кому довіряєте."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Показати це повідомлення наступного разу"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Звіти про помилки"</string>
 </resources>
diff --git a/packages/Shell/res/values-ur-rPK/strings.xml b/packages/Shell/res/values-ur-rPK/strings.xml
index afdb241..73d6877 100644
--- a/packages/Shell/res/values-ur-rPK/strings.xml
+++ b/packages/Shell/res/values-ur-rPK/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"اپنی بَگ رپورٹ کا اشتراک کرنے کیلئے ٹچ کریں"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"بَگ رپورٹس میں سسٹم کی مختلف لاگ فائلوں سے ڈیٹا شامل ہوتا ہے، بشمول ذاتی اور نجی معلومات۔ بَگ رپورٹس کا اشتراک صرف اپنے بھروسے مند ایپس اور لوگوں کے ساتھ کریں۔"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"یہ پیغام اگلی بار دکھائیں"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"بگ رپورٹس"</string>
 </resources>
diff --git a/packages/Shell/res/values-uz-rUZ/strings.xml b/packages/Shell/res/values-uz-rUZ/strings.xml
index e9c3900..b221171 100644
--- a/packages/Shell/res/values-uz-rUZ/strings.xml
+++ b/packages/Shell/res/values-uz-rUZ/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Xatolik hisobotini bo‘lishish uchun barmog‘ingizni tegizing."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Xatolik hisobotlari tizimdagi har xil jurnal fayllardagi ma’lumotlarni, shuningdek, shaxsiy hamda maxfiy ma’lumotlarni o‘z ichiga oladi. Xatolik hisobotlarini faqat ishonchli dasturlar va odamlar bilan bo‘lishing."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Ushbu xabar keyingi safar ko‘rsatilsin"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Xatoliklar hisoboti"</string>
 </resources>
diff --git a/packages/Shell/res/values-vi/strings.xml b/packages/Shell/res/values-vi/strings.xml
index 4919411..16a7df9 100644
--- a/packages/Shell/res/values-vi/strings.xml
+++ b/packages/Shell/res/values-vi/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Chạm để chia sẻ báo cáo lỗi của bạn"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Các báo cáo lỗi chứa dữ liệu từ nhiều tệp nhật ký khác nhau của hệ thống, bao gồm cả thông tin cá nhân và riêng tư. Chỉ chia sẻ báo cáo lỗi với các ứng dụng và những người mà bạn tin tưởng."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Hiển thị thông báo này vào lần tới"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Báo cáo lỗi"</string>
 </resources>
diff --git a/packages/Shell/res/values-zh-rCN/strings.xml b/packages/Shell/res/values-zh-rCN/strings.xml
index 409b5ca..17fdedd 100644
--- a/packages/Shell/res/values-zh-rCN/strings.xml
+++ b/packages/Shell/res/values-zh-rCN/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"触摸即可分享您的错误报告"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"错误报告包含的数据来自于系统的各个日志文件,其中包含个人信息和隐私信息。请务必只与您信任的应用和用户分享错误报告。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次再显示这条讯息"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"错误报告"</string>
 </resources>
diff --git a/packages/Shell/res/values-zh-rHK/strings.xml b/packages/Shell/res/values-zh-rHK/strings.xml
index f2e034b..0f70bab 100644
--- a/packages/Shell/res/values-zh-rHK/strings.xml
+++ b/packages/Shell/res/values-zh-rHK/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"輕觸即可分享您的錯誤報告"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"錯誤報告中有來自系統各個記錄檔案的資料,包括個人和私人資料。請只與您信任的應用程式和使用者分享錯誤報告。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次再顯示這則訊息"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string>
 </resources>
diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml
index fe3bcff..d7f7507 100644
--- a/packages/Shell/res/values-zh-rTW/strings.xml
+++ b/packages/Shell/res/values-zh-rTW/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"輕觸即可分享您的錯誤報告"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"錯誤報告的資料來自系統各個紀錄檔,包括個人和私密資訊。請務必只與您信任的應用程式和使用者分享錯誤報告。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次仍顯示這則訊息"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string>
 </resources>
diff --git a/packages/Shell/res/values-zu/strings.xml b/packages/Shell/res/values-zu/strings.xml
index 38e9595..c82fb93 100644
--- a/packages/Shell/res/values-zu/strings.xml
+++ b/packages/Shell/res/values-zu/strings.xml
@@ -22,4 +22,5 @@
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Thinta ukuze wabelane ngombiko wakho wesiphazamisi"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Imibiko yeziphazamisi iqukethe idatha yamafayela wokungena ahlukile wesistimu, afaka ulwazi lomuntu siqu noma lobumfihlo. Yabelana kuphela ngemibiko yeziphazamisi nezinhlelo zokusebenza nabantu obathembayo."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bonisa lo mlayezo ngesikhathi esilandelayo"</string>
+    <string name="bugreport_storage_title" msgid="5332488144740527109">"Imibiko yeziphazamiso"</string>
 </resources>
diff --git a/packages/Shell/res/values/strings.xml b/packages/Shell/res/values/strings.xml
index 51e2c95..3db0848 100644
--- a/packages/Shell/res/values/strings.xml
+++ b/packages/Shell/res/values/strings.xml
@@ -30,4 +30,7 @@
     <string name="bugreport_confirm">Bug reports contain data from the system\'s various log files, including personal and private information.  Only share bug reports with apps and people you trust.</string>
     <!-- Checkbox that indicates this dialog should be shown again when the next bugreport is taken. [CHAR LIMIT=50] -->
     <string name="bugreport_confirm_repeat">Show this message next time</string>
+
+    <!-- Title for documents backend that offers bugreports. -->
+    <string name="bugreport_storage_title">Bug reports</string>
 </resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
new file mode 100644
index 0000000..814aa8c
--- /dev/null
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -0,0 +1,164 @@
+/*
+ * 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.shell;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.os.CancellationSignal;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
+import android.provider.DocumentsProvider;
+import android.webkit.MimeTypeMap;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+public class BugreportStorageProvider extends DocumentsProvider {
+    private static final String DOC_ID_ROOT = "bugreport";
+
+    private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
+            Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
+            Root.COLUMN_DOCUMENT_ID,
+    };
+
+    private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
+            Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
+            Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
+    };
+
+    private File mRoot;
+
+    @Override
+    public boolean onCreate() {
+        mRoot = new File(getContext().getFilesDir(), "bugreports");
+        return true;
+    }
+
+    @Override
+    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
+        final RowBuilder row = result.newRow();
+        row.add(Root.COLUMN_ROOT_ID, DOC_ID_ROOT);
+        row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED);
+        row.add(Root.COLUMN_ICON, android.R.mipmap.sym_def_app_icon);
+        row.add(Root.COLUMN_TITLE, getContext().getString(R.string.bugreport_storage_title));
+        row.add(Root.COLUMN_DOCUMENT_ID, DOC_ID_ROOT);
+        return result;
+    }
+
+    @Override
+    public Cursor queryDocument(String documentId, String[] projection)
+            throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
+        if (DOC_ID_ROOT.equals(documentId)) {
+            final RowBuilder row = result.newRow();
+            row.add(Document.COLUMN_DOCUMENT_ID, documentId);
+            row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
+            row.add(Document.COLUMN_DISPLAY_NAME, mRoot.getName());
+            row.add(Document.COLUMN_LAST_MODIFIED, mRoot.lastModified());
+            row.add(Document.COLUMN_FLAGS, Document.FLAG_DIR_PREFERS_LAST_MODIFIED);
+        } else {
+            addFileRow(result, getFileForDocId(documentId));
+        }
+        return result;
+    }
+
+    @Override
+    public Cursor queryChildDocuments(
+            String parentDocumentId, String[] projection, String sortOrder)
+            throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
+        if (DOC_ID_ROOT.equals(parentDocumentId)) {
+            final File[] files = mRoot.listFiles();
+            if (files != null) {
+                for (File file : files) {
+                    addFileRow(result, file);
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public ParcelFileDescriptor openDocument(
+            String documentId, String mode, CancellationSignal signal)
+            throws FileNotFoundException {
+        if (ParcelFileDescriptor.parseMode(mode) != ParcelFileDescriptor.MODE_READ_ONLY) {
+            throw new FileNotFoundException("Failed to open: " + documentId + ", mode = " + mode);
+        }
+        return ParcelFileDescriptor.open(getFileForDocId(documentId),
+                ParcelFileDescriptor.MODE_READ_ONLY);
+    }
+
+    @Override
+    public void deleteDocument(String documentId) throws FileNotFoundException {
+        if (!getFileForDocId(documentId).delete()) {
+            throw new FileNotFoundException("Failed to delete: " + documentId);
+        }
+    }
+
+    private static String[] resolveRootProjection(String[] projection) {
+        return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
+    }
+
+    private static String[] resolveDocumentProjection(String[] projection) {
+        return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
+    }
+
+    private static String getTypeForName(String name) {
+        final int lastDot = name.lastIndexOf('.');
+        if (lastDot >= 0) {
+            final String extension = name.substring(lastDot + 1).toLowerCase();
+            final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+            if (mime != null) {
+                return mime;
+            }
+        }
+        return "application/octet-stream";
+    }
+
+    private String getDocIdForFile(File file) {
+        return DOC_ID_ROOT + ":" + file.getName();
+    }
+
+    private File getFileForDocId(String documentId) throws FileNotFoundException {
+        final int splitIndex = documentId.indexOf(':', 1);
+        final String name = documentId.substring(splitIndex + 1);
+        if (splitIndex == -1 || !DOC_ID_ROOT.equals(documentId.substring(0, splitIndex)) ||
+                !FileUtils.isValidExtFilename(name)) {
+            throw new FileNotFoundException("Invalid document ID: " + documentId);
+        }
+        final File file = new File(mRoot, name);
+        if (!file.exists()) {
+            throw new FileNotFoundException("File not found: " + documentId);
+        }
+        return file;
+    }
+
+    private void addFileRow(MatrixCursor result, File file) {
+        final RowBuilder row = result.newRow();
+        row.add(Document.COLUMN_DOCUMENT_ID, getDocIdForFile(file));
+        row.add(Document.COLUMN_MIME_TYPE, getTypeForName(file.getName()));
+        row.add(Document.COLUMN_DISPLAY_NAME, file.getName());
+        row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
+        row.add(Document.COLUMN_FLAGS, Document.FLAG_SUPPORTS_DELETE);
+        row.add(Document.COLUMN_SIZE, file.length());
+    }
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 7a58c87..012c84c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -120,6 +120,9 @@
     <!-- Screen Capturing -->
     <uses-permission android:name="android.permission.MANAGE_MEDIA_PROJECTION" />
 
+    <!-- Assist -->
+    <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
+
     <application
         android:name=".SystemUIApplication"
         android:persistent="true"
@@ -178,15 +181,6 @@
                 android:excludeFromRecents="true">
         </activity>
 
-        <receiver
-            android:name=".recent.RecentsPreloadReceiver"
-            android:exported="false">
-            <intent-filter>
-                <action android:name="com.android.systemui.recent.action.PRELOAD" />
-                <action android:name="com.android.systemui.recent.action.CANCEL_PRELOAD" />
-            </intent-filter>
-        </receiver>
-
         <!-- Alternate Recents -->
         <activity android:name=".recents.RecentsActivity"
                   android:label="@string/accessibility_desc_recent_apps"
@@ -195,6 +189,7 @@
                   android:excludeFromRecents="true"
                   android:stateNotNeeded="true"
                   android:resumeWhilePausing="true"
+                  android:screenOrientation="behind"
                   android:theme="@style/config_recents_activity_theme">
             <intent-filter>
                 <action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
diff --git a/packages/SystemUI/res/anim/ic_volume_collapse_chevron_02_animation.xml b/packages/SystemUI/res/anim/ic_volume_collapse_chevron_02_animation.xml
new file mode 100644
index 0000000..443f2a6
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_volume_collapse_chevron_02_animation.xml
@@ -0,0 +1,25 @@
+<!--
+     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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <objectAnimator
+        android:duration="250"
+        android:interpolator="@android:interpolator/fast_out_slow_in"
+        android:pathData="M 12.0,9.0 c 0.0,0.66667 0.0,5.0 0.0,6.0"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY" />
+
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_volume_collapse_rectangle_1_animation.xml b/packages/SystemUI/res/anim/ic_volume_collapse_rectangle_1_animation.xml
new file mode 100644
index 0000000..d82f670
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_volume_collapse_rectangle_1_animation.xml
@@ -0,0 +1,26 @@
+<!--
+     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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <objectAnimator
+        android:duration="200"
+        android:interpolator="@interpolator/ic_volume_collapse_animation_interpolator_0"
+        android:propertyName="rotation"
+        android:valueFrom="45.0"
+        android:valueTo="-45.0"
+        android:valueType="floatType" />
+
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_volume_collapse_rectangle_2_animation.xml b/packages/SystemUI/res/anim/ic_volume_collapse_rectangle_2_animation.xml
new file mode 100644
index 0000000..0bc66bd
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_volume_collapse_rectangle_2_animation.xml
@@ -0,0 +1,26 @@
+<!--
+     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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <objectAnimator
+        android:duration="200"
+        android:interpolator="@interpolator/ic_volume_collapse_animation_interpolator_0"
+        android:propertyName="rotation"
+        android:valueFrom="-45.0"
+        android:valueTo="45.0"
+        android:valueType="floatType" />
+
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_volume_expand_chevron_01_animation.xml b/packages/SystemUI/res/anim/ic_volume_expand_chevron_01_animation.xml
new file mode 100644
index 0000000..e43e645
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_volume_expand_chevron_01_animation.xml
@@ -0,0 +1,25 @@
+<!--
+     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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <objectAnimator
+        android:duration="250"
+        android:interpolator="@android:interpolator/fast_out_slow_in"
+        android:pathData="M 12.0,15.0 c 0.0,-1.0 0.0,-5.33333 0.0,-6.0"
+        android:propertyXName="translateX"
+        android:propertyYName="translateY" />
+
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_volume_expand_rectangle_3_animation.xml b/packages/SystemUI/res/anim/ic_volume_expand_rectangle_3_animation.xml
new file mode 100644
index 0000000..9b575d8
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_volume_expand_rectangle_3_animation.xml
@@ -0,0 +1,26 @@
+<!--
+     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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <objectAnimator
+        android:duration="200"
+        android:interpolator="@interpolator/ic_volume_expand_animation_interpolator_0"
+        android:propertyName="rotation"
+        android:valueFrom="45.0"
+        android:valueTo="-45.0"
+        android:valueType="floatType" />
+
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/ic_volume_expand_rectangle_4_animation.xml b/packages/SystemUI/res/anim/ic_volume_expand_rectangle_4_animation.xml
new file mode 100644
index 0000000..6ae0fef
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_volume_expand_rectangle_4_animation.xml
@@ -0,0 +1,26 @@
+<!--
+     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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <objectAnimator
+        android:duration="200"
+        android:interpolator="@interpolator/ic_volume_expand_animation_interpolator_0"
+        android:propertyName="rotation"
+        android:valueFrom="-45.0"
+        android:valueTo="45.0"
+        android:valueType="floatType" />
+
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml b/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml
new file mode 100644
index 0000000..52ed76d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ 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
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient
+            android:type="linear"
+            android:angle="90"
+            android:startColor="#33000000"
+            android:endColor="#00000000" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/search_panel_scrim.xml b/packages/SystemUI/res/drawable/assist_orb_scrim.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/search_panel_scrim.xml
rename to packages/SystemUI/res/drawable/assist_orb_scrim.xml
diff --git a/packages/SystemUI/res/drawable/btn_borderless_rect.xml b/packages/SystemUI/res/drawable/btn_borderless_rect.xml
index d640141..c0a89f9 100644
--- a/packages/SystemUI/res/drawable/btn_borderless_rect.xml
+++ b/packages/SystemUI/res/drawable/btn_borderless_rect.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+     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.
@@ -13,13 +13,15 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="?android:attr/colorControlHighlight">
+    android:color="?android:attr/colorControlHighlight" >
+
     <item android:id="@android:id/mask">
         <shape>
             <corners android:radius="@dimen/borderless_button_radius" />
+
             <solid android:color="@android:color/white" />
         </shape>
     </item>
+
 </ripple>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_dnd.xml b/packages/SystemUI/res/drawable/ic_dnd.xml
new file mode 100644
index 0000000..17ecf21
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_dnd.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24dp" >
+
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z" />
+
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_minus.xml b/packages/SystemUI/res/drawable/ic_qs_minus.xml
index 4722c9e..6a3410a 100644
--- a/packages/SystemUI/res/drawable/ic_qs_minus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_minus.xml
@@ -1,25 +1,26 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+     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
+     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
+          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.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+    android:height="24.0dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24.0dp" >
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M24.0,4.0C13.0,4.0 4.0,13.0 4.0,24.0s9.0,20.0 20.0,20.0c11.0,0.0 20.0,-9.0 20.0,-20.0S35.0,4.0 24.0,4.0zM34.0,26.0L14.0,26.0l0.0,-4.0l20.0,0.0L34.0,26.0z"/>
-</vector>
+        android:pathData="M38.0,26.0L10.0,26.0l0.0,-4.0l28.0,0.0l0.0,4.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_plus.xml b/packages/SystemUI/res/drawable/ic_qs_plus.xml
index 17d74cf..393f51c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_plus.xml
@@ -1,25 +1,26 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+     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
+     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
+          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.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+    android:height="24.0dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24.0dp" >
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M24.0,4.0C13.0,4.0 4.0,13.0 4.0,24.0s9.0,20.0 20.0,20.0c11.0,0.0 20.0,-9.0 20.0,-20.0S35.0,4.0 24.0,4.0zM34.0,26.0l-8.0,0.0l0.0,8.0l-4.0,0.0l0.0,-8.0l-8.0,0.0l0.0,-4.0l8.0,0.0l0.0,-8.0l4.0,0.0l0.0,8.0l8.0,0.0L34.0,26.0z"/>
-</vector>
+        android:pathData="M38.0,26.0L26.0,26.0l0.0,12.0l-4.0,0.0L22.0,26.0L10.0,26.0l0.0,-4.0l12.0,0.0L22.0,10.0l4.0,0.0l0.0,12.0l12.0,0.0l0.0,4.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm.xml b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
new file mode 100644
index 0000000..a8ca0d6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24.0dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24.0dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M44.0,11.44l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-28.24,-4.66l-2.57,-3.06 -9.19,7.71 2.57,3.06 9.19,-7.71zm9.24,9.22l-3.0,0.0l0.0,12.0l9.49,5.71 1.51,-2.47 -8.0,-4.74l0.0,-10.5zm-1.01,-8.0c-9.95,0.0 -17.99,8.06 -17.99,18.0s8.04,18.0 17.99,18.0 18.01,-8.06 18.01,-18.0 -8.06,-18.0 -18.01,-18.0zm0.01,32.0c-7.73,0.0 -14.0,-6.27 -14.0,-14.0s6.27,-14.0 14.0,-14.0 14.0,6.27 14.0,14.0 -6.26,14.0 -14.0,14.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
new file mode 100644
index 0000000..8e2f083
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24.0dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24.0dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M24.0,12.0c7.73,0.0 14.0,6.27 14.0,14.0 0.0,1.69 -0.31,3.3 -0.86,4.8l3.04,3.04c1.16,-2.37 1.82,-5.03 1.82,-7.84 0.0,-9.94 -8.06,-18.0 -18.01,-18.0 -2.81,0.0 -5.46,0.66 -7.84,1.81l3.05,3.05c1.5,-0.55 3.11,-0.86 4.8,-0.86zm20.0,-0.56l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-38.16,-6.85l-2.55,2.54 2.66,2.66 -2.22,1.86 2.84,2.84 2.22,-1.86 1.6,1.6c-2.73,3.16 -4.39,7.27 -4.39,11.77 0.0,9.94 8.04,18.0 17.99,18.0 4.51,0.0 8.62,-1.67 11.77,-4.4l4.4,4.4 2.54,-2.55 -34.91,-34.91 -1.95,-1.95zm27.1,32.19c-2.43,2.01 -5.54,3.22 -8.94,3.22 -7.73,0.0 -14.0,-6.27 -14.0,-14.0 0.0,-3.4 1.21,-6.51 3.22,-8.94l19.72,19.72zm-16.91,-30.23l-2.84,-2.84 -1.7,1.43 2.84,2.84 1.7,-1.43z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_bt.xml b/packages/SystemUI/res/drawable/ic_volume_bt.xml
new file mode 100644
index 0000000..bce407a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_bt.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M35.4,15.4L24.0,4.0l-2.0,0.0l0.0,15.2L12.8,10.0L10.0,12.8L21.2,24.0L10.0,35.2l2.8,2.8l9.2,-9.2L22.0,44.0l2.0,0.0l11.4,-11.4L26.8,24.0L35.4,15.4zM26.0,11.7l3.8,3.8L26.0,19.2L26.0,11.7zM29.8,32.6L26.0,36.3l0.0,-7.5L29.8,32.6z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_bt_mute.xml b/packages/SystemUI/res/drawable/ic_volume_bt_mute.xml
new file mode 100644
index 0000000..98a8137
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_bt_mute.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M26.0,11.8l3.8,3.8l-3.2,3.2l2.8,2.8l6.0,-6.0L24.0,4.2l-2.0,0.0l0.0,10.1l4.0,4.0L26.0,11.8zM10.8,8.2L8.0,11.0l13.2,13.2L10.0,35.3l2.8,2.8L22.0,29.0l0.0,15.2l2.0,0.0l8.6,-8.6l4.6,4.6l2.8,-2.8L10.8,8.2zM26.0,36.5L26.0,29.0l3.8,3.8L26.0,36.5z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
new file mode 100644
index 0000000..71df4d3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24.0dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24.0dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M29.41,19.0L34.0,14.41L34.0,22.0l1.0,0.0l5.71,-5.71 -4.3,-4.29 4.29,-4.29L35.0,2.0l-1.0,0.0l0.0,7.59L29.41,5.0 28.0,6.41 33.59,12.0 28.0,17.59 29.41,19.0zM36.0,5.83l1.88,1.88L36.0,9.59L36.0,5.83zm0.0,8.58l1.88,1.88L36.0,18.17l0.0,-3.76zM40.0,31.0c-2.49,0.0 -4.89,-0.4 -7.14,-1.14 -0.69,-0.22 -1.48,-0.06 -2.0,0.49l-4.4,4.41c-5.67,-2.88 -10.29,-7.51 -13.18,-13.17l4.4,-4.41c0.55,-0.5 0.71,-1.3 0.49,-2.03C17.4,12.9 17.0,10.49 17.0,8.0c0.0,-1.11 -0.89,-2.0 -2.0,-2.0L8.0,6.0c-1.11,0.0 -2.0,0.89 -2.0,2.0 0.0,18.78 15.22,34.0 34.0,34.0 1.11,0.0 2.0,-0.89 2.0,-2.0l0.0,-7.0c0.0,-1.11 -0.89,-2.0 -2.0,-2.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_collapse.xml b/packages/SystemUI/res/drawable/ic_volume_collapse.xml
new file mode 100644
index 0000000..dc6d301
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_collapse.xml
@@ -0,0 +1,62 @@
+<!--
+     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:name="ic_volume_collapse"
+    android:height="24dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24"
+    android:width="24dp" >
+
+    <group
+        android:name="chevron_02"
+        android:rotation="90"
+        android:translateX="12"
+        android:translateY="9" >
+        <group
+            android:name="rectangle_2"
+            android:rotation="-45" >
+            <group
+                android:name="rectangle_2_pivot"
+                android:translateY="4" >
+                <group
+                    android:name="rectangle_path_2_position"
+                    android:translateY="-1" >
+                    <path
+                        android:name="rectangle_path_2"
+                        android:fillColor="#FFFFFFFF"
+                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="rectangle_1"
+            android:rotation="45" >
+            <group
+                android:name="rectangle_1_pivot"
+                android:translateY="-4" >
+                <group
+                    android:name="rectangle_path_1_position"
+                    android:translateY="1" >
+                    <path
+                        android:name="rectangle_path_1"
+                        android:fillColor="#FFFFFFFF"
+                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_collapse_animation.xml b/packages/SystemUI/res/drawable/ic_volume_collapse_animation.xml
new file mode 100644
index 0000000..5c482bc
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_collapse_animation.xml
@@ -0,0 +1,29 @@
+<!--
+     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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/ic_volume_collapse" >
+
+    <target
+        android:name="chevron_02"
+        android:animation="@anim/ic_volume_collapse_chevron_02_animation" />
+    <target
+        android:name="rectangle_2"
+        android:animation="@anim/ic_volume_collapse_rectangle_2_animation" />
+    <target
+        android:name="rectangle_1"
+        android:animation="@anim/ic_volume_collapse_rectangle_1_animation" />
+
+</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_expand.xml b/packages/SystemUI/res/drawable/ic_volume_expand.xml
new file mode 100644
index 0000000..a60623f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_expand.xml
@@ -0,0 +1,62 @@
+<!--
+     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:name="ic_volume_expand"
+    android:height="24dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24"
+    android:width="24dp" >
+
+    <group
+        android:name="chevron_01"
+        android:rotation="90"
+        android:translateX="12"
+        android:translateY="15" >
+        <group
+            android:name="rectangle_3"
+            android:rotation="45" >
+            <group
+                android:name="rectangle_2_pivot_0"
+                android:translateY="4" >
+                <group
+                    android:name="rectangle_path_3_position"
+                    android:translateY="-1" >
+                    <path
+                        android:name="rectangle_path_3"
+                        android:fillColor="#FFFFFFFF"
+                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+        <group
+            android:name="rectangle_4"
+            android:rotation="-45" >
+            <group
+                android:name="rectangle_1_pivot_0"
+                android:translateY="-4" >
+                <group
+                    android:name="rectangle_path_4_position"
+                    android:translateY="1" >
+                    <path
+                        android:name="rectangle_path_4"
+                        android:fillColor="#FFFFFFFF"
+                        android:pathData="M -1.0,-4.0 l 2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -2.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-8.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_expand_animation.xml b/packages/SystemUI/res/drawable/ic_volume_expand_animation.xml
new file mode 100644
index 0000000..ae2d7e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_expand_animation.xml
@@ -0,0 +1,29 @@
+<!--
+     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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/ic_volume_expand" >
+
+    <target
+        android:name="chevron_01"
+        android:animation="@anim/ic_volume_expand_chevron_01_animation" />
+    <target
+        android:name="rectangle_3"
+        android:animation="@anim/ic_volume_expand_rectangle_3_animation" />
+    <target
+        android:name="rectangle_4"
+        android:animation="@anim/ic_volume_expand_rectangle_4_animation" />
+
+</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_media.xml b/packages/SystemUI/res/drawable/ic_volume_media.xml
new file mode 100644
index 0000000..97089f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_media.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24.0dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
+    android:width="24.0dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M12.0,3.0l0.0,9.28c-0.47,-0.17 -0.97,-0.28 -1.5,-0.28C8.01,12.0 6.0,14.01 6.0,16.5S8.01,21.0 10.5,21.0c2.31,0.0 4.2,-1.75 4.45,-4.0L15.0,17.0L15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
new file mode 100644
index 0000000..beb806c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
@@ -0,0 +1,29 @@
+<!--
+     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:height="24.0dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
+    android:width="24.0dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0l0.0,5.6l3.0,3.0C15.0,8.8 15.0,6.0 15.0,6.0z" />
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M4.8,3.9L3.5,5.1l6.9,6.9C8.0,12.1 6.0,14.0 6.0,16.5C6.0,19.0 8.0,21.0 10.5,21.0c2.7,0.0 4.5,-2.3 4.5,-4.3c0.0,0.0 0.0,-0.1 0.0,-0.1l4.0,4.0l1.3,-1.3L4.8,3.9z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_remote.xml b/packages/SystemUI/res/drawable/ic_volume_remote.xml
new file mode 100644
index 0000000..b363178
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_remote.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM38.0,14.0L10.0,14.0l0.0,3.3c7.9,2.6 14.2,8.8 16.7,16.7L38.0,34.0L38.0,14.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0zM42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml b/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml
new file mode 100644
index 0000000..5f39ad7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml
@@ -0,0 +1,38 @@
+<!--
+     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:height="24.0dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
+    android:width="24.0dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M23.7,21.3l-1.1,-1.0c0.0,0.0 0.0,0.0 0.0,0.0L21.0,18.8l0.0,0.0L5.8,5.0l0.0,0.0L3.6,3.0l0.0,0.0L1.7,1.3L0.3,2.7l1.1,1.0C1.2,4.1 1.0,4.5 1.0,5.0l0.0,3.0l2.0,0.0L3.0,5.2L18.2,19.0L14.0,19.0l0.0,2.0l6.4,0.0l1.9,1.7L23.7,21.3z" />
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M21.0,5.0l0.0,11.1l2.0,1.8L23.0,5.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0L6.6,3.0l2.2,2.0L21.0,5.0z" />
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M1.0,18.0l0.0,3.0l3.0,0.0C4.0,19.3 2.7,18.0 1.0,18.0z" />
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M1.0,14.0l0.0,2.0c2.8,0.0 5.0,2.2 5.0,5.0l2.0,0.0C8.0,17.1 4.9,14.0 1.0,14.0z" />
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M1.0,10.0l0.0,2.0c5.0,0.0 9.0,4.0 9.0,9.0l2.0,0.0C12.0,14.9 7.1,10.0 1.0,10.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer.xml b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
new file mode 100644
index 0000000..c566d5a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
+    android:width="24dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
new file mode 100644
index 0000000..0c20361
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M23.000000,44.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000l-8.000000,0.000000C19.000000,42.200001 20.799999,44.000000 23.000000,44.000000zM36.000000,21.000000c0.000000,-6.100000 -4.300000,-11.300000 -10.000000,-12.600000L26.000000,7.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,1.400000c-1.000000,0.200000 -2.000000,0.600000 -2.900000,1.100000L36.000000,28.400000L36.000000,21.000000zM35.500000,38.000000l4.000000,4.000000l2.500000,-2.500000L8.500000,6.000000L6.000000,8.500000l5.800000,5.800000C10.700000,16.299999 10.000000,18.600000 10.000000,21.000000l0.000000,11.000000l-4.000000,4.000000l0.000000,2.000000L35.500000,38.000000z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
new file mode 100644
index 0000000..38b3234
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
+    android:width="24dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M0.0,15.0l2.0,0.0L2.0,9.0L0.0,9.0L0.0,15.0zM3.0,17.0l2.0,0.0L5.0,7.0L3.0,7.0L3.0,17.0zM22.0,9.0l0.0,6.0l2.0,0.0L24.0,9.0L22.0,9.0zM19.0,17.0l2.0,0.0L21.0,7.0l-2.0,0.0L19.0,17.0zM16.5,3.0l-9.0,0.0C6.7,3.0 6.0,3.7 6.0,4.5l0.0,15.0C6.0,20.3 6.7,21.0 7.5,21.0l9.0,0.0c0.8,0.0 1.5,-0.7 1.5,-1.5l0.0,-15.0C18.0,3.7 17.3,3.0 16.5,3.0zM16.0,19.0L8.0,19.0L8.0,5.0l8.0,0.0L16.0,19.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_settings.xml b/packages/SystemUI/res/drawable/ic_volume_settings.xml
new file mode 100644
index 0000000..9f79b5a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_settings.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="20dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
+    android:width="20dp" >
+
+    <path
+        android:fillColor="@color/volume_settings_icon_color"
+        android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_system.xml b/packages/SystemUI/res/drawable/ic_volume_system.xml
new file mode 100644
index 0000000..ccd8e18
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_system.xml
@@ -0,0 +1,32 @@
+<!--
+     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:height="24.0dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
+    android:width="24.0dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M17.7,14.8l-4.5,-2.3c-0.2,-0.1 -0.4,-0.1 -0.5,-0.1l-0.8,0.0l0.0,-6.0c0.0,-0.8 -0.7,-1.5 -1.5,-1.5S8.9,5.6 8.9,6.4l0.0,10.7l-3.4,-0.7c-0.1,0.0 -0.2,0.0 -0.2,0.0c-0.3,0.0 -0.6,0.1 -0.8,0.3l-0.8,0.8l4.9,4.9c0.3,0.3 0.6,0.4 1.1,0.4l6.8,0.0c0.8,0.0 1.3,-0.6 1.4,-1.3l0.8,-5.3c0.0,-0.1 0.0,-0.1 0.0,-0.2C18.6,15.5 18.2,15.0 17.7,14.8z" />
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M14.3,8.8l1.8,0.9c1.5,-2.0 1.4,-4.8 -0.4,-6.6l-1.4,1.4C15.5,5.7 15.5,7.6 14.3,8.8z" />
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M17.9,10.6l1.8,0.9C22.0,8.0 21.6,3.3 18.5,0.3l-1.4,1.4C19.5,4.1 19.8,7.9 17.9,10.6z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_system_mute.xml b/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
new file mode 100644
index 0000000..dfcb655
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
@@ -0,0 +1,35 @@
+<!--
+     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:height="24.0dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
+    android:width="24.0dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M14.3,8.8l1.8,0.9c1.5,-2.0 1.4,-4.8 -0.4,-6.6l-1.4,1.4C15.5,5.7 15.5,7.6 14.3,8.8z" />
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M17.9,10.6l1.8,0.9C22.0,8.0 21.6,3.3 18.5,0.3l-1.4,1.4C19.5,4.1 19.8,7.9 17.9,10.6z" />
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M22.0,20.6l-3.5,-2.8l0.0,0.0l-9.6,-7.6l0.0,0.0L3.2,5.7L2.0,7.3l6.9,5.4L8.9,17.0l-3.4,-0.7c-0.1,0.0 -0.2,0.0 -0.2,0.0c-0.3,0.0 -0.6,0.1 -0.8,0.3l-0.8,0.8l4.9,4.9c0.3,0.3 0.6,0.4 1.1,0.4l6.8,0.0c0.8,0.0 1.3,-0.6 1.4,-1.3l0.2,-1.5l2.6,2.1L22.0,20.6z" />
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M11.9,6.4c0.0,-0.8 -0.7,-1.5 -1.5,-1.5S8.9,5.6 8.9,6.4l0.0,1.5l3.0,2.4L11.9,6.4z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_voice.xml b/packages/SystemUI/res/drawable/ic_volume_voice.xml
new file mode 100644
index 0000000..133253e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_voice.xml
@@ -0,0 +1,26 @@
+<!--
+     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:height="24.0dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24.0dp" >
+
+    <path
+        android:fillColor="@color/volume_icon_color"
+        android:pathData="M13.25,21.59c2.88,5.66 7.51,10.29 13.18,13.17l4.4,-4.41c0.55,-0.55 1.34,-0.71 2.03,-0.49C35.1,30.6 37.51,31.0 40.0,31.0c1.11,0.0 2.0,0.89 2.0,2.0l0.0,7.0c0.0,1.11 -0.89,2.0 -2.0,2.0C21.22,42.0 6.0,26.78 6.0,8.0c0.0,-1.1 0.9,-2.0 2.0,-2.0l7.0,0.0c1.11,0.0 2.0,0.89 2.0,2.0 0.0,2.4 0.4,4.9 1.14,7.1 0.2,0.6 0.06,1.48 -0.49,2.03l-4.4,4.42z" />
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_no_sims.xml b/packages/SystemUI/res/drawable/stat_sys_no_sims.xml
index 8bad226..2229c99 100644
--- a/packages/SystemUI/res/drawable/stat_sys_no_sims.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_no_sims.xml
@@ -20,6 +20,6 @@
         android:viewportHeight="24.0">
 
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M19.0,5.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0l-7.0,0.0L7.7,5.3L19.0,16.7L19.0,5.0zM3.7,3.9L2.4,5.2L5.0,7.8L5.0,19.0c0.0,1.1 0.9,2.0 2.0,2.0l10.0,0.0c0.4,0.0 0.7,-0.1 1.0,-0.3l1.9,1.9l1.3,-1.3L3.7,3.9z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
index e1e81fd..643c4f9 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
@@ -20,12 +20,12 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
     <path
         android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
-        android:fillColor="#4DFFFFFF"/>
+        android:fillColor="?attr/backgroundColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
index c0dfcf4..e267d25 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
@@ -20,6 +20,6 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
index d1124ee..64781c3 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
@@ -20,15 +20,15 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/>
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M17.7,8.0l4.299999,0.0 0.0,-6.0 -20.0,20.0 15.700001,0.0z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml
index 29eda94..60822f4 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml
@@ -20,9 +20,9 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
index 537c788..eb2be08 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
@@ -20,15 +20,15 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M13.900000,10.000000l-11.900000,12.000000 11.900000,0.000000z"/>
     <path
         android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
-        android:fillColor="#4DFFFFFF"/>
+        android:fillColor="?attr/backgroundColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml
index 7d9376e..5e68eed 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml
@@ -20,9 +20,9 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M14.000000,10.000000l-12.000000,12.000000 12.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
index 09fe33a..22afad0 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
@@ -20,15 +20,15 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.700001,19.900000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.700001,9.900000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M16.700001,7.200000l-14.700001,14.700000 14.700001,0.000000z"/>
     <path
         android:pathData="M17.700001,7.900000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
-        android:fillColor="#4DFFFFFF"/>
+        android:fillColor="?attr/backgroundColor"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml
index 8ec5500..599b34a 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml
@@ -20,9 +20,9 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M16.700001,7.300000l-14.700001,14.700000 14.700001,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
index bb98541..d1e866d 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
@@ -19,13 +19,14 @@
         android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
+
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M2.000000,22.000000l15.700001,0.000000 0.000000,-14.000000 4.299999,0.000000 0.000000,-6.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml
index a468410..b66d89a 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml
@@ -20,6 +20,6 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_null.xml b/packages/SystemUI/res/drawable/stat_sys_signal_null.xml
index d25fc1c..2b487f9e 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_null.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_null.xml
@@ -20,6 +20,6 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M2.000000,22.000000l20.000000,0.000000L22.000000,2.000000L2.000000,22.000000zM20.000000,20.000000L6.800000,20.000000L20.000000,6.800000L20.000000,20.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
index be930e8..7f1b715e 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
@@ -19,12 +19,12 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M19.000000,8.000000l5.300000,0.000000l1.200000,-1.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0_fully.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0_fully.xml
index b2691f6..60f7eb6 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0_fully.xml
@@ -19,6 +19,6 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
index dde781d..acd89be 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
@@ -19,15 +19,15 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M13.000000,22.000000l5.500000,-6.800000c-0.200000,-0.200000 -2.300000,-1.900000 -5.500000,-1.900000s-5.300000,1.800000 -5.500000,1.900000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1_fully.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1_fully.xml
index 65931f4..554350d 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1_fully.xml
@@ -19,9 +19,9 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M13.100000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.500000,6.500000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M13.100000,22.000000l5.500000,-6.800000c-0.200000,-0.200000 -2.300000,-1.900000 -5.500000,-1.900000s-5.300000,1.800000 -5.500000,1.900000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
index 63d9dca..f33b25c 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
@@ -19,15 +19,15 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M19.000000,11.600000c-1.300000,-0.700000 -3.400000,-1.600000 -6.000000,-1.600000c-4.400000,0.000000 -7.300000,2.400000 -7.600000,2.700000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,11.600000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2_fully.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2_fully.xml
index 7ba4895..2c2465a 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2_fully.xml
@@ -19,9 +19,9 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M13.000000,22.000000l7.600000,-9.400000C20.299999,12.400000 17.400000,10.000000 13.000000,10.000000s-7.300000,2.400000 -7.600000,2.700000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
index 7d393b4..09d2e50 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
@@ -19,15 +19,15 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M19.000000,8.600000c-1.600000,-0.700000 -3.600000,-1.300000 -6.000000,-1.300000c-5.300000,0.000000 -8.900000,3.000000 -9.200000,3.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.600000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3_fully.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3_fully.xml
index e2cde53..7d0f756 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3_fully.xml
@@ -19,9 +19,9 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/fillColor"
         android:pathData="M13.000000,22.000000l9.200000,-11.400000c-0.400000,-0.300000 -3.900000,-3.200000 -9.200000,-3.200000s-8.900000,3.000000 -9.200000,3.200000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
index ec8137f..fb1f584 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
@@ -19,12 +19,12 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4_fully.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4_fully.xml
index 9d02980..a7e213f 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4_fully.xml
@@ -19,6 +19,6 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?attr/singleToneColor"
         android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
index 95c6531..5169de4 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
@@ -19,6 +19,6 @@
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="?attr/backgroundColor"
         android:pathData="M13.000000,2.000000C7.700000,2.000000 3.700000,3.900000 0.400000,6.400000L13.000000,22.000000L25.600000,6.500000C22.299999,4.000000 18.299999,2.000000 13.000000,2.000000zM13.000000,18.600000L3.300000,7.000000l0.000000,0.000000l0.000000,0.000000C6.000000,5.300000 8.700000,4.000000 13.000000,4.000000s7.000000,1.400000 9.700000,3.000000l0.000000,0.000000l0.000000,0.000000L13.000000,18.600000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/vector_drawable_place_bottom_left.xml b/packages/SystemUI/res/drawable/vector_drawable_place_bottom_left.xml
new file mode 100644
index 0000000..cea6324
--- /dev/null
+++ b/packages/SystemUI/res/drawable/vector_drawable_place_bottom_left.xml
@@ -0,0 +1,24 @@
+<!--
+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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M24.0,24.0L24.0,0.0L0.0,0.0l0.0,24.0L24.0,24.0zM4.0,10.0l10.0,0.0l0.0,10.0L4.0,20.0L4.0,10.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/vector_drawable_place_bottom_right.xml b/packages/SystemUI/res/drawable/vector_drawable_place_bottom_right.xml
new file mode 100644
index 0000000..c2ae9c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/vector_drawable_place_bottom_right.xml
@@ -0,0 +1,24 @@
+<!--
+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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M24.0,24.0L24.0,0.0L0.0,0.0l0.0,24.0L24.0,24.0zM20.0,20.0L10.0,20.0L10.0,10.0l10.0,0.0L20.0,20.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/vector_drawable_place_top_left.xml b/packages/SystemUI/res/drawable/vector_drawable_place_top_left.xml
new file mode 100644
index 0000000..feb612c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/vector_drawable_place_top_left.xml
@@ -0,0 +1,24 @@
+<!--
+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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M0.0,0.0l0.0,24.0l24.0,0.0L24.0,0.0L0.0,0.0zM4.0,4.0l10.0,0.0l0.0,10.0L4.0,14.0L4.0,4.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/vector_drawable_place_top_right.xml b/packages/SystemUI/res/drawable/vector_drawable_place_top_right.xml
new file mode 100644
index 0000000..9f4ee49
--- /dev/null
+++ b/packages/SystemUI/res/drawable/vector_drawable_place_top_right.xml
@@ -0,0 +1,24 @@
+<!--
+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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M0.0,0.0l0.0,24.0l24.0,0.0L24.0,0.0L0.0,0.0zM20.0,14.0L10.0,14.0L10.0,4.0l10.0,0.0L20.0,14.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/volume_dialog_background.xml b/packages/SystemUI/res/drawable/volume_dialog_background.xml
new file mode 100644
index 0000000..f09c01b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/volume_dialog_background.xml
@@ -0,0 +1,22 @@
+<!--
+     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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <solid android:color="@color/system_primary_color" />
+
+    <corners android:radius="@dimen/notification_material_rounded_rect_radius" />
+
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/interpolator/ic_volume_collapse_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_volume_collapse_animation_interpolator_0.xml
new file mode 100644
index 0000000..c3930e4
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_volume_collapse_animation_interpolator_0.xml
@@ -0,0 +1,17 @@
+<!--
+     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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.0001,0.0 0.0,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_volume_expand_animation_interpolator_0.xml b/packages/SystemUI/res/interpolator/ic_volume_expand_animation_interpolator_0.xml
new file mode 100644
index 0000000..c3930e4
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_volume_expand_animation_interpolator_0.xml
@@ -0,0 +1,17 @@
+<!--
+     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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.0001,0.0 0.0,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/layout/recents_task_resize_dialog.xml b/packages/SystemUI/res/layout-land/recents_task_resize_dialog.xml
similarity index 77%
copy from packages/SystemUI/res/layout/recents_task_resize_dialog.xml
copy to packages/SystemUI/res/layout-land/recents_task_resize_dialog.xml
index a8c6ee9..a718d4d 100644
--- a/packages/SystemUI/res/layout/recents_task_resize_dialog.xml
+++ b/packages/SystemUI/res/layout-land/recents_task_resize_dialog.xml
@@ -41,20 +41,6 @@
             android:layout_margin="10dp"
             android:background="@drawable/vector_drawable_place_right" />
         <Button
-            android:id="@+id/place_top"
-            android:layout_width="36dp"
-            android:layout_height="36dp"
-            android:layout_weight="1"
-            android:layout_margin="10dp"
-            android:background="@drawable/vector_drawable_place_top" />
-        <Button
-            android:id="@+id/place_bottom"
-            android:layout_width="36dp"
-            android:layout_height="36dp"
-            android:layout_weight="1"
-            android:layout_margin="10dp"
-            android:background="@drawable/vector_drawable_place_bottom" />
-        <Button
             android:id="@+id/place_full"
             android:layout_width="36dp"
             android:layout_height="36dp"
diff --git a/packages/SystemUI/res/layout/recents_task_resize_dialog.xml b/packages/SystemUI/res/layout-port/recents_task_resize_dialog.xml
similarity index 77%
rename from packages/SystemUI/res/layout/recents_task_resize_dialog.xml
rename to packages/SystemUI/res/layout-port/recents_task_resize_dialog.xml
index a8c6ee9..250f53d 100644
--- a/packages/SystemUI/res/layout/recents_task_resize_dialog.xml
+++ b/packages/SystemUI/res/layout-port/recents_task_resize_dialog.xml
@@ -27,20 +27,6 @@
         android:layout_height="wrap_content"
         android:orientation="horizontal">
         <Button
-            android:id="@+id/place_left"
-            android:layout_width="36dp"
-            android:layout_height="36dp"
-            android:layout_weight="1"
-            android:layout_margin="10dp"
-            android:background="@drawable/vector_drawable_place_left" />
-        <Button
-            android:id="@+id/place_right"
-            android:layout_width="36dp"
-            android:layout_height="36dp"
-            android:layout_weight="1"
-            android:layout_margin="10dp"
-            android:background="@drawable/vector_drawable_place_right" />
-        <Button
             android:id="@+id/place_top"
             android:layout_width="36dp"
             android:layout_height="36dp"
diff --git a/packages/SystemUI/res/layout/recents_task_resize_dialog.xml b/packages/SystemUI/res/layout-sw600dp-land/recents_task_resize_dialog.xml
similarity index 77%
copy from packages/SystemUI/res/layout/recents_task_resize_dialog.xml
copy to packages/SystemUI/res/layout-sw600dp-land/recents_task_resize_dialog.xml
index a8c6ee9..26c9b1a 100644
--- a/packages/SystemUI/res/layout/recents_task_resize_dialog.xml
+++ b/packages/SystemUI/res/layout-sw600dp-land/recents_task_resize_dialog.xml
@@ -41,19 +41,33 @@
             android:layout_margin="10dp"
             android:background="@drawable/vector_drawable_place_right" />
         <Button
-            android:id="@+id/place_top"
+            android:id="@+id/place_top_left"
             android:layout_width="36dp"
             android:layout_height="36dp"
             android:layout_weight="1"
             android:layout_margin="10dp"
-            android:background="@drawable/vector_drawable_place_top" />
+            android:background="@drawable/vector_drawable_place_top_left" />
         <Button
-            android:id="@+id/place_bottom"
+            android:id="@+id/place_top_right"
             android:layout_width="36dp"
             android:layout_height="36dp"
             android:layout_weight="1"
             android:layout_margin="10dp"
-            android:background="@drawable/vector_drawable_place_bottom" />
+            android:background="@drawable/vector_drawable_place_top_right" />
+        <Button
+            android:id="@+id/place_bottom_left"
+            android:layout_width="36dp"
+            android:layout_height="36dp"
+            android:layout_weight="1"
+            android:layout_margin="10dp"
+            android:background="@drawable/vector_drawable_place_bottom_left" />
+        <Button
+            android:id="@+id/place_bottom_right"
+            android:layout_width="36dp"
+            android:layout_height="36dp"
+            android:layout_weight="1"
+            android:layout_margin="10dp"
+            android:background="@drawable/vector_drawable_place_bottom_right" />
         <Button
             android:id="@+id/place_full"
             android:layout_width="36dp"
diff --git a/packages/SystemUI/res/layout/recents_task_resize_dialog.xml b/packages/SystemUI/res/layout-sw600dp-port/recents_task_resize_dialog.xml
similarity index 77%
copy from packages/SystemUI/res/layout/recents_task_resize_dialog.xml
copy to packages/SystemUI/res/layout-sw600dp-port/recents_task_resize_dialog.xml
index a8c6ee9..e180daa 100644
--- a/packages/SystemUI/res/layout/recents_task_resize_dialog.xml
+++ b/packages/SystemUI/res/layout-sw600dp-port/recents_task_resize_dialog.xml
@@ -27,20 +27,6 @@
         android:layout_height="wrap_content"
         android:orientation="horizontal">
         <Button
-            android:id="@+id/place_left"
-            android:layout_width="36dp"
-            android:layout_height="36dp"
-            android:layout_weight="1"
-            android:layout_margin="10dp"
-            android:background="@drawable/vector_drawable_place_left" />
-        <Button
-            android:id="@+id/place_right"
-            android:layout_width="36dp"
-            android:layout_height="36dp"
-            android:layout_weight="1"
-            android:layout_margin="10dp"
-            android:background="@drawable/vector_drawable_place_right" />
-        <Button
             android:id="@+id/place_top"
             android:layout_width="36dp"
             android:layout_height="36dp"
@@ -55,6 +41,34 @@
             android:layout_margin="10dp"
             android:background="@drawable/vector_drawable_place_bottom" />
         <Button
+            android:id="@+id/place_top_left"
+            android:layout_width="36dp"
+            android:layout_height="36dp"
+            android:layout_weight="1"
+            android:layout_margin="10dp"
+            android:background="@drawable/vector_drawable_place_top_left" />
+        <Button
+            android:id="@+id/place_top_right"
+            android:layout_width="36dp"
+            android:layout_height="36dp"
+            android:layout_weight="1"
+            android:layout_margin="10dp"
+            android:background="@drawable/vector_drawable_place_top_right" />
+        <Button
+            android:id="@+id/place_bottom_left"
+            android:layout_width="36dp"
+            android:layout_height="36dp"
+            android:layout_weight="1"
+            android:layout_margin="10dp"
+            android:background="@drawable/vector_drawable_place_bottom_left" />
+        <Button
+            android:id="@+id/place_bottom_right"
+            android:layout_width="36dp"
+            android:layout_height="36dp"
+            android:layout_weight="1"
+            android:layout_margin="10dp"
+            android:background="@drawable/vector_drawable_place_bottom_right" />
+        <Button
             android:id="@+id/place_full"
             android:layout_width="36dp"
             android:layout_height="36dp"
diff --git a/packages/SystemUI/res/layout/assist_orb.xml b/packages/SystemUI/res/layout/assist_orb.xml
new file mode 100644
index 0000000..ab0a0a5
--- /dev/null
+++ b/packages/SystemUI/res/layout/assist_orb.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2012, 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.
+*/
+-->
+
+<!-- Extends FrameLayout -->
+<com.android.systemui.assist.AssistOrbContainer
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.android.systemui.statusbar.AlphaOptimizedView
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/assist_orb_scrim_height"
+        android:layout_gravity="bottom"
+        android:id="@+id/assist_orb_scrim"
+        android:background="@drawable/assist_orb_scrim"/>
+
+    <com.android.systemui.assist.AssistOrbView
+        android:id="@+id/assist_orb"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/search_logo"/>
+    </com.android.systemui.assist.AssistOrbView>
+
+    <com.android.systemui.statusbar.AlphaOptimizedView
+        android:id="@+id/assist_orb_navbar_scrim"
+        android:layout_height="@dimen/assist_orb_navbar_scrim_height"
+        android:layout_width="match_parent"
+        android:layout_gravity="bottom"
+        android:elevation="50dp"
+        android:outlineProvider="none"
+        android:background="@drawable/assist_orb_navbar_scrim"/>
+
+</com.android.systemui.assist.AssistOrbContainer>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml
index 97697189..6a4ac2c 100644
--- a/packages/SystemUI/res/layout/mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/mobile_signal_group.xml
@@ -23,11 +23,19 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     >
-    <ImageView
+    <com.android.systemui.statusbar.AlphaOptimizedImageView
+        android:theme="@style/DualToneLightTheme"
         android:id="@+id/mobile_signal"
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
         />
+    <com.android.systemui.statusbar.AlphaOptimizedImageView
+        android:theme="@style/DualToneDarkTheme"
+        android:id="@+id/mobile_signal_dark"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:alpha="0.0"
+        />
     <ImageView
         android:id="@+id/mobile_type"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/segmented_button.xml b/packages/SystemUI/res/layout/segmented_button.xml
index e92f310..ead735f 100644
--- a/packages/SystemUI/res/layout/segmented_button.xml
+++ b/packages/SystemUI/res/layout/segmented_button.xml
@@ -19,10 +19,10 @@
     android:layout_height="wrap_content"
     android:layout_marginStart="@dimen/segmented_button_spacing"
     android:layout_weight="1"
-    android:gravity="center_horizontal|top"
+    android:paddingStart="8dp"
+    android:gravity="start|center_vertical"
+    android:maxLines="2"
     android:textColor="@color/segmented_button_text_selector"
     android:background="@drawable/btn_borderless_rect"
-    android:textAppearance="@style/TextAppearance.QS.SegmentedButton"
-    android:minHeight="64dp"
-    android:paddingTop="11dp"
-    android:drawablePadding="6dp" />
+    android:textAppearance="@style/TextAppearance.Volume.ZenSwitchSummary"
+    android:minHeight="48dp" />
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 8fbd8f7..c9edef8 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -38,11 +38,19 @@
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
         >
-        <ImageView
+        <com.android.systemui.statusbar.AlphaOptimizedImageView
+            android:theme="@style/DualToneLightTheme"
             android:id="@+id/wifi_signal"
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             />
+        <com.android.systemui.statusbar.AlphaOptimizedImageView
+            android:theme="@style/DualToneDarkTheme"
+            android:id="@+id/wifi_signal_dark"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:alpha="0.0"
+            />
     </FrameLayout>
     <View
         android:id="@+id/wifi_signal_spacer"
@@ -56,12 +64,25 @@
         android:layout_width="wrap_content"
         >
     </LinearLayout>
-    <ImageView
-        android:id="@+id/no_sims"
+    <FrameLayout
         android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:src="@drawable/stat_sys_no_sims"
-        />
+        android:layout_width="wrap_content">
+        <com.android.systemui.statusbar.AlphaOptimizedImageView
+            android:theme="@style/DualToneLightTheme"
+            android:id="@+id/no_sims"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:src="@drawable/stat_sys_no_sims"
+            />
+        <com.android.systemui.statusbar.AlphaOptimizedImageView
+            android:theme="@style/DualToneDarkTheme"
+            android:id="@+id/no_sims_dark"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:src="@drawable/stat_sys_no_sims"
+            android:alpha="0.0"
+            />
+    </FrameLayout>
     <View
         android:id="@+id/wifi_airplane_spacer"
         android:layout_width="4dp"
diff --git a/packages/SystemUI/res/layout/status_bar_search_panel.xml b/packages/SystemUI/res/layout/status_bar_search_panel.xml
deleted file mode 100644
index e0520ef6..0000000
--- a/packages/SystemUI/res/layout/status_bar_search_panel.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* apps/common/assets/default/default/skins/StatusBar.xml
-**
-** Copyright 2012, 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.
-*/
--->
-
-<!-- Extends FrameLayout -->
-<com.android.systemui.SearchPanelView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/search_panel_container"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent">
-
-    <com.android.systemui.statusbar.AlphaOptimizedView
-        style="@style/SearchPanelScrim"
-        android:id="@+id/search_panel_scrim"
-        android:background="@drawable/search_panel_scrim" />
-
-    <com.android.systemui.SearchPanelCircleView
-        style="@style/SearchPanelCircle"
-        android:id="@+id/search_panel_circle">
-
-        <ImageView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:id="@+id/search_logo" />
-    </com.android.systemui.SearchPanelCircleView>
-
-</com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 3765fe8..7586227 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -1,6 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
-     Copyright (C) 2014 The Android Open Source Project
+     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.
@@ -14,15 +13,50 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/volume_dialog"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:layout_marginBottom="4dp"
     android:layout_marginLeft="@dimen/notification_side_padding"
     android:layout_marginRight="@dimen/notification_side_padding"
-    android:background="@drawable/qs_background_primary"
-    android:translationZ="@dimen/volume_panel_z"
-    android:layout_marginBottom="@dimen/volume_panel_z">
+    android:layout_marginTop="4dp"
+    android:background="@drawable/volume_dialog_background"
+    android:translationZ="4dp" >
 
-        <include layout="@layout/volume_panel" />
+    <com.android.keyguard.AlphaOptimizedImageButton
+        android:id="@+id/volume_expand_button"
+        style="@style/VolumeButtons"
+        android:layout_alignParentLeft="true"
+        android:layout_width="@dimen/volume_button_size"
+        android:layout_height="@dimen/volume_button_size"
+        android:clickable="true"
+        android:soundEffectsEnabled="false"
+        android:src="@drawable/ic_volume_collapse_animation" />
 
-</FrameLayout>
\ No newline at end of file
+    <LinearLayout
+        android:id="@+id/volume_dialog_content"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:paddingBottom="4dp"
+        android:paddingEnd="4dp"
+        android:paddingStart="4dp"
+        android:paddingTop="6dp" >
+
+        <!-- volume rows added and removed here! :-) -->
+
+        <FrameLayout
+            android:id="@+id/volume_footer"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            tools:ignore="UselessParent" >
+
+            <include layout="@layout/volume_text_footer" />
+
+            <include layout="@layout/volume_zen_footer" />
+        </FrameLayout>
+    </LinearLayout>
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
new file mode 100644
index 0000000..af27cc4
--- /dev/null
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -0,0 +1,64 @@
+<!--
+     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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:clipChildren="false" >
+
+    <TextView
+        android:id="@+id/volume_row_header"
+        style="?android:attr/textAppearanceButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:alpha="@dimen/volume_secondary_alpha"
+        android:ellipsize="end"
+        android:maxLines="1"
+        android:paddingBottom="0dp"
+        android:paddingEnd="12dp"
+        android:paddingStart="13dp"
+        android:paddingTop="8dp" />
+
+    <com.android.keyguard.AlphaOptimizedImageButton
+        android:id="@+id/volume_row_icon"
+        style="@style/VolumeButtons"
+        android:layout_width="@dimen/volume_button_size"
+        android:layout_height="@dimen/volume_button_size"
+        android:layout_below="@id/volume_row_header"
+        android:soundEffectsEnabled="false" />
+
+    <SeekBar
+        android:id="@+id/volume_row_slider"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBottom="@+id/volume_row_icon"
+        android:layout_alignWithParentIfMissing="true"
+        android:layout_below="@id/volume_row_header"
+        android:layout_toEndOf="@id/volume_row_icon"
+        android:layout_toStartOf="@+id/volume_settings_button"
+        android:paddingEnd="4dp"
+        android:paddingStart="4dp"
+        android:progressTint="@android:color/white"
+        android:thumbTint="@android:color/white" />
+
+    <com.android.keyguard.AlphaOptimizedImageButton
+        android:id="@+id/volume_settings_button"
+        style="@style/VolumeButtons"
+        android:layout_width="@dimen/volume_button_size"
+        android:layout_height="@dimen/volume_button_size"
+        android:layout_alignParentEnd="true"
+        android:layout_below="@id/volume_row_header" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/volume_panel_dialog.xml b/packages/SystemUI/res/layout/volume_panel_dialog.xml
new file mode 100644
index 0000000..700102f
--- /dev/null
+++ b/packages/SystemUI/res/layout/volume_panel_dialog.xml
@@ -0,0 +1,27 @@
+<!--
+     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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginBottom="@dimen/volume_panel_z"
+    android:layout_marginLeft="@dimen/notification_side_padding"
+    android:layout_marginRight="@dimen/notification_side_padding"
+    android:background="@drawable/qs_background_primary"
+    android:translationZ="@dimen/volume_panel_z" >
+
+    <include layout="@layout/volume_panel" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/volume_text_footer.xml b/packages/SystemUI/res/layout/volume_text_footer.xml
new file mode 100644
index 0000000..7436488
--- /dev/null
+++ b/packages/SystemUI/res/layout/volume_text_footer.xml
@@ -0,0 +1,54 @@
+<!--
+     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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/volume_text_footer"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:visibility="gone"
+    tools:ignore="UselessParent" >
+
+    <TextView
+        android:id="@+id/volume_footline_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBaseline="@+id/volume_footline_action_button"
+        android:alpha="@dimen/volume_secondary_alpha"
+        android:fontFamily="sans-serif"
+        android:paddingEnd="8dp"
+        android:paddingStart="13dp"
+        android:textColor="?android:attr/textColorPrimary" />
+
+    <Button
+        android:id="@+id/volume_footline_action_button"
+        style="@android:style/Widget.Material.Button.Borderless"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/volume_button_size"
+        android:layout_toEndOf="@id/volume_footline_text"
+        android:layout_toStartOf="@+id/volume_settings_button"
+        android:alpha="@dimen/volume_secondary_alpha"
+        android:paddingEnd="0dp"
+        android:paddingStart="0dp" />
+
+    <com.android.keyguard.AlphaOptimizedImageButton
+        android:id="@+id/volume_settings_button"
+        style="@style/VolumeButtons"
+        android:layout_width="@dimen/volume_button_size"
+        android:layout_height="@dimen/volume_button_size"
+        android:layout_alignParentEnd="true"
+        android:src="@drawable/ic_volume_settings" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml
new file mode 100644
index 0000000..c491e9c
--- /dev/null
+++ b/packages/SystemUI/res/layout/volume_zen_footer.xml
@@ -0,0 +1,108 @@
+<!--
+     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.
+-->
+<com.android.systemui.volume.ZenFooter xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/volume_zen_footer"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical" > <!-- extends LinearLayout -->
+
+    <LinearLayout
+        android:id="@+id/volume_zen_switch_bar"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/volume_button_size"
+        android:clickable="true"
+        android:orientation="horizontal" >
+
+        <ImageView
+            android:id="@+id/volume_zen_switch_bar_icon"
+            android:layout_width="@dimen/volume_button_size"
+            android:layout_height="@dimen/volume_button_size"
+            android:scaleType="center"
+            android:src="@drawable/ic_dnd" />
+
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="1"
+            android:gravity="center_vertical"
+            android:textDirection="locale"
+            android:padding="3dp"
+            android:text="@string/volume_zen_switch_text"
+            android:textAppearance="@style/TextAppearance.Volume.ZenSwitch" />
+
+        <Switch
+            android:id="@+id/volume_zen_switch"
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:layout_marginEnd="11dp" />
+    </LinearLayout>
+
+    <RelativeLayout
+        android:id="@+id/volume_zen_panel_summary"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/volume_button_size"
+        android:layout_marginStart="@dimen/volume_button_size"
+        android:paddingEnd="3dp"
+        android:paddingStart="3dp" >
+
+        <TextView
+            android:id="@+id/volume_zen_panel_summary_line_1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textAppearance="@style/TextAppearance.Volume.ZenSwitchSummary" />
+
+        <TextView
+            android:id="@+id/volume_zen_panel_summary_line_2"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/volume_zen_panel_summary_line_1"
+            android:textAppearance="@style/TextAppearance.Volume.ZenSwitchDetail" />
+    </RelativeLayout>
+
+    <include layout="@layout/zen_mode_panel" />
+
+    <LinearLayout
+        android:id="@+id/volume_zen_mode_panel_buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="end" >
+
+        <TextView
+            android:id="@+id/volume_zen_mode_panel_more"
+            style="@style/QSBorderlessButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="8dp"
+            android:clickable="true"
+            android:focusable="true"
+            android:minWidth="132dp"
+            android:text="@string/quick_settings_more_settings"
+            android:textAppearance="@style/TextAppearance.QS.DetailButton" />
+
+        <TextView
+            android:id="@+id/volume_zen_mode_panel_done"
+            style="@style/QSBorderlessButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:clickable="true"
+            android:focusable="true"
+            android:minWidth="66dp"
+            android:text="@string/quick_settings_done"
+            android:textAppearance="@style/TextAppearance.QS.DetailButton" />
+    </LinearLayout>
+
+</com.android.systemui.volume.ZenFooter>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/zen_mode_condition.xml b/packages/SystemUI/res/layout/zen_mode_condition.xml
index 0b91913..a169d1a 100644
--- a/packages/SystemUI/res/layout/zen_mode_condition.xml
+++ b/packages/SystemUI/res/layout/zen_mode_condition.xml
@@ -18,8 +18,8 @@
     android:layout_width="match_parent"
     android:layout_height="@dimen/qs_detail_item_height"
     android:layout_marginBottom="@dimen/zen_mode_condition_detail_item_spacing"
-    android:layout_marginStart="@dimen/zen_mode_condition_detail_button_padding"
-    android:layout_marginEnd="@dimen/zen_mode_condition_detail_button_padding" >
+    android:layout_marginStart="1dp"
+    android:layout_marginEnd="0dp" >
 
     <RadioButton
         android:id="@android:id/checkbox"
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 33c1899..3d73ff7 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -19,6 +19,7 @@
     android:id="@+id/zen_mode_panel"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:layout_marginStart="35dp"
     android:clipChildren="false"
     android:orientation="vertical" >
 
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index d234701..a98993c 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Skakel batterybespaarder aan"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Instellings"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Vliegtuigmodus"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Outodraai skerm"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEMP"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"OUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ontsluit"</string>
     <string name="phone_label" msgid="2320074140205331708">"maak foon oop"</string>
     <string name="camera_label" msgid="7261107956054836961">"maak kamera oop"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Kies nuwe taakuitleg"</string>
+    <string name="cancel" msgid="6442560571259935130">"Kanselleer"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Versoenbaarheid-zoem se knoppie."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoem kleiner na groter skerm."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth gekoppel."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Vliegtuigmodus aangeskakel."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Moenie steur nie aan, net prioriteit."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Moenie steur nie aan, geen onderbrekings nie."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Moenie steur nie af."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Moenie steur nie is afgeskakel."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Moenie steur nie is aangeskakel."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Nageregkas"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Sluimer"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Vliegtuigmodus"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Moenie steur nie"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Net prioriteit"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Geen onderbrekings nie"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> toestelle)"</string>
@@ -301,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Geen onderbrekings nie. Nie eens wekkers nie."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Geen onderbrekings nie"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Net prioriteitonderbrekings"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Jou volgende wekker is om <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Jou volgende wekker is <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Jy sal nie jou wekker om <xliff:g id="ALARM_TIME">%s</xliff:g> hoor nie"</string>
@@ -310,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Sleep op om te ontsluit"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Sleep regs vir foon"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Sleep links vir kamera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Geen"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioriteit"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Alles"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laai tans (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tot vol)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Wissel gebruiker"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Wissel gebruiker, huidige gebruiker <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -380,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Weier"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is die volumedialoog"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Raak om die oorspronklike terug te stel."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 827a8a3..db9b25e 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"ባትሪ ቆጣቢን አብራ"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ቅንብሮች"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"የአውሮፕላን ሁነታ"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"ማያ በራስ ሰር አሽከርክር"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ድምጽ አጥፋ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ራስ ሰር"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ክፈት"</string>
     <string name="phone_label" msgid="2320074140205331708">"ስልክ ክፈት"</string>
     <string name="camera_label" msgid="7261107956054836961">"ካሜራ ክፈት"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"የአዲስ ተግባር አቀማመጥን ይምረጡ"</string>
+    <string name="cancel" msgid="6442560571259935130">"ይቅር"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"የተኳኋኝአጉላ አዝራር።"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"አነስተኛውን ማያ ወደ ትልቅ አጉላ።"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ብሉቱዝ ተያይዟል።"</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"የአውሮፕላን ሁነታ በርቷል።"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"አትረብሽ በርቷል፣ ቅድሚያ የሚሰጠው ብቻ።"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"አትረብሽ በርቷል፣ ምንም ማቋረጦች የሉም።"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"አትረብሽ ጠፍቷል።"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"አትረብሽ ጠፍቷል።"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"አትረብሽ በርቷል።"</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"የማወራረጃ ምግቦች መያዣ"</string>
     <string name="start_dreams" msgid="7219575858348719790">"የቀን ህልም"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ኤተርኔት"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"የአውሮፕላን ሁነታ"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"አትረብሽ"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"ቅድሚያ የሚሰጠው ብቻ"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"ምንም ማቋረጦች የሉም"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ብሉቱዝ"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ብሉቱዝ (<xliff:g id="NUMBER">%d</xliff:g> መሣሪያዎች)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ምንም አውታረ መረብ የለም"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ጠፍቷል"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"ምንም የተቀመጡ አውታረ መረቦች አይገኙም"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"ውሰድ"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"በመውሰድ ላይ"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"ያልተሰየመ መሳሪያ"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"ለመውሰድ ዝግጁ"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"ምንም ማቋረጦች የሉም። ማንቂያዎችም እንኳ።"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"ምንም ማቋረጦች የሉም"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"ቅድሚያ የሚሰጣቸው ማቋረጦች ብቻ"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"ቀጣዩ ማንቂያ ደውልዎ በ<xliff:g id="ALARM_TIME">%s</xliff:g> ነው"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"ቀጣዩ ማንቂያ ደውልዎ <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> ነው"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"በ<xliff:g id="ALARM_TIME">%s</xliff:g> ያለውን ማንቂያ ደውልዎን አይሰሙትም"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"ለማስከፈት ወደ ላይ ያንሸራትቱ"</string>
     <string name="phone_hint" msgid="3101468054914424646">"ለስልክ ወደቀኝ ያንሸራትቱ"</string>
     <string name="camera_hint" msgid="5241441720959174226">"ለካሜራ ወደግራ ያንሸራትቱ"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"ምንም"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"ቅድሚያ"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"ሁሉም"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ሃይል በመሙላት ላይ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> እስከሚሞላ ድረስ)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ተጠቃሚ ቀይር"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ተጠቃሚ ይለውጡ፣ የአሁን ተጠቃሚ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ከልክል"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> የድምጽ መጠን መገናኛው ነው"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"የመጀመሪያውን ወደነበረበት ለመመለስ ይንኩ።"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 2bcb2c1..9fe45c4 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -48,7 +48,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"تشغيل توفير شحن البطارية"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"الإعدادات"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"وضع الطائرة"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"التدوير التلقائي للشاشة"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"كتم"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"تلقائي"</string>
@@ -92,6 +91,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"إلغاء القفل"</string>
     <string name="phone_label" msgid="2320074140205331708">"فتح الهاتف"</string>
     <string name="camera_label" msgid="7261107956054836961">"فتح الكاميرا"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"تحديد تنسيق جديد للمهمة"</string>
+    <string name="cancel" msgid="6442560571259935130">"إلغاء"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"زر تكبير/تصغير للتوافق."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"استخدام التكبير/التصغير لتحويل شاشة صغيرة إلى شاشة أكبر"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"تم توصيل البلوتوث."</string>
@@ -182,6 +183,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"تم تشغيل وضع الطائرة."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"تم تشغيل الرجاء عدم الإزعاج، الأولوية فقط."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"تم تشغيل \"الرجاء عدم الإزعاج\"، ممنوع الإزعاج."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"تم تشغيل الرجاء عدم الإزعاج، التنبيهات فقط."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"تم تعطيل \"الرجاء عدم الإزعاج\"."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"تم تعطيل \"الرجاء عدم الإزعاج\"."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"تم تشغيل \"الرجاء عدم الإزعاج\"."</string>
@@ -232,9 +234,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"حالة الحلويات"</string>
     <string name="start_dreams" msgid="7219575858348719790">"حلم اليقظة"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"وضع الطائرة"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"الرجاء عدم الإزعاج"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"الأولوية فقط"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"التنبيهات فقط"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"عدم الإزعاج"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوتوث"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوتوث (<xliff:g id="NUMBER">%d</xliff:g> من الأجهزة)"</string>
@@ -305,6 +307,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"عدم المقاطعة، ولا بالتنبيهات كذلك."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"بدون مقاطعات"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"المقاطعات ذات الأولوية فقط"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"التنبيهات فقط"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"التنبيه المقبل في <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"التنبيه المقبل في <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"لن تسمع المنبهات في <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -314,9 +317,15 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"مرر سريعًا لأعلى لإلغاء القفل"</string>
     <string name="phone_hint" msgid="3101468054914424646">"مرر سريعًا إلى اليسار لفتح الهاتف"</string>
     <string name="camera_hint" msgid="5241441720959174226">"مرر سريعًا إلى اليمين لفتح الكاميرا"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"بدون"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"الأولوية"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"التنبيهات فقط"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"الكل"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"عدم\nالإزعاج"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"الأولوية \nفقط"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"التنبيهات\nفقط"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"جارٍ الشحن (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> حتى الامتلاء)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"تبديل المستخدم"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"تبديل المستخدم، المستخدم الحالي <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -384,4 +393,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"رفض"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> هو مربع حوار مستوى الصوت"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"المس لاستعادة الإعداد الأصلي."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a4251be..0909f48 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Включване на режима за запазване на батерията"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Настройки"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Самолетен режим"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Авт. завъртане на екрана"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"БЕЗ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АВТ."</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"отключване"</string>
     <string name="phone_label" msgid="2320074140205331708">"отваряне на телефона"</string>
     <string name="camera_label" msgid="7261107956054836961">"отваряне на камерата"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Избиране на ново оформление за задачите"</string>
+    <string name="cancel" msgid="6442560571259935130">"Отказ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Бутон за промяна на мащаба с цел съвместимост."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Промяна на мащаба на екрана от по-малък до по-голям."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth е включен."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Самолетният режим се включи."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Настройката „Не безпокойте“ е включена – само с приоритет."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Настройката „Не безпокойте“ е включена – без прекъсвания."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Настройката „Не безпокойте“ е изключена."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Настройката „Не безпокойте“ е изключена."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Настройката „Не безпокойте“ е включена."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Витрина с десерти"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Мечта"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Самолетен режим"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Не безпокойте"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Само с приоритет"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Без прекъсвания"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> устройства)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Няма мрежа"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi е изключен"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Няма налични запазени мрежи"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Предаване"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Предава се"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Устройство без име"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Готово за предаване"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Без прекъсвания. Дори без будилници."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Без прекъсвания"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Само приоритетни прекъсвания"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Следващият ви будилник е в <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Следващият ви будилник е в/ъв <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Няма да чуете будилника си в <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Прекарайте пръст нагоре, за да отключите"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Прекарайте пръст надясно, за да използвате телефона"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Прекарайте пръст наляво, за да включите камерата"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Няма"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Приоритет"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Всички"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Зарежда се (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до пълно зареждане)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Превключване между потребителите"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Превключване на потребителя – текущият е <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Отказване"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> изпълнява ролята на диалоговия прозорец за силата на звука"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Докоснете, за да възстановите оригинала."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index b085767..bd44893 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"ব্যাটারি সঞ্চয়কারী চালু"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"সেটিংস"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"বিমান মোড"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"স্বতঃ-ঘূর্ণায়মান স্ক্রীণ"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"নিঃশব্দ করুন"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"স্বতঃ"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"আনলক করুন"</string>
     <string name="phone_label" msgid="2320074140205331708">"ফোন খুলুন"</string>
     <string name="camera_label" msgid="7261107956054836961">"ক্যামেরা খুলুন"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"নতুন কার্য লেআউট নির্বাচন করুন"</string>
+    <string name="cancel" msgid="6442560571259935130">"বাতিল করুন"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"সামঞ্জস্যের জুম বোতাম৷"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ছোট থেকে বৃহৎ স্ক্রীণে জুম করুন৷"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth সংযুক্ত হয়েছে৷"</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"বিমান মোড চালু হয়েছে।"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"“বিরক্ত করবেন না” চালু করবেন, শুধুমাত্র অগ্রাধিকার৷"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"“বিরক্ত করবেন না” চালু করবেন, কোন বাধা নয়"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"“বিরক্ত করবেন না” বন্ধ৷"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"বিরক্ত করবেন না বন্ধ রয়েছে৷"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"বিরক্ত করবেন না চালু রয়েছে৷"</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"ডেজার্ট কেস"</string>
     <string name="start_dreams" msgid="7219575858348719790">"স্ক্রিনসেভার"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ইথারনেট"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"বিমান মোড"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"বিরক্ত করবেন না"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"শুধুমাত্র অগ্রাধিকার"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"কোনো বাধা নয়"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> টি ডিভাইস)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"কোনো নেটওয়ার্ক নেই"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi বন্ধ"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"কোন সংরক্ষিত নেটওয়ার্ক উপলব্ধ নেই"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"কাস্ট করুন"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"কাস্ট করা হচ্ছে"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"নামবিহীন ডিভাইস"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"কাস্ট করার জন্য প্রস্তুত"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"কোনো ব্যাঘাত ছাড়াই। এমনকি অ্যালার্মও নয়।"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"কোনো বাধা নয়"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"শুধুমাত্র প্রাধান্য বাধাগুলি"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"আপনার পরবর্তী অ্যালার্মের সময় <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"আপনার পরবর্তী অ্যালার্মের সময় <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> বাজলে আপনি অ্যালার্ম শুনতে পাবেন না"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"আনলক করতে উপরের দিকে সোয়াইপ করুন"</string>
     <string name="phone_hint" msgid="3101468054914424646">"ফোনের জন্য ডানদিকে সোয়াইপ করুন"</string>
     <string name="camera_hint" msgid="5241441720959174226">"ক্যামেরার জন্য ডানদিকে সোয়াইপ করুন"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"কোনো কিছুই নয়"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"অগ্রাধিকার"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"সমস্ত"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"চার্জ হচ্ছে (পূর্ণ হতে <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> সময় বাকি)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ব্যবহারকারী পাল্টে দিন"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ব্যবহারকারী পাল্টান, বর্তমান ব্যবহারকারী <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"প্রত্যাখ্যান করুন"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> হল ভলিউম ডায়লগ"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"আসলটি পুনঃস্থাপন করতে স্পর্শ করুন৷"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index b260e44..7334d82f 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Activa l\'estalvi de bateria"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configuració"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode d\'avió"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Gira pantalla automàticament"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"Silen."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO."</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloqueja"</string>
     <string name="phone_label" msgid="2320074140205331708">"obre el telèfon"</string>
     <string name="camera_label" msgid="7261107956054836961">"obre la càmera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Selecciona el disseny de la tasca nova"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancel·la"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botó de zoom de compatibilitat."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Amplia menys com més gran sigui la pantalla."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connectat."</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"S\'ha activat el Mode d\'avió."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"El mode No molesteu està activat (només amb prioritat)."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"El mode No molesteu està activat (cap interrupció)."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"El mode No molesteu està desactivat."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"S\'ha desactivat el mode No molesteu."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"S\'ha activat el mode No molesteu."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Capsa de postres"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Estalvi de pantalla"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode d\'avió"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"No molesteu"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Només amb prioritat"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Cap interrupció"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositius)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hi ha cap xarxa"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desconnectada"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"No hi ha cap xarxa desada disponible."</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Emet"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"En emissió"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Dispositiu sense nom"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"A punt per a l\'emissió"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Sense interrupcions (ni tan sols alarmes)"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Cap interrupció"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Només interrupcions amb prioritat"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"La propera alarma és a les <xliff:g id="ALARM_TIME">%s</xliff:g>."</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Propera alarma: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"No sentiràs l\'alarma a les <xliff:g id="ALARM_TIME">%s</xliff:g>."</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Fes lliscar el dit cap amunt per desbloquejar el teclat."</string>
     <string name="phone_hint" msgid="3101468054914424646">"Fes lliscar el dit cap a la dreta per obrir el telèfon."</string>
     <string name="camera_hint" msgid="5241441720959174226">"Fes lliscar el dit cap a l\'esquerra per obrir la càmera."</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Cap"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritat"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Totes"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregant (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> per completar la càrrega)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Canvia d\'usuari"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Canvia l\'usuari. Usuari actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Denega"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> és el diàleg de volum"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca per restaurar l\'original."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f1cbb7e..9664f69 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -46,7 +46,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Zapnout úsporu baterie"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavení"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Režim Letadlo"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Autom. otočení obrazovky"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ZTLUM."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
@@ -90,6 +89,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"odemknout"</string>
     <string name="phone_label" msgid="2320074140205331708">"otevřít telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"spustit fotoaparát"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Vybrat nové rozvržení úkolů"</string>
+    <string name="cancel" msgid="6442560571259935130">"Zrušit"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačítko úpravy velikosti z důvodu kompatibility"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zvětšit menší obrázek na větší obrazovku."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Rozhraní Bluetooth je připojeno."</string>
@@ -182,6 +183,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Režim Letadlo je zapnutý."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Stav Nerušit je zapnutý – pouze prioritní vyrušení."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Stav Nerušit je zapnutý – žádná vyrušení."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Stav Nerušit je vypnutý."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Stav Nerušit je vypnutý"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Stav Nerušit je zapnutý."</string>
@@ -232,9 +235,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Pult se sladkostmi"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Spořič obrazovky"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Režim Letadlo"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Nerušit"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Pouze prioritní"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Žádná vyrušení"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> zařízení)"</string>
@@ -261,8 +265,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Žádná síť"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi vypnuta"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Nejsou dostupné žádné uložené sítě"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Odeslat"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Odesílání"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Nepojmenované zařízení"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Připraveno k vysílání"</string>
@@ -306,6 +309,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Žádná vyrušení, dokonce ani budíky."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Žádná vyrušení"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Pouze prioritní vyrušení"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Další budík je nastaven na: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Další budík: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Neuslyšíte budík v <xliff:g id="ALARM_TIME">%s</xliff:g>."</string>
@@ -315,9 +320,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Zařízení odemknete přejetím prstem nahoru"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Telefon otevřete přejetím prstem vpravo."</string>
     <string name="camera_hint" msgid="5241441720959174226">"Fotoaparát otevřete přejetím prstem vlevo."</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Žádné"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritní"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Vše"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Přepnout uživatele"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Přepnout uživatele, aktuální uživatel: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -385,4 +400,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmítnout"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialog hlasitosti"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 92efc89..2c951d9 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Aktivér batterisparefunktion"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Indstillinger"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flytilstand"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Automatisk skærmrotation"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"LYDLØS"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"lås op"</string>
     <string name="phone_label" msgid="2320074140205331708">"åbn telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"åbn kamera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Vælg nyt opgavelayout"</string>
+    <string name="cancel" msgid="6442560571259935130">"Annuller"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knap for kompatibilitetszoom."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom mindre til større skærm."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tilsluttet."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Flytilstand er slået til."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\"Vil ikke forstyrres\" er slået til, kun prioritet."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\"Vil ikke forstyrres\" er slået til, ingen afbrydelser."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Vil ikke forstyrres\" er slået fra."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Vil ikke forstyrres\" er slået fra."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Vil ikke forstyrres\" er slået til."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessertcase"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Dagdrøm"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flytilstand"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Vil ikke forstyrres"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Kun prioritet"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Ingen afbrydelser"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheder)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Intet netværk"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi slået fra"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Der er ingen tilgængelige gemte netværk"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Caster"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Enhed uden navn"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Klar til at caste"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Ingen afbrydelser. Ikke engang alarmer."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Ingen afbrydelser"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Kun prioriterede afbrydelser"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Dit næste alarm er indstillet til kl. <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Din næste alarm er indstillet til <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Du vil ikke kunne høre din alarm kl. <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Stryg for at låse op"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Stryg til højre for at bruge telefonen"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Stryg til venstre for at åbne kameraet"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Ingen"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritet"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Oplader (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Skift bruger"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Skift bruger. Nuværende bruger er <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Afvis"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er dialogboksen for lydstyrke"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Tryk for at gendanne originalen."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 1119f1f..f884e08 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Energiesparmodus aktivieren"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Einstellungen"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WLAN"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flugmodus"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Bildschirm automatisch drehen"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"STUMM"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"Entsperren"</string>
     <string name="phone_label" msgid="2320074140205331708">"Telefon öffnen"</string>
     <string name="camera_label" msgid="7261107956054836961">"Kamera öffnen"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Neues Aufgabenlayout auswählen"</string>
+    <string name="cancel" msgid="6442560571259935130">"Abbrechen"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Schaltfläche für Kompatibilitätszoom"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom auf einen größeren Bildschirm"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Mit Bluetooth verbunden"</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Der Flugmodus ist aktiviert."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\"Nicht stören\" an, nur wichtige Unterbrechungen"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\"Nicht stören\" an, keine Unterbrechungen"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Nicht stören\" aus"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Nicht stören\" deaktiviert"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Nicht stören\" aktiviert"</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessertbehälter"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flugmodus"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Nicht stören"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Nur wichtige Unterbrechungen"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Keine Unterbrechungen"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Geräte)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Kein Netz"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WLAN aus"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Keine gespeicherten Netzwerke verfügbar"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Übertragen"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Wird übertragen"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Unbenanntes Gerät"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Startklar"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Keine Unterbrechungen. Auch keine Weckrufe."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Keine Unterbrechungen"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Nur wichtige Unterbrechungen"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Nächster Weckruf: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Nächster Weckruf: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Lautloser Weckruf um <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Zum Entsperren nach oben wischen"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Zum Öffnen des Telefons nach rechts wischen"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Zum Öffnen der Kamera nach links wischen"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Keine"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Wichtig"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Wird aufgeladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Nutzer wechseln"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Nutzer wechseln. Aktueller Nutzer: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ablehnen"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> regelt die Lautstärke."</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Zum Wiederherstellen des Originals hier tippen"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index bc1b7a2..902b123 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Ενεργοποίηση της εξοικονόμησης μπαταρίας"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ρυθμίσεις"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Λειτουργία πτήσης"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Αυτόματη περιστροφή οθόνης"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ΣΙΓΑΣΗ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ΑΥΤΟΜ."</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ξεκλείδωμα"</string>
     <string name="phone_label" msgid="2320074140205331708">"άνοιγμα τηλεφώνου"</string>
     <string name="camera_label" msgid="7261107956054836961">"άνοιγμα φωτογραφικής μηχανής"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Επιλέξτε τη νέα διάταξη εργασίας"</string>
+    <string name="cancel" msgid="6442560571259935130">"Ακύρωση"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Κουμπί εστίασης συμβατότητας."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Ζουμ από μικρότερη σε μεγαλύτερη οθόνη."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Το Bluetooth είναι συνδεδεμένο."</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Ενεργή λειτουργία πτήσης."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Η λειτουργία \"Μην ενοχλείτε\" ενεργοποιήθηκε, μόνο προτεραιότητας."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Η λειτουργία \"Μην ενοχλείτε\" ενεργοποιήθηκε, χωρίς διακοπές."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Η λειτουργία \"Μην ενοχλείτε\" απενεργοποιήθηκε."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Η λειτουργία \"Μην ενοχλείτε\" απενεργοποιήθηκε."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Η λειτουργία \"Μην ενοχλείτε\" ενεργοποιήθηκε."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Επιδόρπιο"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Λειτουργία πτήσης"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Μην ενοχλείτε"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Μόνο προτεραιότητας"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Χωρίς διακοπές"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> συσκευές)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Κανένα δίκτυο"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ανενεργό"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Δεν υπάρχουν διαθέσιμα αποθηκευμένα δίκτυα"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Μετάδοση"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Μετάδοση"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Ανώνυμη συσκευή"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Έτοιμο για μετάδοση"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Χωρίς διακοπές. Ούτε ειδοποιήσεις,"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Χωρίς διακοπές"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Μόνο διακοπές προτεραιότητας"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Το επόμενο ξυπνητήρι είναι στις <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Το επόμενο ξυπνητήρι είναι στις <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Δεν θα ακούτε το ξυπνητήρι σας στις <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Σύρετε για να ξεκλειδώσετε"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Σύρετε προς τα δεξιά για το τηλέφωνο"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Σύρετε αριστερά για τη φωτογραφική μηχανή"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Κανένα"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Προτεραιότητα"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Όλα"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> για πλήρη φόρτιση)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Εναλλαγή χρήστη"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Εναλλαγή χρήστη, τρέχων χρήστης <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Απόρριψη"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> αποτελεί το παράθυρο διαλόγου ελέγχου έντασης"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Αγγίξτε για επαναφορά αρχικού."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index ee3f826..2f5c937 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Turn on battery saver"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Settings"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Aeroplane mode"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Auto-rotate screen"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"unlock"</string>
     <string name="phone_label" msgid="2320074140205331708">"open phone"</string>
     <string name="camera_label" msgid="7261107956054836961">"open camera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -178,6 +179,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Aeroplane mode turned on."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\'Do not disturb\' on, priority only."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\'Do not disturb\' on, no interruptions."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Do not disturb on, alarms only."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\'Do not disturb\' off."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\'Do not disturb\' turned off."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\'Do not disturb\' turned on."</string>
@@ -228,9 +230,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Aeroplane mode"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Do not disturb"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Priority only"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Alarms only"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"No interruptions"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
@@ -301,6 +303,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"No interruptions. Not even alarms."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"No interruptions"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Priority interruptions only"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"Alarms only"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Your next alarm is at <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Your next alarm is <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"You won\'t hear your alarm at <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -310,9 +313,13 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Swipe right for phone"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Swipe left for camera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"None"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Priority"</string>
+    <string name="interruption_level_none" msgid="8284541443482072628">"No interruptions"</string>
+    <string name="interruption_level_priority" msgid="6426766465363855505">"Priority only"</string>
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"Alarms only"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"All"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"No\ninterruptions"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priority\nonly"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarms\nonly"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Switch user"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Switch user, current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -380,4 +387,5 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
+    <string name="volume_zen_switch_text" msgid="6388350641576595452">"Block interruptions"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index ee3f826..2f5c937 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Turn on battery saver"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Settings"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Aeroplane mode"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Auto-rotate screen"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"unlock"</string>
     <string name="phone_label" msgid="2320074140205331708">"open phone"</string>
     <string name="camera_label" msgid="7261107956054836961">"open camera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -178,6 +179,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Aeroplane mode turned on."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\'Do not disturb\' on, priority only."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\'Do not disturb\' on, no interruptions."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Do not disturb on, alarms only."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\'Do not disturb\' off."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\'Do not disturb\' turned off."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\'Do not disturb\' turned on."</string>
@@ -228,9 +230,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Aeroplane mode"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Do not disturb"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Priority only"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Alarms only"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"No interruptions"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
@@ -301,6 +303,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"No interruptions. Not even alarms."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"No interruptions"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Priority interruptions only"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"Alarms only"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Your next alarm is at <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Your next alarm is <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"You won\'t hear your alarm at <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -310,9 +313,13 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Swipe right for phone"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Swipe left for camera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"None"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Priority"</string>
+    <string name="interruption_level_none" msgid="8284541443482072628">"No interruptions"</string>
+    <string name="interruption_level_priority" msgid="6426766465363855505">"Priority only"</string>
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"Alarms only"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"All"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"No\ninterruptions"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priority\nonly"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarms\nonly"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Switch user"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Switch user, current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -380,4 +387,5 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
+    <string name="volume_zen_switch_text" msgid="6388350641576595452">"Block interruptions"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index ee3f826..2f5c937 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Turn on battery saver"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Settings"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Aeroplane mode"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Auto-rotate screen"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"unlock"</string>
     <string name="phone_label" msgid="2320074140205331708">"open phone"</string>
     <string name="camera_label" msgid="7261107956054836961">"open camera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Select new task layout"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancel"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -178,6 +179,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Aeroplane mode turned on."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\'Do not disturb\' on, priority only."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\'Do not disturb\' on, no interruptions."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Do not disturb on, alarms only."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\'Do not disturb\' off."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\'Do not disturb\' turned off."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\'Do not disturb\' turned on."</string>
@@ -228,9 +230,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Aeroplane mode"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Do not disturb"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Priority only"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Alarms only"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"No interruptions"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
@@ -301,6 +303,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"No interruptions. Not even alarms."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"No interruptions"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Priority interruptions only"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"Alarms only"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Your next alarm is at <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Your next alarm is <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"You won\'t hear your alarm at <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -310,9 +313,13 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Swipe right for phone"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Swipe left for camera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"None"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Priority"</string>
+    <string name="interruption_level_none" msgid="8284541443482072628">"No interruptions"</string>
+    <string name="interruption_level_priority" msgid="6426766465363855505">"Priority only"</string>
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"Alarms only"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"All"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"No\ninterruptions"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priority\nonly"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarms\nonly"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Switch user"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Switch user, current user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -380,4 +387,5 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
+    <string name="volume_zen_switch_text" msgid="6388350641576595452">"Block interruptions"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index a605a03..9f2c642 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Activar ahorro de batería"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configuración"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo avión"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Girar la pantalla automáticamente"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"SILENC"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
     <string name="phone_label" msgid="2320074140205331708">"abrir teléfono"</string>
     <string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Selecciona el nuevo diseño de la tarea."</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Modo de avión activado"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"No molestar activado (solo prioridad)"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"No molestar activado (sin interrupciones)"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"No molestar desactivado"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"No molestar desactivado"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"No molestar activado"</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Caja para postres"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Activar protector"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"No molestar"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Solo prioridad"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Sin interrupciones"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sin red"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desactivada"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"No hay redes guardadas disponibles"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Transmitir"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Transmitiendo"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Dispositivo sin nombre"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Listo para transmitir"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Sin interrupciones (ni siquiera alarmas)"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Sin interrupciones"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Solo interrupciones de prioridad"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Próxima alarma a la(s) <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Próxima alarma: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"No oirás la alarma a la(s) <xliff:g id="ALARM_TIME">%s</xliff:g>."</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Deslizar el dedo hacia arriba para desbloquear"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Desliza hacia la derecha para abrir el teléfono."</string>
     <string name="camera_hint" msgid="5241441720959174226">"Desliza hacia la izquierda para acceder a la cámara."</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Ninguno"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioridad"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Todo"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (faltan <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambiar usuario"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Cambiar de usuario (usuario actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rechazar"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen."</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar el original."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index dcffc65..30bc2623 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Activar ahorro de energía"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ajustes"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo avión"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Girar pantalla automáticamente"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"SILENC"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
     <string name="phone_label" msgid="2320074140205331708">"abrir teléfono"</string>
     <string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Seleccionar diseño de tarea nueva"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Modo avión activado."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"No molestar activado (solo prioritarias)."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"No molestar activado (sin interrupciones)."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"No molestar desactivado."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"No molestar desactivado."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"No molestar activado."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Caja para postres"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Salvapantallas"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"No molestar"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Solo prioritarias"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Sin interrupciones"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hay red."</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desactivado"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"No hay redes guardadas disponibles"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Enviar"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Enviando"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Dispositivo sin nombre"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Listo para enviar"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Sin interrupciones, ni siquiera alarmas."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Sin interrupciones"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Solo interrupciones de prioridad"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Siguiente alarma: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Siguiente alarma: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"No oirás tu alarma a las <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Desliza el dedo hacia arriba para desbloquear"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Desliza el dedo hacia la derecha para acceder al teléfono"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Desliza el dedo hacia la izquierda para acceder a la cámara"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Nada"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioridad"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Todo"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambiar de usuario"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Cambiar de usuario (usuario actual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rechazar"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar la versión original."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 1a74a8f..44f4855 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Akusäästja sisselülitamine"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Seaded"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WiFi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lennurežiim"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Pööra ekraani automaatselt"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"SUMMUTA"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ava lukk"</string>
     <string name="phone_label" msgid="2320074140205331708">"ava telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"ava kaamera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Uue toimingu paigutuse valimine"</string>
+    <string name="cancel" msgid="6442560571259935130">"Tühista"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Sobivussuumi nupp."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Suumi suuremale ekraanile vähem."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth on ühendatud."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Lennukirežiim on sisse lülitatud."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Funktsioon Mitte segada on sisse lülitatud (ainult prioriteetsed)."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Funktsioon Mitte segada on sisse lülitatud (mitte ühtegi katkestust)."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Funktsioon Mitte segada on välja lülitatud."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Funktsioon Mitte segada on välja lülitatud."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Funktsioon Mitte segada on sisse lülitatud."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Maiustusekorv"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Unistus"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lennurežiim"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Mitte segada"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Ainult prioriteetsed"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Mitte ühtegi katkestust"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> seadet)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Võrku pole"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WiFi-ühendus on väljas"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Ühtegi salvestatud võrku pole saadaval"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Ülekandmine"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Osatäitjad"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Nimeta seade"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Valmis ülekandmiseks"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Katkestusi pole. Pole isegi hoiatusi."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Mitte ühtegi katkestust"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Ainult prioriteetsed katkestused"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Teie järgmine äratus on <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Teie järgmine äratus on <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Te ei kuule äratust <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Lukustuse tühistamiseks pühkige üles"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Telefoni kasutamiseks pühkige paremale"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Kaamera kasutamiseks pühkige vasakule"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Puudub"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioriteet"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Kõik"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laadimine (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>, kuni seade on täis)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Kasutaja vahetamine"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Kasutaja vahetamine, praegune kasutaja: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Keela"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on helitugevuse dialoog"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Originaali taastamiseks puudutage."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index c7019d9..4c5286d0 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Aktibatu bateria aurrezteko aukera"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ezarpenak"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Hegaldi modua"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Biratu pantaila automatikoki"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DESAKTIBATU AUDIOA"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"desblokeatu"</string>
     <string name="phone_label" msgid="2320074140205331708">"ireki telefonoan"</string>
     <string name="camera_label" msgid="7261107956054836961">"ireki kamera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Hautatu zereginen diseinua"</string>
+    <string name="cancel" msgid="6442560571259935130">"Utzi"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoom-bateragarritasunaren botoia."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Handiagotu pantaila txikia."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetootha konektatuta."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Hegaldi modua aktibatu egin da."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\"Ez molestatu\" aukera aktibatuta dago, lehentasunezkoak soilik."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\"Ez molestatu\" aukera aktibatuta dago, etenaldirik gabe."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Ez molestatu\" aukera desaktibatuta dago."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Ez molestatu\" aukera desaktibatuta dago."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Ez molestatu\" aukera aktibatuta dago."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Postreen kutxa"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Pantaila-babeslea"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Hegaldi modua"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Ez molestatu"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Lehentasunezkoak soilik"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Etenaldirik gabe"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetootha (<xliff:g id="NUMBER">%d</xliff:g> gailu)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ez dago sarerik"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi konexioa desaktibatuta"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Ez dago gordetako sarerik erabilgarri"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Igorpena"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Igortzen"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Izenik gabeko gailua"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Igortzeko prest"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Etenaldirik ez, ezta alarmaren bat bada ere."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Etenaldirik gabe"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Lehentasun-etenaldiak soilik"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Hurrengo alarma: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Hurrengo alarma: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Ez duzu entzungo alarma ordu honetan: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Desblokeatzeko, pasatu hatza gorantz"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Telefonoa irekitzeko, pasatu hatza eskuinera."</string>
     <string name="camera_hint" msgid="5241441720959174226">"Kamera irekitzeko, pasatu hatza ezkerrera."</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Bat ere ez"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Lehentas."</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Guztiak"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> guztiz kargatu arte)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Aldatu erabiltzailea"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Aldatu erabiltzailez. <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> da saioa hasita duena."</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ukatu"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> da bolumenaren leihoa"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Ukitu jatorrizkora leheneratzeko"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 18d8f76..0bbc787 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"ذخیره‌کننده باتری را روشن کنید"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"تنظیمات"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"حالت هواپیما"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"چرخش خودکار صفحه"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"بی‌صدا"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"خودکار"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"بازکردن قفل"</string>
     <string name="phone_label" msgid="2320074140205331708">"باز کردن تلفن"</string>
     <string name="camera_label" msgid="7261107956054836961">"باز کردن دوربین"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"انتخاب طرح‌بندی جدید کار"</string>
+    <string name="cancel" msgid="6442560571259935130">"لغو"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"دکمه بزرگنمایی سازگار."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"بزرگنمایی از صفحه‌های کوچک تا بزرگ."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"بلوتوث متصل است."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"حالت هواپیما روشن شد."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"«مزاحم نشوید» روشن است، فقط اولویت‌دار."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"«مزاحم نشوید» روشن است، وقفه ایجاد نشود."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"«مزاحم نشوید» خاموش است."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"«مزاحم نشوید» خاموش شد."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"«مزاحم نشوید» روشن شد."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"ویترین دسر"</string>
     <string name="start_dreams" msgid="7219575858348719790">"رویاپردازی"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"اترنت"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"حالت هواپیما"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"مزاحم نشوید"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"فقط اولویت‌دار"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"وقفه ایجاد نشود"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوتوث"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوتوث ( <xliff:g id="NUMBER">%d</xliff:g> دستگاه)"</string>
@@ -301,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"بدون قطعی. حتی هشدارها قطع نمی‌شوند."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"بدون وقفه"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"فقط وقفه‌های اولویت‌دار"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"هشدار بعدی شما در ساعت <xliff:g id="ALARM_TIME">%s</xliff:g> است"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"هشدار بعدی شما <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> است"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"هشدارتان را در ساعت <xliff:g id="ALARM_TIME">%s</xliff:g> نخواهید شنید"</string>
@@ -310,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"برای باز کردن قفل سریع به بالا بکشید"</string>
     <string name="phone_hint" msgid="3101468054914424646">"برای تلفن انگشت را تند به سمت چپ بکشید"</string>
     <string name="camera_hint" msgid="5241441720959174226">"برای دوربین انگشت را تند به سمت راست بکشید"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"هیچ‌کدام"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"اولویت"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"همه"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"در حال شارژ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> تا شارژ کامل)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"تغییر کاربر"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"تعویض کاربر، کاربر کنونی <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -380,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"رد کردن"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> کنترل‌کننده صدا است"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"برای بازیابی کنترل‌کننده اصلی، لمس کنید."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 61e591a..9fd05b2 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Ota virransäästö käyttöön"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Asetukset"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lentokonetila"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Kierrä näyttöä automaattisesti"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ÄÄNET."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"avaa lukitus"</string>
     <string name="phone_label" msgid="2320074140205331708">"avaa puhelin"</string>
     <string name="camera_label" msgid="7261107956054836961">"avaa kamera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Valitse uusi tehtävien asettelu"</string>
+    <string name="cancel" msgid="6442560571259935130">"Peruuta"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Yhteensopivuuszoomaus-painike."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoomaa pienemmältä suuremmalle ruudulle."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth yhdistetty."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Lentokonetila otettiin käyttöön."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Älä häiritse -tila on päällä, vain tärkeät."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Älä häiritse -tila on päällä, ei keskeytyksiä."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Älä häiritse -tila on pois päältä."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Älä häiritse -tila on pois päältä."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Älä häiritse -tila on päällä."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Jälkiruokavitriini"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Unelmat"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lentokonetila"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Älä häiritse"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Vain tärkeät"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Ei häiriöitä"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> laitetta)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ei verkkoa"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi-yhteys pois käytöstä"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Tallennettuja verkkoja ei ole käytettävissä"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Suoratoisto"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Lähetetään"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Nimetön laite"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Valmis lähetystä varten"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Ei keskeytyksiä, ei edes herätyksiä."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Ei häiriöitä"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Vain tärkeät häiriöt"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Seuraava hälytysaika on <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Seuraava hälytysaika on <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Et kuule hälytystä klo <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Avaa lukitus pyyhkäisemällä ylös"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Avaa puhelin pyyhkäisemällä oikealle"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Avaa kamera pyyhkäisemällä oikealle"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Ei mitään"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Tärkeät"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Kaikki"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ladataan (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kunnes täynnä)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Vaihda käyttäjää"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Vaihda käyttäjä (nyt <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Estä"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on äänenvoimakkuusvalinta."</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Palauta alkuperäinen koskettamalla."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 3427cfa..780591b 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Activer l\'économiseur d\'énergie"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Paramètres"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode Avion"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Rotation auto de l\'écran"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUET"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOMATIQUE"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"déverrouiller"</string>
     <string name="phone_label" msgid="2320074140205331708">"Ouvrir le téléphone"</string>
     <string name="camera_label" msgid="7261107956054836961">"Ouvrir l\'appareil photo"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Sélectionner un nouveau format de tâche"</string>
+    <string name="cancel" msgid="6442560571259935130">"Annuler"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Bouton \"Zoom de compatibilité\""</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilité avec la taille de l\'écran"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connecté"</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Le mode Avion est activé."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Mode « Ne pas déranger » activé, interruptions prioritaires uniquement."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Mode « Ne pas déranger » activé, sans interruption."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Mode « Ne pas déranger » désactivé."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Le mode « Ne pas déranger » a bien été désactivé."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Le mode « Ne pas déranger » a bien été activé."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Vitrine des desserts"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Écran de veille"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode Avion"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Ne pas déranger"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Priorités seulement"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Aucune interruption"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> appareils)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Aucun réseau"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi désactivé"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Aucun des réseaux enregistrés n\'est disponible"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Diffuser"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Diffusion"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Appareil sans nom"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Prêt à diffuser"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Aucune interruption. Même pas pour les alarmes."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Aucune interruption"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Interruptions prioritaires seulement"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Prochaine alarme : <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Prochaine alarme : <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Vous n\'entendrez pas votre alarme à <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Glissez vers le haut pour déverrouiller"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Balayez l\'écran vers la droite pour accéder au téléphone"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Balayez l\'écran vers la gauche pour accéder à l\'appareil photo"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Aucun"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Priorité"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Tous"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours... (chargée à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuser"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Touchez pour restaurer l\'original."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 393a0f8..a8dbed1 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Activer l\'économiseur de batterie"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Paramètres"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode Avion"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Rotation automatique de l\'écran"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUET"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"déverrouiller"</string>
     <string name="phone_label" msgid="2320074140205331708">"ouvrir le téléphone"</string>
     <string name="camera_label" msgid="7261107956054836961">"ouvrir l\'appareil photo"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Sélectionner un nouveau plan de tâche"</string>
+    <string name="cancel" msgid="6442560571259935130">"Annuler"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Bouton \"Zoom de compatibilité\""</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilité avec la taille de l\'écran"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connecté"</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Le mode Avion est activé."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Mode \"Ne pas déranger\" activé, interruptions prioritaires uniquement"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Mode \"Ne pas déranger\" activé, sans interruption"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Mode \"Ne pas déranger\" désactivé"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Le mode \"Ne pas déranger\" a bien été désactivé."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Le mode \"Ne pas déranger\" a bien été activé."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Vitrine des desserts"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Écran de veille interactif"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode avion"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Ne pas déranger"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Prioritaires uniquement"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Aucune interruption"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> appareils)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Aucun réseau"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi désactivé"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Aucun réseau enregistré disponible."</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Diffuser"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Diffusion"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Appareil sans nom"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Prêt à caster"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Aucune sonnerie, pas même pour les alarmes"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Aucune sonnerie"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Sonneries prioritaires uniquement"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Prochaine alarme : <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Prochaine alarme : <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Vous n\'entendrez pas votre alarme à <xliff:g id="ALARM_TIME">%s</xliff:g>."</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Faire glisser pour déverrouiller"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Balayer l\'écran vers la droite pour accéder au téléphone"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Balayer l\'écran vers la gauche pour accéder à l\'appareil photo"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Aucune"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritaire"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Toujours"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours… (chargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuser"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Appuyez pour restaurer l\'interface d\'origine."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index c47fc4e..2d3c249 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Activar o aforro de batería"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configuración"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo avión"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Xirar pantalla automaticamente"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"APAGAR"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
     <string name="phone_label" msgid="2320074140205331708">"abrir teléfono"</string>
     <string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Seleccionar novo deseño de tarefas"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidade"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilidade co tamaño da pantalla."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Activouse o modo avión."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Non molestar activado, só prioridade."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Non molestar activado, sen interrupcións."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"A opción Non molestar está desactivada."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Desactivouse a opción Non molestar."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Activouse a opción Non molestar."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Caixa de sobremesa"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Protector pantalla"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Non molestar"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Só prioridade"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Sen interrupcións"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Non hai rede"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wifi desactivada"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Non hai redes gardadas dispoñibles"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Emisión"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Emitindo"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Dispositivo sen nome"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Listo para emitir"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Non hai interrupcións nin alarmas."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Sen interrupcións"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Só interrupcións prioritarias"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"A túa próxima alarma ten lugar ás <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"A túa próxima alarma ten lugar o <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Non escoitarás a túa alarma ás <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Pasa o dedo cara arriba para desbloquear"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Pasa o dedo cara á dereita para acceder ao teléfono"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Pasa o dedo cara á esquerda para abrir a cámara"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Ningún"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioridade"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Todas"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para finalizar a carga)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambiar usuario"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Cambiar usuario, usuario actual: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Denegar"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é o cadro de diálogo de volume"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar o orixinal."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 516ae5e..47afe2c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"बैटरी बचतकर्ता को चालू करें"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"सेटिंग"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"वाई-फ़ाई"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"हवाई जहाज मोड"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"स्‍क्रीन अपनेआप घुमाएं"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"म्यूट करें"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"स्वत:"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"अनलॉक करें"</string>
     <string name="phone_label" msgid="2320074140205331708">"फ़ोन खोलें"</string>
     <string name="camera_label" msgid="7261107956054836961">"कैमरा खोलें"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"नया कार्य लेआउट चुनें"</string>
+    <string name="cancel" msgid="6442560571259935130">"अभी नहीं"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"संगतता ज़ूम बटन."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"छोटी से बड़ी स्‍क्रीन पर ज़ूम करें."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लूटूथ कनेक्ट किया गया."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"हवाई जहाज़ मोड को चालू किया गया."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"परेशान ना करें चालू, केवल प्राथमिकता."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"परेशान ना करें चालू है, कोई बाधा नहीं."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"परेशान ना करें बंद."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"परेशान ना करें बंद किया गया."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"परेशान ना करें चालू किया गया."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"मिठाई का डिब्बा"</string>
     <string name="start_dreams" msgid="7219575858348719790">"स्क्रीनसेवर"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ईथरनेट"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"हवाई जहाज़ मोड"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"परेशान ना करें"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"केवल प्राथमिकता"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"कोई मेसज और कॉल को नहीं रोका गया"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब्लूटूथ"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लूटूथ (<xliff:g id="NUMBER">%d</xliff:g> डिवाइस)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"कोई नेटवर्क नहीं"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"वाई-फ़ाई  बंद"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"कोई भी सहेजा गया नेटवर्क उपलब्ध नहीं"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"कास्ट करें"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"कास्टिंग"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"अनाम डिवाइस"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"कास्ट करने के लिए तैयार"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"ऐसा सेट करें की कोई कि अलार्म भी ना हो."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"कोई अवरोध नहीं"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"केवल प्राथमिकता वाले कल और मैसेज को रोकें"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"आपका अगला अलार्म <xliff:g id="ALARM_TIME">%s</xliff:g> पर है"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"आपका अगला अलार्म <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> पर है"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"आपको <xliff:g id="ALARM_TIME">%s</xliff:g> पर अपना अलार्म सुनाई नहीं देगा"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"अनलॉक करने के लिए ऊपर स्वाइप करें"</string>
     <string name="phone_hint" msgid="3101468054914424646">"फ़ोन के लिए दाएं स्वाइप करें"</string>
     <string name="camera_hint" msgid="5241441720959174226">"कैमरे के लिए बाएं स्वाइप करें"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"कोई नहीं"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"प्राथमिकता"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"सभी"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"चार्ज हो रहा है (पूरा होने में <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> बाकी)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"उपयोगकर्ता स्विच करें"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"उपयोगकर्ता स्विच करें, वर्तमान उपयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"अस्वीकार करें"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद है"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"मूल वॉल्यूम को फिर से लाने के लिए स्पर्श करें."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index f63b1cd..3db3a43 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -45,7 +45,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Uključi uštedu baterije"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Postavke"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Način rada u zrakoplovu"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Automatski zakreni zaslon"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"Bez zv."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
@@ -89,6 +88,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"otključavanje"</string>
     <string name="phone_label" msgid="2320074140205331708">"otvaranje telefona"</string>
     <string name="camera_label" msgid="7261107956054836961">"otvaranje fotoaparata"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Odaberite novi izgled zadataka"</string>
+    <string name="cancel" msgid="6442560571259935130">"Odustani"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb za kompatibilnost zumiranja."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zumiranje manjeg zaslona na veći."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth povezan."</string>
@@ -179,6 +180,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Način rada u zrakoplovu uključen."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\"Ne ometaj\" uključeno, samo prioritetno."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\"Ne ometaj\" uključeno, bez prekida."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Ne ometaj\" isključeno."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Ne ometaj\" isključeno."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Ne ometaj\" uključeno."</string>
@@ -229,9 +232,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Izlog za slastice"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Sanjarenje"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Način rada u zrakoplovu"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Ne ometaj"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Samo prioritetno"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Bez prekida"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (broj uređaja: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -258,8 +262,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nema mreže"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi isključen"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Spremljene mreže nisu dostupne"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Emitiranje"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Emitiranje"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Uređaj bez naziva"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Spreman za emitiranje"</string>
@@ -303,6 +306,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Bez prekida, čak ni za alarme."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Bez prekida"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Samo prioritetni prekidi"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Vaš sljedeći alarm bit će u <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Vaš sljedeći alarm bit će u <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Nećete čuti alarm u <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -312,9 +317,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Prijeđite prstom prema gore za otključavanje"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Prijeđite prstom udesno za telefon"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Prijeđite prstom ulijevo za fotoaparat"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Ništa"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritet"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Sve"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napunjenosti)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Promjena korisnika"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Promjena korisnika, trenutačni korisnik <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -382,4 +397,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odbij"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> predstavlja dijaloški okvir za upravljanje glasnoćom"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Dodirnite da biste vratili izvorno."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 621bdb8..4db932f 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Akkumulátorkímélő mód bekapcsolása"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Beállítások"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Repülőgép üzemmód"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Képernyő automatikus forgatása"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"NÉMÍT"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"feloldás"</string>
     <string name="phone_label" msgid="2320074140205331708">"telefon megnyitása"</string>
     <string name="camera_label" msgid="7261107956054836961">"kamera megnyitása"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Új feladatelrendezés kiválasztása"</string>
+    <string name="cancel" msgid="6442560571259935130">"Mégse"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kompatibilitási zoom gomb."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kicsinyítsen a nagyobb képernyőhöz."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth csatlakoztatva."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Repülős üzemmód bekapcsolva."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"A „Ne zavarjanak” mód bekapcsolva. Csak prioritásos."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"A „Ne zavarjanak” mód bekapcsolva. Nincsenek értesítések."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"A „Ne zavarjanak” mód kikapcsolva."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"A „Ne zavarjanak” mód kikapcsolva."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"A „Ne zavarjanak” mód bekapcsolva."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Álmodozás"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Repülőgép üzemmód"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Ne zavarjanak"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Csak prioritásos"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Ne zavarjon"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> eszköz)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nincs hálózat"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi kikapcsolva"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Nem áll rendelkezésre mentett hálózat"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Tartalomátküldés"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Átküldés"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Név nélküli eszköz"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Küldésre kész"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Semmi sem zavarja meg, még a riasztások sem."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Ne zavarjon"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Csak prioritást élvező zavaró üzenetek"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"A következő ébresztés ideje: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"A következő ébresztés napja és ideje: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Nem fogja hallani az ébresztést ekkor: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Húzza felfelé az ujját a feloldáshoz"</string>
     <string name="phone_hint" msgid="3101468054914424646">"A telefon eléréséhez csúsztassa ujját jobbra"</string>
     <string name="camera_hint" msgid="5241441720959174226">"A fényképezőgép eléréséhez csúsztassa ujját balra"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Nincs"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritást élvező"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Összes"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Töltés (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> a teljes töltöttségig)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Felhasználóváltás"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Felhasználóváltás (a jelenlegi felhasználó: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Elutasítás"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás kezeli a hangerőt"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Érintse meg az eredeti érték visszaállításához."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 4529415..fe14938 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Միացնել մարտկոցի տնտեսումը"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Կարգավորումներ"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Ինքնաթիռային ռեժիմ"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Ինքնապտտվող էկրան"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"Համրեցնել"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"Ինքնաշխատ"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ապակողպել"</string>
     <string name="phone_label" msgid="2320074140205331708">"բացել հեռախոսը"</string>
     <string name="camera_label" msgid="7261107956054836961">"բացել ֆոտոխցիկը"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Ընտրել առաջադրանքի նոր դասավորություն"</string>
+    <string name="cancel" msgid="6442560571259935130">"Չեղարկել"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Համատեղելիության խոշորացման կոճակը:"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Դիտափոխել փոքրից ավելի մեծ էկրան:"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-ը միացված է:"</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Ինքնաթիռային ռեժիմը միացավ:"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Չխանգարելու ընտրանքը միացված է: Ընդհատել միայն կարևոր ծանուցումների դեպքում:"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Չխանգարելու ընտրանքը միացված է: Չընդհատել:"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Չխանգարելու ընտրանքն անջատված է:"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Չխանգարելու ընտրանքն անջատվեց:"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Չխանգարելու ընտրանքը միացվեց:"</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Ցերեկային ռեժիմ"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Ինքնաթիռային ռեժիմ"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Չխանգարել"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Միայն կարևոր ծանուցումների դեպքում"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Չընդհատել"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> սարք)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ցանց չկա"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi-ը անջատված է"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Հասանելի պահված ցանցեր չկան"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Հեռարձակում"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Հեռարձակում"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Անանուն սարք"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Պատրաստ է հեռարձակման"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Առանց ընդհատումների՝ ներառյալ զարթուցիչները:"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Առանց ընդհատումների"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Միայն կարևոր ընդհատումներ"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Ձեր հաջորդ զարթուցիչի ժամն է՝ <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Ձեր հաջորդ զարթուցիչի օրն է՝ <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Դուք չեք լսի ձեր զարթուցիչը <xliff:g id="ALARM_TIME">%s</xliff:g>-ին:"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Սահեցրեք վերև` ապակողպելու համար"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Հեռախոսի համար սահեցրեք աջ"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Խցիկի համար սահեցրեք ձախ"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"-"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Կարևորություն"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Բոլորը"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Լիցքավորում (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> մինչև լրիվ լիցքավորումը)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Անջատել օգտվողին"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Փոխել օգտվողին. ներկայիս օգտվողն է՝ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Մերժել"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ձայնի ուժգնության երկխոսության հավելված է"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Դիպչեք՝ սկզբնօրինակը վերականգնելու համար:"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 5bf8d13..3a1c0f3 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Aktifkan penghemat baterai"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Setelan"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode pesawat"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Rotasi layar otomatis"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"BUNGKAM"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"buka kunci"</string>
     <string name="phone_label" msgid="2320074140205331708">"buka ponsel"</string>
     <string name="camera_label" msgid="7261107956054836961">"buka kamera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Pilih tata letak tugas baru"</string>
+    <string name="cancel" msgid="6442560571259935130">"Batal"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tombol perbesar/perkecil kompatibilitas."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Perbesar dari layar kecil ke besar."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tersambung."</string>
@@ -178,6 +179,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Mode pesawat diaktifkan."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Status \"Jangan ganggu\" aktif, hanya untuk prioritas."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Status \"Jangan ganggu\" aktif, tanpa gangguan."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Jangan ganggu aktif, hanya alarm."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Status \"Jangan ganggu\" nonaktif."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Status \"Jangan ganggu\" dinonaktifkan."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Status \"Jangan ganggu\" diaktifkan."</string>
@@ -228,9 +230,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"Etalase Hidangan Penutup"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Lamunan"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode pesawat"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Jangan ganggu"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Hanya untuk prioritas"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Hanya alarm"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Tanpa gangguan"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Perangkat)"</string>
@@ -301,6 +303,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Tanpa gangguan, termasuk alarm."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Tidak ada interupsi"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Hanya interupsi prioritas"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"Hanya alarm"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Alarm Anda berikutnya pukul <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Alarm Anda berikutnya hari <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Anda tidak akan mendengar alarm pukul <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -310,9 +313,15 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Gesek ke atas untuk membuka kunci"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Gesek ke kanan untuk menelepon"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Gesek ke kiri untuk kamera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Tidak ada"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritas"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"Hanya alarm"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"Semua"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"Tidak ada\ngangguan"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Hanya\nprioritas"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Hanya\nalarm"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengisi daya (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Beralih pengguna"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Ganti pengguna, pengguna saat ini <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -380,4 +389,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tolak"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> adalah dialog volume"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan aslinya."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 1ae4566..a34abb2 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Kveikja á rafhlöðusparnaði"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Stillingar"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flugstilling"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Snúa skjá sjálfkrafa"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ÞAGGA"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"SJÁLFV"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"taka úr lás"</string>
     <string name="phone_label" msgid="2320074140205331708">"opna síma"</string>
     <string name="camera_label" msgid="7261107956054836961">"opna myndavél"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Velja nýtt útlit verkefna"</string>
+    <string name="cancel" msgid="6442560571259935130">"Hætta við"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Hnappur fyrir samhæfisaðdrátt."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aðlaga forrit fyrir lítinn skjá að stærri skjá."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tengt."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Kveikt á flugstillingu."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Kveikt á „Ónáðið ekki“, aðeins forgangur."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Kveikt á „Ónáðið ekki“, engar truflanir."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Slökkt á „Ónáðið ekki“."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Slökkt á „Ónáðið ekki“."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Kveikt á „Ónáðið ekki“."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Eftirréttaborð"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Skjávari"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flugstilling"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Ónáðið ekki"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Aðeins forgangur"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Engar truflanir"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> tæki)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ekkert net"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Slökkt á Wi-Fi"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Engin vistuð net til staðar"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Útsending"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Sendir út"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Ónefnt tæki"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Tilbúið í útsendingu"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Engar truflanir. Ekki einu sinni vekjarar."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Engin truflun"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Aðeins forgangstruflanir"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Næsti vekjari er kl. <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Næsti vekjari er <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Ekki mun heyrast í vekjaranum kl. <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Strjúktu upp til að opna"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Strjúktu til hægri fyrir síma"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Strjúktu til vinstri fyrir myndavél"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Engar"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Forgangur"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Allar"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Í hleðslu (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> fram að fullri hleðslu)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Skipta um notanda"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Skipta um notanda; núverandi notandi er <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Hafna"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er hljóðstyrksvalmyndin"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Snertu til að færa í upprunalegt horf."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index c9ccf05..6abc7a1 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Attiva risparmio energetico"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Impostazioni"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modalità aereo"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Rotazione automatica schermo"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"sblocca"</string>
     <string name="phone_label" msgid="2320074140205331708">"apri telefono"</string>
     <string name="camera_label" msgid="7261107956054836961">"apri fotocamera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Seleziona un nuovo layout per le attività"</string>
+    <string name="cancel" msgid="6442560571259935130">"Annulla"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Pulsante zoom compatibilità."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom inferiore per schermo più grande."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth collegato."</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Modalità aereo attivata."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\"Non disturbare\" attivo, solo con priorità."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\"Non disturbare\" attivo, nessuna interruzione."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Non disturbare\" non attivo."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Non disturbare\" non attivo."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Non disturbare\" attivo."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Vetrina di dolci"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modalità aereo"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Non disturbare"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Solo con priorità"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Nessuna interruzione"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivi)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nessuna rete"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi disattivato"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Nessuna rete salvata disponibile"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Trasmetti"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"In trasmissione"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Dispositivo senza nome"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Pronto a trasmettere"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Senza interruzioni. Neanche sveglie."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Nessuna interruzione"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Solo interruzioni con priorità"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Il tuo prossimo allarme è alle ore <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Il tuo prossimo allarme è il giorno <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Il tuo allarme non suonerà alle <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Scorri verso l\'alto per sbloccare"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Scorri verso destra per accedere al telefono"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Scorri verso sinistra per accedere alla fotocamera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Nessuna"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Priorità"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Tutte"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"In carica (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> al termine)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Cambio utente"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Cambia utente, utente corrente <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Nega"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> rappresenta la finestra di dialogo relativa al volume"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Tocca per ripristinare l\'originale."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ff7fc57..15c74cf 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -46,7 +46,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"הפעל חיסכון בסוללה"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"הגדרות"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"מצב טיסה"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"סיבוב אוטומטי של המסך"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"השתק"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"אוטומטי"</string>
@@ -90,6 +89,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"בטל את הנעילה"</string>
     <string name="phone_label" msgid="2320074140205331708">"פתח את הטלפון"</string>
     <string name="camera_label" msgid="7261107956054836961">"פתח את המצלמה"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"בחר פריסה חדשה להצגת משימות"</string>
+    <string name="cancel" msgid="6442560571259935130">"ביטול"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"לחצן מרחק מתצוגה של תאימות."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"שנה מרחק מתצוגה של מסך קטן לגדול יותר."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"‏Bluetooth מחובר."</string>
@@ -180,6 +181,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"מצב טיסה הופעל."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\'נא לא להפריע\' פועל. הודעות בעדיפות בלבד."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\'נא לא להפריע\' פועל. ללא הפרעות."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"\'נא לא להפריע\' הופעל. התראות בלבד."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\'נא לא להפריע\' כבוי."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\'נא לא להפריע\' כבוי."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\'נא לא להפריע\' פועל."</string>
@@ -230,9 +232,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"מזנון קינוחים"</string>
     <string name="start_dreams" msgid="7219575858348719790">"חלום בהקיץ"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"מצב טיסה"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"נא לא להפריע"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"עדיפות בלבד"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"התראות בלבד"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"ללא הפרעות"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"‏Bluetooth ‏(<xliff:g id="NUMBER">%d</xliff:g> מכשירים)"</string>
@@ -259,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"אין רשת"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"‏Wi-Fi כבוי"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"אין רשתות שמורות זמינות"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"מעביר"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"מכשיר ללא שם"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"מוכן להעביר"</string>
@@ -304,6 +305,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"ללא הפרעות. גם לא התראות."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"ללא הפרעות"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"רק הפרעות בעדיפות גבוהה"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"התראות בלבד"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"ההתראה הבאה שלך היא ב-<xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"ההתראה הבאה שלך היא ב<xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"לא תשמע את ההתראה שלך ב-<xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -313,9 +315,15 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"החלק מעלה כדי לבטל את הנעילה"</string>
     <string name="phone_hint" msgid="3101468054914424646">"כדי להפעיל את הטלפון, החלק שמאלה"</string>
     <string name="camera_hint" msgid="5241441720959174226">"החלק ימינה להפעלת המצלמה"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"ללא"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"עדיפות"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"התראות בלבד"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"הכל"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"ללא\nהפרעות"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"התראות בעדיפות\nבלבד"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"התראות\nבלבד"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"טוען (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> עד לסיום)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"החלפת משתמש"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"החלף משתמש. המשתמש הנוכחי הוא <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +391,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"דחה"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> הוא תיבת הדו-שיח של עוצמת הקול"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"גע כדי לשחזר את עוצמת הקול המקורית."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index ca6aec9..1cf20df 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"バッテリーセーバーをONにします"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"設定"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"機内モード"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"自動回転画面"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ミュート"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"オート"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ロック解除"</string>
     <string name="phone_label" msgid="2320074140205331708">"電話を起動"</string>
     <string name="camera_label" msgid="7261107956054836961">"カメラを起動"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"新しいタスクレイアウトの選択"</string>
+    <string name="cancel" msgid="6442560571259935130">"キャンセル"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"互換ズームボタン。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"小さい画面から大きい画面に拡大。"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetoothに接続済み。"</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"機内モードをONにしました。"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"[通知を非表示]はONで、重要な通知のみです。"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"[通知を非表示]はONで、サイレントです。"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"[通知を非表示]はOFFです。"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"[通知を非表示]をOFFにしました。"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"[通知を非表示]をONにしました。"</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"デザートケース"</string>
     <string name="start_dreams" msgid="7219575858348719790">"スクリーンセーバー"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"イーサネット"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"機内モード"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"通知を非表示"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"重要な通知のみ"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"サイレント"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth(端末数<xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ネットワークなし"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi OFF"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"保存されているネットワークがありません"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"キャスト"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"キャストしています"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"名前のないデバイス"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"キャスト準備完了"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"サイレント(アラームも鳴りません)"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"サイレント"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"重要な通知のみ"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"次のアラームは<xliff:g id="ALARM_TIME">%s</xliff:g>です"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"次のアラームは<xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>です"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g>のアラームは鳴りません"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"ロック解除するには上にスワイプしてください"</string>
     <string name="phone_hint" msgid="3101468054914424646">"右にスワイプして電話を表示"</string>
     <string name="camera_hint" msgid="5241441720959174226">"左にスワイプしてカメラを表示"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"なし"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"重要"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"すべて"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中(フル充電まで<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ユーザーを切り替える"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ユーザーを切り替える、現在のユーザーは<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"許可しない"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>を音量ダイアログとして使用"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"タップすると元の音量ダイアログが復元されます。"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 100af70..2432abe 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"ბატარეის დაზოგვის ჩართვა"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"პარამეტრები"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"თვითმფრინავის რეჟიმი"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"ავტოროტაციის ეკრანი"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"დადუმება"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ავტო."</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"განბლოკვა"</string>
     <string name="phone_label" msgid="2320074140205331708">"ტელეფონის გახსნა"</string>
     <string name="camera_label" msgid="7261107956054836961">"კამერის გახსნა"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"ახალი ამოცანის განლაგების არჩევა"</string>
+    <string name="cancel" msgid="6442560571259935130">"გაუქმება"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"თავსებადი მასშტაბირების ღილაკი."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"შეცვალეთ პატარა ეკრანი უფრო დიდით."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth დაკავშირებულია."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"თვითმფრინავის რეჟიმი ჩაირთო."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"ჩართულია რეჟიმი „არ შემაწუხოთ\", მხოლოდ პრიორიტეტები."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"ჩართულია რეჟიმი „არ შემაწუხოთ\", შეწყვეტის გარეშე."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"„არ შემაწუხოთ“ გამორთულია"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"„არ შემაწუხოთ\" რეჟიმი გამორთულია."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"„არ შემაწუხოთ\" რეჟიმი ჩართულია."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"სადესერტო ყუთი"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ეთერნეტი"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"თვითმფრინავის რეჟიმი"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"არ შემაწუხოთ"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"მხოლოდ პრიორიტეტული"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"შეფერხებების გაეშე"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> მოწყობილობა)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ქსელი არ არის"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi გამორთულია"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"შენახული ქსელები მიუწვდომელია"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"ტრანსლირება"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"გადაიცემა"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"უსახელო მოწყობილობა"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"მზად არის სამაუწყებლოდ"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"წყვეტების გარეშე. მაღვიძარების შემთხვევაშიც კი."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"შეწყვეტების გარეშე"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"მხოლოდ პრიორიტეტული შეწყვეტები"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"თქვენი შემდეგი მაღვიძარაა <xliff:g id="ALARM_TIME">%s</xliff:g>-ზე"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"თქვენი შემდეგი მაღვიძარაა <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"თქვენს მაღვიძარას <xliff:g id="ALARM_TIME">%s</xliff:g>-ზე ვერ გაიგონებთ"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"გაასრიალეთ ზევით განსაბლოკად"</string>
     <string name="phone_hint" msgid="3101468054914424646">"გადაფურცლეთ მარჯვნივ ტელეფონისთვის"</string>
     <string name="camera_hint" msgid="5241441720959174226">"კამერისთვის მარცხენა შენაცვლება"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"არცერთი"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"პრიორიტეტი"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"ყველა"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>-ის შეცვლა დასრულებამდე)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"მომხმარებლის გადართვა"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"მომხმარებლის გდართვა. ამჟამინდელი მომხმარებელი <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"უარყოფა"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ხმოვან დიალოგშია"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"ორიგინალის აღდგენისათვის, შეეხეთ."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 9ed07ca..062bf95 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Батарея үнемдегішін қосу"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Параметрлер"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Ұшақ режимі"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Авто айналатын экран"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ҮНСІЗ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"Авто"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"бекітпесін ашу"</string>
     <string name="phone_label" msgid="2320074140205331708">"телефонды ашу"</string>
     <string name="camera_label" msgid="7261107956054836961">"камераны ашу"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Жаңа тапсырма пішімін таңдау"</string>
+    <string name="cancel" msgid="6442560571259935130">"Бас тарту"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Үйлесімділік ұлғайту түймесі."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Үлкендеу экранда кішірейту."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth қосылған."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Ұшақ режимі қосылды."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Мазаламау режимі қосулы, тек басымдық"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Мазаламау режимі қосулы, үзілістерсіз"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Мазаламау режимі өшірулі"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Мазаламау режимі өшірілді."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Мазаламау режимі қосылды."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Десерт жағдайы"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Қалғу"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Этернет"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Ұшақ режимі"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Мазаламау"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Тек басымдық"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Үзулерсіз"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> құрылғылары)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Желі жоқ"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi өшірулі"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Сақталған желілер қол жетімді емес"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Трансляциялау"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Трансляциялануда"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Атаусыз құрылғы"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Трансляциялауға дайын"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Үзілулер болмайды. Тіпті дабылдар да."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Үзулерсіз"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Тек басым үзулер"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Келесі дабыл — <xliff:g id="ALARM_TIME">%s</xliff:g> уақытында"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Келесі дабыл — <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> уақытында дабылды естімейсіз"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Бекітпесін ашу үшін жанаңыз"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Телефон үшін оңға жанаңыз"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Камера үшін солға жанаңыз"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Ешқандай"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Басымдық"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Барлығы"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Зарядталуда (толғанша <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Пайдаланушыны ауыстыру"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Пайдаланушыны ауыстыру, ағымдағы пайдаланушы <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Өшіру"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> — көлем диалогтық терезесі"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнұсқаны қалпына келтіру үшін түртіңіз."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index de48a23..77cc79f 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"បើក​ធាតុ​រក្សា​ថាមពល​ថ្ម"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ការ​កំណត់"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"វ៉ាយហ្វាយ"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"ពេល​ជិះ​យន្តហោះ"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"បង្វិល​អេក្រង់​ស្វ័យ​ប្រវត្តិ"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ស្ងាត់"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ស្វ័យប្រវត្តិ"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ដោះ​សោ"</string>
     <string name="phone_label" msgid="2320074140205331708">"បើក​ទូរស័ព្ទ"</string>
     <string name="camera_label" msgid="7261107956054836961">"បើក​ម៉ាស៊ីន​ថត"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"ជ្រើសប្លង់ភារកិច្ចថ្មី"</string>
+    <string name="cancel" msgid="6442560571259935130">"បោះ​បង់​"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ប៊ូតុង​ពង្រីក​ត្រូវ​គ្នា។"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ពង្រីក/បង្រួម​​អេក្រង់​ពី​​ទៅធំ"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"បាន​តភ្ជាប់​ប៊្លូធូស។"</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"បាន​បើក​របៀប​ជិះ​យន្តហោះ។"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"បានបើកមុខងារកុំរំខាន (អាទិភាពប៉ុណ្ណោះ)។"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"បានបើកមុខងារកុំរំខាន សូមកុំរំខាន"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"បានបិទមុខងារកុំរំខាន។"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"បានបិទមុខងារកុំរំខាន។"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"បានបើកមុខងារកុំរំខាន។"</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"ករណី Dessert"</string>
     <string name="start_dreams" msgid="7219575858348719790">"ធាតុ​រក្សា​អេក្រង់"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"អ៊ីសឺរណិត"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"របៀបពេល​​ជិះ​យន្តហោះ"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"កុំរំខាន"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"អាទិភាពប៉ុណ្ណោះ"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"សូមកុំរំខាន"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ប៊្លូធូស"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ប៊្លូធូស (ឧបករណ៍ <xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"គ្មាន​បណ្ដាញ"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"វ៉ាយហ្វាយ​បានបិទ"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"មិន​មាន​បណ្ដាញ​ដែល​បាន​រក្សាទុក"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"ខាស"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"ការ​ចាត់​ថ្នាក់"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"ឧបករណ៍​​ដែល​មិន​មាន​ឈ្មោះ"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"ត្រៀម​រួចរាល់​ដើម្បី​ចាត់​ថ្នាក់"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"គ្មាន​ការ​ផ្អាក។ គ្មាន​ការ​ជូនដំណឹង​ពី​ព្រឹត្តិការណ៍។"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"គ្មាន​ការ​ផ្អាក"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"តែ​ការ​ផ្អាក​អាទិភាព​ប៉ុណ្ណោះ"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"ការ​ជូនដំណឹង​បន្ទាប់​របស់​អ្នក​គឺនៅម៉ោង <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"ការ​ជូនដំណឹង​បន្ទាប់​របស់​អ្នក​គឺ​នៅ <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"អ្នកនឹងមិនឮការជូន​ដំណឹងរបស់អ្នកនៅម៉ោង <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"អូស​ឡើង​លើ ដើម្បី​ដោះ​សោ"</string>
     <string name="phone_hint" msgid="3101468054914424646">"អូស​ទៅ​ស្ដាំ​ដើម្បី​បើក​​ទូរស័ព្ទ"</string>
     <string name="camera_hint" msgid="5241441720959174226">"អូស​ទៅ​ឆ្វេង​​ដើម្បី​ប្រើ​​ម៉ាស៊ីន​ថត"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"គ្មាន"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"អាទិភាព"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"ទាំងអស់"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"កំពុង​បញ្ចូល​ថ្ម (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ទើប​ពេញ)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ប្ដូរ​អ្នក​ប្រើ"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ប្ដូរ​អ្នកប្រើ ​អ្នកប្រើ​បច្ចុប្បន្ន <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"បដិសេធ"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> គឺជាប្រអប់សម្លេង"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"ប៉ះដើម្បីស្តារច្បាប់ដើម។"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 2687de1..a0fe152 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"ಬ್ಯಾಟರಿ ಉಳಿತಾಯವನ್ನು ಆನ್ ಮಾಡಿ"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"ಪರದೆಯನ್ನು ಸ್ವಯಂ-ತಿರುಗಿಸಿ"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ಮ್ಯೂಟ್"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ಸ್ವಯಂ"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ಅನ್‌ಲಾಕ್ ಮಾಡು"</string>
     <string name="phone_label" msgid="2320074140205331708">"ಫೋನ್ ತೆರೆಯಿರಿ"</string>
     <string name="camera_label" msgid="7261107956054836961">"ಕ್ಯಾಮರಾ ತೆರೆಯಿರಿ"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"ಹೊಸ ಕಾರ್ಯ ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="cancel" msgid="6442560571259935130">"ರದ್ದುಮಾಡು"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ಹೊಂದಾಣಿಕೆಯ ಝೂಮ್ ಬಟನ್."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ಚಿಕ್ಕ ಪರದೆಯಿಂದ ದೊಡ್ಡ ಪರದೆಗೆ ಝೂಮ್ ಮಾಡು."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ಬ್ಲೂಟೂತ್‌‌ ಸಂಪರ್ಕಗೊಂಡಿದೆ."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್ ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆನ್, ಆದ್ಯತೆ ಮಾತ್ರ."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆನ್ ಆಗಿದೆ, ಯಾವುದೇ ಅಡಚಣೆಗಳಿಲ್ಲ."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆಫ್ ಆಗಿದೆ."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"ತೊಂದರೆ ಮಾಡಬೇಡಿ ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"ಡೆಸರ್ಟ್ ಕೇಸ್"</string>
     <string name="start_dreams" msgid="7219575858348719790">"ಡೇಡ್ರೀಮ್"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ಇಥರ್ನೆಟ್"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"ಆದ್ಯತೆ ಮಾತ್ರ"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"ಯಾವುದೇ ಅಡಚಣೆಗಳಿಲ್ಲ"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ಬ್ಲೂಟೂತ್‌"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ಬ್ಲೂಟೂತ್‌ (<xliff:g id="NUMBER">%d</xliff:g> ಸಾಧನಗಳು)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ನೆಟ್‌ವರ್ಕ್ ಇಲ್ಲ"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ಆಫ್"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"ಯಾವುದೇ ಉಳಿಸಲಾದ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"ಬಿತ್ತರಿಸುವಿಕೆ"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"ಬಿತ್ತರಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"ಹೆಸರಿಸದಿರುವ ಸಾಧನ"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"ಬಿತ್ತರಿಸಲು ಸಿದ್ದವಾಗಿದೆ"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"ಅಲಾರಂಗಳನ್ನು ಸೇರಿದಂತೆ ಯಾವುದೇ ಅಡಚಣೆಗಳಿಲ್ಲ."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"ಯಾವುದೇ ಅಡಚಣೆಗಳಿಲ್ಲ"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"ಆದ್ಯತೆಯ ಅಡಚಣೆಗಳು ಮಾತ್ರ"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"ನಿಮ್ಮ ಮುಂದಿನ ಅಲಾರಂ <xliff:g id="ALARM_TIME">%s</xliff:g> ಗೆ ಆಗಿದೆ"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"ನಿಮ್ಮ ಮುಂದಿನ ಅಲಾರಮ್ <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> ಆಗಿದೆ"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> ಗೆ ನೀವು ನಿಮ್ಮ ಅಲಾರಂ ಆಲಿಸುವುದಿಲ್ಲ"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"ಅನ್‌ಲಾಕ್‌ ಮಾಡಲು ಸ್ವೈಪ್‌ ಮಾಡಿ"</string>
     <string name="phone_hint" msgid="3101468054914424646">"ಫೋನ್‌ಗಾಗಿ ಬಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
     <string name="camera_hint" msgid="5241441720959174226">"ಕ್ಯಾಮರಾಗಾಗಿ ಎಡಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"ಯಾವುದೂ ಇಲ್ಲ"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"ಆದ್ಯತೆ"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"ಎಲ್ಲ"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ ( ಪೂರ್ತಿ ಆಗುವವರೆಗೆ <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ಬಳಕೆದಾರರನ್ನು ಬದಲಿಸಿ, ಪ್ರಸ್ತುತ ಬಳಕೆದಾರ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ನಿರಾಕರಿಸು"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಿದೆ"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"ಮೂಲ ಮರುಸ್ಥಾಪಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 993bef4..8884c83 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"배터리 절약 기능 사용"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"설정"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"비행기 모드"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"자동 화면 회전"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"무시"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"자동"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"잠금 해제"</string>
     <string name="phone_label" msgid="2320074140205331708">"휴대전화 열기"</string>
     <string name="camera_label" msgid="7261107956054836961">"카메라 열기"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"새 작업 레이아웃 선택"</string>
+    <string name="cancel" msgid="6442560571259935130">"취소"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"호환성 확대/축소 버튼입니다."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"작은 화면을 큰 화면으로 확대합니다."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"블루투스가 연결되었습니다."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"비행기 모드를 사용합니다."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"알림 일시중지 사용, 중요 알림만 수신"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"알림 일시중지 사용, 방해 금지"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"알림 일시중지 사용 중지"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"알림 일시중지가 사용 중지되었습니다."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"알림 일시중지를 사용합니다."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"디저트 케이스"</string>
     <string name="start_dreams" msgid="7219575858348719790">"화면 보호기"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"이더넷"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"비행기 모드"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"알림 일시중지"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"중요 알림만"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"방해 금지"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"블루투스"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"블루투스(<xliff:g id="NUMBER">%d</xliff:g>개의 기기)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"네트워크가 연결되지 않음"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 꺼짐"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"저장된 네트워크가 없습니다."</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"전송"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"전송 중"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"이름이 없는 기기"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"전송 준비 완료"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"어떤 방해도 받지 않습니다. 알람도 울리지 않습니다."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"모든 알림 차단"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"최우선 알림만 수신"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"다음 알람 시각: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"다음 알람 일시: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g>에 알람을 들을 수 없습니다."</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"위로 스와이프하여 잠금 해제"</string>
     <string name="phone_hint" msgid="3101468054914424646">"전화 기능을 사용하려면 오른쪽으로 스와이프하세요."</string>
     <string name="camera_hint" msgid="5241441720959174226">"카메라를 사용하려면 왼쪽으로 스와이프하세요."</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"수신 안함"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"최우선만 수신"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"모두 수신"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"충전 중(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> 후 충전 완료)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"사용자 전환"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"사용자 전환, 현재 사용자 <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -369,8 +384,8 @@
     <string name="notification_collapse_button_text" msgid="6883253262134328057">"모두 숨기기"</string>
     <string name="zen_mode_and_condition" msgid="4462471036429759903">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"화면 고정됨"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"고정 해제하기 전까지 계속 표시됩니다. 고정 해제하려면 뒤로와 개요를 동시에 길게 터치합니다."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"고정 해제하기 전까지 계속 표시됩니다. 고정 해제하려면 개요를 길게 터치합니다."</string>
+    <string name="screen_pinning_description" msgid="1346522416878235405">"고정 해제하기 전까지 계속 표시됩니다. 고정 해제하려면 뒤로와 최근 사용을 동시에 길게 터치합니다."</string>
+    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"고정 해제하기 전까지 계속 표시됩니다. 고정 해제하려면 최근 사용을 길게 터치합니다."</string>
     <string name="screen_pinning_positive" msgid="3783985798366751226">"확인"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"거부"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>을(를) 숨기시겠습니까?"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"거부"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>은(는) 볼륨 대화입니다."</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"원본을 복원하려면 터치하세요."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 25471e5..7b9625d 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -52,8 +52,6 @@
     <skip />
     <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
     <skip />
-    <!-- no translation found for status_bar_settings_airplane (4879879698500955300) -->
-    <skip />
     <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
     <skip />
     <!-- no translation found for status_bar_settings_mute_label (554682549917429396) -->
@@ -113,6 +111,9 @@
     <string name="unlock_label" msgid="8779712358041029439">"кулпуну ачуу"</string>
     <string name="phone_label" msgid="2320074140205331708">"телефонду ачуу"</string>
     <string name="camera_label" msgid="7261107956054836961">"камераны ачуу"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Жаңы тапшырманын планын тандаңыз"</string>
+    <!-- no translation found for cancel (6442560571259935130) -->
+    <skip />
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Масштабды сыйыштыруу баскычы."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Кичинекейди чоң экранга масштабдоо."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth байланышта"</string>
@@ -203,6 +204,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Учак режими күйгүзүлдү."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Тынчымды алба деген күйүк, артыкчылыктуулар гана."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Тынчымды алба деген күйүк, үзгүлтүккө учуратуулар жок."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Тынчымды алба деген өчүк."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Тынчымды алба деген өчүрүлдү."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Тынчымды алба деген күйгүзүлдү."</string>
@@ -253,9 +256,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Десерт себети"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Кыялдануу"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Учак тартиби"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Тынчымды алба"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Артыкчылык гана"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Үзгүлтүксүз"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> түзмөк)"</string>
@@ -282,8 +286,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Желе жок"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi өчүк"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Сакталган тармактар жок"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Тышкы экранга чыгаруу"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Тышкы экранга чыгарылууда"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Аты жок түзмөк"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Тышкы экранга чыгарууга даяр"</string>
@@ -327,6 +330,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Үзгүлтүктөр жок. Ойготкучтар дагы жок."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Үзгүлтүксүз"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Артыкчылыктуу үзгүлтүктөр гана"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Кийинки үн ишараты саат <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Кийинки үн ишараты <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Саат <xliff:g id="ALARM_TIME">%s</xliff:g> үн ишаратын укпайсыз."</string>
@@ -336,9 +341,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Кулпуну ачуу үчүн серпип коюңуз"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Телефонду колдонуу үчүн оңго серпип коюңуз"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Камераны ачуу үчүн солго серпип коюңуз"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Эч нерсе жок"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Артыкчылыктуу"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Бардыгы"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Кубатталууда (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> толгонго чейин)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Колдонуучуну которуу"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Колдонуучуну күйгүзүү, учурдагы колдонуучу <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -406,4 +421,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Жок"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> үндү катуулатуу диалогу"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнусканы калыбына келтирүү үчүн тийип коюңуз."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-land/styles.xml b/packages/SystemUI/res/values-land/styles.xml
index e58fbb1..8919198 100644
--- a/packages/SystemUI/res/values-land/styles.xml
+++ b/packages/SystemUI/res/values-land/styles.xml
@@ -18,10 +18,4 @@
     <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer">
         <item name="android:layout_width">360dp</item>
     </style>
-
-    <style name="SearchPanelScrim">
-        <item name="android:layout_width">@dimen/search_panel_scrim_height</item>
-        <item name="android:layout_height">match_parent</item>
-        <item name="android:layout_gravity">right</item>
-    </style>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 6ae0c71..8f75cf6 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"​ເປີດ​ໃຊ້​ໂຕ​ປະ​ຢັດ​ແບັດ​ເຕີ​ຣີ"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ການຕັ້ງຄ່າ"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"ໂໝດເທິງຍົນ"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"ໝຸນໜ້າຈໍອັດຕະໂນມັດ"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ປິດສຽງ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ອັດຕະໂນມັດ"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ປົດລັອກ"</string>
     <string name="phone_label" msgid="2320074140205331708">"​ເປີດ​​ແປ້ນ​ໂທ​ລະ​ສັບ"</string>
     <string name="camera_label" msgid="7261107956054836961">"ເປີດ​ກ້ອງ"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"ເລືອກ​ແຜນ​ຜັງ​ໜ້າ​ວຽກ​ໃໝ່"</string>
+    <string name="cancel" msgid="6442560571259935130">"ຍົກເລີກ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ປຸ່ມຊູມທີ່ໃຊ້ຮ່ວມກັນໄດ້."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ຊູມຈໍນ້ອຍໄປເປັນຈໍຂະຫນາດໃຫຍ່."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ເຊື່ອມຕໍ່ Bluetooth ແລ້ວ."</string>
@@ -178,6 +179,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"ເປີດ​ໂໝດ​ຢູ່​ໃນ​ຍົນ​ແລ້ວ."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"ຫ້າມ​ລະ​ກວນ​ເປີດ​ຢູ່, ບຸ​ລິ​ມະ​ສິດ​ເທົ່າ​ນັ້ນ."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"ຫ້າມ​ລະ​ກວນ​ເປີດ​ຢູ່, ບໍ່​ມີ​ການ​ຂັດ​ຈັງ​ຫວະ."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"ຫ້າມ​ລົບ​ກວນ​ເປີດ​ຢູ່, ໂມງ​ປຸກ​ເທົ່າ​ນັ້ນ."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"ຫ້າມ​ລົບ​ກວນປິດຢູ່."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"ຢ່າ​ລົບ​ກວນ​ປິດ​ແລ້ວ."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"ຢ່າ​ລົບ​ກວນ​ເປີດ​ແລ້ວ."</string>
@@ -228,9 +230,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"ກ່ອງຂອງຫວານ"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ໂໝດຢູ່ໃນຍົນ"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"ຫ້າມ​ລົບ​ກວນ"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"ບຸ​ລິ​ມະ​ສິດເທົ່າ​ນັ້ນ"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"ໂມງ​ປຸກ​ເທົ່າ​ນັ້ນ"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"ບໍ່​ມີ​ການ​ລົບກວນ"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ອຸປະກອນ)"</string>
@@ -301,6 +303,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"ບໍ່​ມີ​ການ​ລົບ​ກວນ. ບໍ່​ວ່າ​ຈະ​ເປັນ​​ໂມງ​ປຸກ​ກໍ​ຕາມ."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"ບໍ່​ມີ​ການ​ລົບກວນ"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"ສະເພາະ​ເລື່ອງ​ສຳຄັນ​ເທົ່ານັນ"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"ໂມງ​ປຸກ​ເທົ່າ​ນັ້ນ"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"ໂມງ​ປຸກ​ຖັດ​ໄປ​ຂອງ​ທ່ານ​ແມ່ນ <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"ໂມງ​ປຸກ​ຖັດ​ໄປ​ຂອງ​ທ່ານ​ແມ່ນ <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"ທ່ານ​ຈະ​ບໍ່​ໄດ້​ຍິນ​ສຽງ​ໂມງ​ປຸກ​ໃນ​ເວ​ລາ <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -310,9 +313,15 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນ​ຂຶ້ນ​ເພື່ອ​ປົດ​ລັອກ"</string>
     <string name="phone_hint" msgid="3101468054914424646">"ປັດ​ຂວາ​ເພື່ອ​ໃຊ້​ໂທ​ລະ​ສັບ"</string>
     <string name="camera_hint" msgid="5241441720959174226">"ປັດ​ຊ້າຍ​ເພື່ອ​ໃຊ້​ກ້ອງ"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"ບໍ່ມີ"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"ລະດັບຄວາມສຳຄັນ"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"ໂມງ​ປຸກ​ເທົ່າ​ນັ້ນ"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"ທັງໝົດ"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"ບໍ່​ມີ\nລົບ​ກວນ"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ບຸ​ລິ​ມະ​ສິດ\nເທົ່າ​ນັ້ນ"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ໂມງ​ປຸກ\nເທົ່າ​ນັ້ນ"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ກຳ​ລັງ​ສາກ​ໄຟ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ກວ່າ​ຈ​ະ​ເຕັມ)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ສະ​ລັບ​ຜູ່ໃຊ້"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ປ່ຽນຜູ່ໃຊ້, ຜູ່ໃຊ້ປະຈຸບັນ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -380,4 +389,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ປະຕິເສດ"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ແມ່ນ​ໜ້າ​ຕ່າງ​ລະ​ດັບ​ສຽງ"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"ສໍາ​ຜັດ​ເພື່ອກູ້​ຄືນ​ຕົ້ນ​ສະ​ບັບ​."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 0fc6fbb..31401c8 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -46,7 +46,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Įj. Akum. tausojimo priemonę"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nustatymai"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lėktuvo režimas"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Automatiškai sukti ekraną"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"NUTILD."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
@@ -90,6 +89,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"atrakinti"</string>
     <string name="phone_label" msgid="2320074140205331708">"atidaryti telefoną"</string>
     <string name="camera_label" msgid="7261107956054836961">"atidaryti fotoaparatą"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Pasirinkti naują užduoties išdėstymą"</string>
+    <string name="cancel" msgid="6442560571259935130">"Atšaukti"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Suderinamumo priartinimo mygtukas."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Padidinti ekraną."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"„Bluetooth“ prijungtas."</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Lėktuvo režimas įjungtas."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Funkcija „Netrukdyti“ įjungta. Tik prioritetiniai įvykiai."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Funkcija „Netrukdyti“ įjungta. Jokių pertraukčių."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Funkcija „Netrukdyti“ išjungta."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Funkcija „Netrukdyti“ išjungta."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Funkcija „Netrukdyti“ įjungta."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Desertų dėklas"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Svajonė"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Eternetas"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lėktuvo režimas"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Netrukdyti"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Tik prioritetiniai įvykiai"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Jokių pertraukčių"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"„Bluetooth“ (<xliff:g id="NUMBER">%d</xliff:g> įreng.)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tinklo nėra"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"„Wi-Fi“ išjungta"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Nėra pasiekiamų išsaugotų tinklų"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Perdavimas"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Perduodama"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Įrenginys be pavadinimo"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Paruošta perduoti"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Nėra trikdžių. Nėra net įspėjimų."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Jokių pertraukčių"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Tik prioritetinės pertrauktys"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Kito signalo laikas: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Kito signalo laikas: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> signalo negirdėsite"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Perbraukite aukštyn, kad atrakintumėte"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Perbraukite į dešinę, kad galėtumėte skambinti"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Perbraukite į kairę, kad būtų įjungtas fotoaparatas"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Nėra"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritetas"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Visi"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Kraunama (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> iki visiško įkrovimo)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Perjungti naudotoją"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Perjungti naudotoją, dabartinis naudotojas <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Atmesti"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ yra garsumo valdymo dialogo langas"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Palieskite, kad atkurtumėte originalą."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 54cc36a..5a10fd5 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -45,7 +45,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Ieslēgt akumulatora jaudas taupīšanu"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Iestatījumi"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lidmašīnas režīms"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Automātiska ekrāna pagriešana"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"IZ. SK."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
@@ -89,6 +88,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"atbloķēt"</string>
     <string name="phone_label" msgid="2320074140205331708">"atvērt tālruni"</string>
     <string name="camera_label" msgid="7261107956054836961">"atvērt kameru"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Atlasiet jaunu uzdevumu izkārtojumu"</string>
+    <string name="cancel" msgid="6442560571259935130">"Atcelt"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Saderības tālummaiņas poga."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Veikt tālummaiņu no mazāka ekrāna uz lielāku."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth savienojums ir izveidots."</string>
@@ -179,6 +180,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Lidojuma režīms ir ieslēgts."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Statuss Netraucēt ir ieslēgts, izvēlēts iestatījums Tikai prioritārie."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Statuss Netraucēt ir ieslēgts, izvēlēts iestatījums Bez pārtraukumiem."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Statuss Netraucēt ir izslēgts."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Statuss Netraucēt tika izslēgts."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Statuss Netraucēt tika ieslēgts."</string>
@@ -229,9 +232,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Saldo ēdienu stends"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Ekrānsaudzētājs"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Tīkls Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Lidojuma režīms"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Netraucēt"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Tikai prioritārie"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Bez pārtraukumiem"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ierīce(-es))"</string>
@@ -258,8 +262,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nav tīkla"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ir izslēgts"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Nav pieejams neviens saglabātais tīkls."</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Apraide"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Notiek apraide…"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Nenosaukta ierīce"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Gatavs apraidei"</string>
@@ -303,6 +306,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Bez traucējumiem. Pat bez brīdinājumiem"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Nepārtraukt"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Tikai prioritārie pārtraukumi"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Jūsu nākamā signāla laiks: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Jūsu nākamā signāla datums un laiks: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Jūs nedzirdēsiet iestatīto signālu: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -312,9 +317,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Velciet uz augšu, lai atbloķētu"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Lai lietotu tālruni, velciet pa labi."</string>
     <string name="camera_hint" msgid="5241441720959174226">"Lai lietotu kameru, velciet pa kreisi."</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Nav"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritāte"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Visi"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Notiek uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> līdz pilnīgai uzlādei)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Mainīt lietotāju"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Pārslēgt lietotāju; pašreizējais lietotājs: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -382,4 +397,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Neatļaut"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ir skaļuma dialoglodziņš"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Pieskarieties, lai atjaunotu sākotnējo."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 2be9c4c..d62aad1 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Вклучете го штедачот на батерија"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Подесувања"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим на работа во авион"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Автоматско ротирање на екранот"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ИСКЛ."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"Автоматски"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"отклучи"</string>
     <string name="phone_label" msgid="2320074140205331708">"отвори телефон"</string>
     <string name="camera_label" msgid="7261107956054836961">"отвори камера"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Изберете нов распоред на задача"</string>
+    <string name="cancel" msgid="6442560571259935130">"Откажи"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Копче за компатибилност на зум."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Зумот е помал на поголем екран."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth е поврзан."</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Авионскиот режим е вклучен."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"„Не вознемирувај“ е вклучено, само приоритетни."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"„Не вознемирувај“ е вклучено, без прекини."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"„Не вознемирувај“ е исклучено."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"„Не вознемирувај“ е исклучено."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"„Не вознемирувај“ е вклучено."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Етернет"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим на работа во авион"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Не вознемирувај"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Само приоритетно"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Без прекини"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> уреди)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нема мрежа"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi е исклучено"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Нема достапни зачувани мрежи"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Емитувај"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Емитување"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Неименуван уред"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Подготвено за емитување"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Без прекини. Дури и без аларми."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Без прекини"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Само приоритетни прекини"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Следниот аларм е во <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Следниот аларм е <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Нема да го слушнете алармот во <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Повлечете за да се отклучи"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Повлечете надесно за телефон"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Повлечете налево за камера"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Ништо"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Приоритет"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Сѐ"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Се полни (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> додека не се наполни)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Промени го корисникот"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Промени го корисникот, тековен корисник <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Одбиј"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> е дијалог за јачина на звук"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Допрете за да го вратите оригиналот."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index c446927..e232e27 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"ബാറ്ററി സേവർ ഓണാക്കുക"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ക്രമീകരണങ്ങൾ"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"ഫ്ലൈറ്റ് മോഡ്"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"സ്‌ക്രീൻ യാന്ത്രികമായി തിരിക്കുക"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"മ്യൂട്ടുചെയ്യുക"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"യാന്ത്രികം"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"അൺലോക്കുചെയ്യുക"</string>
     <string name="phone_label" msgid="2320074140205331708">"ഫോൺ തുറക്കുക"</string>
     <string name="camera_label" msgid="7261107956054836961">"ക്യാമറ തുറക്കുക"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"പുതിയ ടാസ്‌ക് ലേഔട്ട് തിരഞ്ഞെടുക്കുക"</string>
+    <string name="cancel" msgid="6442560571259935130">"റദ്ദാക്കുക"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"അനുയോജ്യതാ സൂം ബട്ടൺ."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ചെറുതിൽ നിന്ന് വലിയ സ്‌ക്രീനിലേക്ക് സൂം ചെയ്യുക."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ബ്ലൂടൂത്ത് കണക്‌റ്റുചെയ്തു."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"ഫ്ലൈറ്റ് മോഡ് ഓണാക്കി."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"ശല്യപ്പെടുത്തരുത് എന്നത് ഓണാണ്, മുൻഗണന മാത്രം."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"ശല്യപ്പെടുത്തരുത് എന്നത് ഓണാണ്, തടസ്സങ്ങളൊന്നുമില്ല."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"ശല്ല്യപ്പെടുത്തരുത് എന്നത് ഓഫാണ്."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"ശല്യപ്പെടുത്തരുത് എന്നത് ഓഫാക്കി."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"ശല്യപ്പെടുത്തരുത് എന്നത് ഓണാക്കി."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"ഡെസേർട്ട് കെയ്സ്"</string>
     <string name="start_dreams" msgid="7219575858348719790">"ഡേഡ്രീം"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ഇതർനെറ്റ്"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ഫ്ലൈറ്റ് മോഡ്"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"ശല്ല്യപ്പെടുത്തരുത്"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"മുൻഗണന മാത്രം"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"തടസ്സങ്ങളൊന്നുമില്ല"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ബ്ലൂടൂത്ത്"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ബ്ലൂടൂത്ത് (<xliff:g id="NUMBER">%d</xliff:g> ഉപകരണങ്ങൾ)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"നെറ്റ്‌വർക്ക് ഒന്നുമില്ല"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ഓഫുചെയ്യുക"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"സംരംക്ഷിച്ച നെറ്റ്‌വർക്കുകളൊന്നും ലഭ്യമല്ല"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"കാസ്‌റ്റുചെയ്യുക"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"കാസ്റ്റുചെയ്യുന്നു"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"പേരിടാത്ത ഉപകരണം"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"കാസ്‌റ്റ് ചെയ്യാൻ തയ്യാറാണ്"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"തടസ്സങ്ങളൊന്നുമില്ല. അലാറങ്ങൾ പോലുമില്ല."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"തടസ്സങ്ങളൊന്നുമില്ല"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"മുൻഗണനാ തടസ്സങ്ങൾ മാത്രം"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"നിങ്ങളുടെ അടുത്ത അലാറം <xliff:g id="ALARM_TIME">%s</xliff:g>-നാണ്"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"നിങ്ങളുടെ അടുത്ത അലാറം <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>-നാണ്"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"നിങ്ങൾ <xliff:g id="ALARM_TIME">%s</xliff:g>-ന് അലാറം കേൾക്കില്ല"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"അൺലോക്കുചെയ്യുന്നതിന് മുകളിലേക്ക് സ്വൈപ്പുചെയ്യുക"</string>
     <string name="phone_hint" msgid="3101468054914424646">"ഫോണിനായി വലതുവശത്ത് സ്വൈപ്പുചെയ്യുക"</string>
     <string name="camera_hint" msgid="5241441720959174226">"ക്യാമറയ്‌ക്കായി ഇടതുവശത്ത് സ്വൈപ്പുചെയ്യുക"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"ഒന്നുമില്ല"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"പ്രധാനപ്പെട്ടവ"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"എല്ലാം"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ചാർജ്ജുചെയ്യുന്നു (പൂർണ്ണമാകുന്നതിന്, <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"ഉപയോക്താവ് മാറുക"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"ഉപയോക്താവിനെ മാറ്റുക, <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> എന്നയാളാണ് നിലവിലുള്ള ഉപയോക്താവ്"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"നിരസിക്കുക"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗാണ്"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"ആദ്യത്തേത് പുനഃസ്ഥാപിക്കാൻ സ്‌പർശിക്കുക."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index f7268c2..200808c 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -42,7 +42,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Батерей хэмнэгчийг асаах"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Тохиргоо"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Нислэгийн горим"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Дэлгэцийг автоматаар эргүүлэх"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ХААХ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АВТОМАТ"</string>
@@ -86,6 +85,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"тайлах"</string>
     <string name="phone_label" msgid="2320074140205331708">"утас нээх"</string>
     <string name="camera_label" msgid="7261107956054836961">"камер нээх"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Шинэ ажиллах талбарыг сонгоно уу"</string>
+    <string name="cancel" msgid="6442560571259935130">"Цуцлах"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Тохиромжтой өсгөх товч."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Жижгээс том дэлгэцрүү өсгөх."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Блютүүт холбогдсон."</string>
@@ -176,6 +177,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Нислэгийн горимыг асаасан."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Бүү саад болно уу.Зөвхөн чухал зүйлст."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Бүү саад болно уу. Аливаа саад учруулахгүй байна уу."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Бүү саад бол."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Идэвхгүй болгох үйлдэлд бүү саад бол."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Идэвхжүүлэх үйлдэлд бүү саад бол."</string>
@@ -226,9 +229,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Амттаны хайрцаг"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Этернет"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Нислэгийн горим"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Бүү саад бол"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Зөвхөн чухал зүйлс"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Аливаа саад байхгүй байх"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Блютүүт"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Блютүүт (<xliff:g id="NUMBER">%d</xliff:g> төхөөрөмж)"</string>
@@ -299,6 +303,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Тасалдал байхгүй. Сэрүүлэг ч байхгүй."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Ямар ч тасалдалгүй"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Зөвхөн нэн тэргүүний тасалдалд"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Таны дараагийн сэрүүлгийн цаг <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Таны дараагийн сэрүүлгийн цаг <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Та <xliff:g id="ALARM_TIME">%s</xliff:g>-д өөрийн сэрүүлгээ сонсохгүй"</string>
@@ -308,9 +314,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Түгжээг тайлах бол шудрана уу"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Утас гаргахын тулд баруун шударна уу"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Камер гаргахын тулд зүүн шударна уу"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Хоосон"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Нэн тэргүүний"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Бүгд"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Хэрэглэгчийг сэлгэх"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Хэрэглэгчийг сэлгэх, одоогийн хэрэглэгч <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -378,4 +394,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Татгалзах"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь дууны диалог юм."</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Анхны хувилбарыг эргүүлэн хадгалахыг хүсвэл хүрнэ үү."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 6023d49..686b96a 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"बॅटरी बचतकर्ता चालू करा"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"सेटिंग्ज"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"वाय-फाय"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"विमान मोड"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"स्वयं-फिरणारी स्क्रीन"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"नि:शब्द करा"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"स्वयं"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"अनलॉक करा"</string>
     <string name="phone_label" msgid="2320074140205331708">"फोन उघडा"</string>
     <string name="camera_label" msgid="7261107956054836961">"कॅमेरा उघडा"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"नवीन कार्य लेआउट निवडा"</string>
+    <string name="cancel" msgid="6442560571259935130">"रद्द करा"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"सुसंगतता झूम बटण."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"लहानपासून मोठ्‍या स्‍क्रीनवर झूम करा."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब कनेक्‍ट केले."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"विमान मोड चालू केला."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"व्यत्यय आणू नका चालू, केवळ प्राधान्य."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"व्यत्यय आणू नका चालू, कोणताही व्यत्यय नाही."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"व्यत्यय आणू नका बंद."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"व्यत्यय आणू नका बंद करा"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"व्यत्यय आणू नका चालू करा"</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"मिष्ठान्न प्रकरण"</string>
     <string name="start_dreams" msgid="7219575858348719790">"डेड्रीम"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"इथरनेट"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"विमान मोड"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"व्यत्यय आणू नका"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"केवळ प्राधान्य"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"कोणतेही व्यत्यय नाही"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब्लूटुथ"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब (<xliff:g id="NUMBER">%d</xliff:g> डिव्हाइसेस)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"नेटवर्क नाही"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"वाय-फाय बंद"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"कोणतीही जतन केलेली नेटवर्क उपलब्ध नाहीत"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"कास्‍ट करा"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"कास्ट करत आहे"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"निनावी डिव्हाइस"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"कास्ट करण्यास सज्ज"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"कोणतेही व्यत्यय नाहीत. अगदी अलार्मचे देखील नाहीत."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"कोणतेही व्यत्यय नाही"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"केवळ प्राधान्य दिलेले व्‍यत्यय"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"आपला पुढील अलार्म <xliff:g id="ALARM_TIME">%s</xliff:g> वाजता आहे"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"आपला पुढील अलार्म <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> आहे"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"आपण आपला अलार्म <xliff:g id="ALARM_TIME">%s</xliff:g> वाजता ऐकणार नाही"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"अनलॉक करण्यासाठी स्वाइप करा"</string>
     <string name="phone_hint" msgid="3101468054914424646">"फोन साठी उजवीकडे स्वाइप करा"</string>
     <string name="camera_hint" msgid="5241441720959174226">"कॅमेर्‍यासाठी डावीकडे स्वाइप करा"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"काहीही नाही"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"प्राधान्य"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"सर्व"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> पूर्ण होईपर्यंत) चार्ज होत आहे"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"वापरकर्ता स्विच करा"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"वापरकर्ता स्विच करा, वर्तमान वापरकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"नकार द्या"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा व्हॉल्यूम संवाद आहे"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"मूळ पुनर्संचयित करण्यासाठी स्पर्श करा."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 8579e07..71f66d4 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Hidupkan penjimat bateri"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Tetapan"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mod pesawat"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Autoputar skrin"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"REDAM"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"buka kunci"</string>
     <string name="phone_label" msgid="2320074140205331708">"buka telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"buka kamera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Pilih reka letak tugas baharu"</string>
+    <string name="cancel" msgid="6442560571259935130">"Batal"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Butang zum keserasian."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Skrin zum lebih kecil kepada lebih besar."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth disambungkan."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Mod pesawat dihidupkan."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Jangan ganggu dihidupkan, perkara penting sahaja."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Jangan ganggu dihidupkan, tiada gangguan."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Jangan ganggu dimatikan."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Jangan ganggu dimatikan."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Jangan ganggu dihidupkan."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Bekas Pencuci Mulut"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Lamun"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mod kapal terbang"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Jangan ganggu"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Keutamaan sahaja"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Tiada gangguan"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Peranti)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tiada Rangkaian"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Dimatikan"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Tiada rangkaian disimpan tersedia"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Hantar"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Menghantar"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Peranti tidak bernama"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Bersedia untuk menghantar"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Tiada gangguan, walau penggera sekalipun."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Tiada gangguan"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Gangguan keutamaan sahaja"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Penggera anda yang seterusnya pada <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Penggera anda yang seterusnya pada <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Anda tdk akan mdgr penggera anda pd <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Leret ke atas untuk membuka kunci"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Leret ke kanan untuk telefon"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Leret ke kiri untuk kamera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Tiada"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Keutamaan"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Semua"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengecas (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> sehingga penuh)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Tukar pengguna"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Tukar pengguna, pengguna semasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tolak"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ialah dialog kelantangan"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan yang asal."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 58e5239..30ee13d 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"ဘက်ထရီ ချွေတာမှုကို ဖွင့်ရန်"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"အပြင်အဆင်များ"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"ဝိုင်ဖိုင်"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"လေယာဥ်ပျံပေါ်အသုံးပြုသောစနစ်"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"မျက်နှာပြင်အလိုအလျောက်လှည့်ရန်"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"သော့ဖွင့်ရန်"</string>
     <string name="phone_label" msgid="2320074140205331708">"ဖုန်းကို ဖွင့်ရန်"</string>
     <string name="camera_label" msgid="7261107956054836961">"ကင်မရာ ဖွင့်ရန်"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"အလုပ်သစ်စီစဥ်မှုကို ရွေးပါ။"</string>
+    <string name="cancel" msgid="6442560571259935130">"ထားတော့"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"အံ့ဝင်သောချုံ့ချဲ့ခလုတ်"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ဖန်သားပြင်ပေါ်တွင် အသေးမှအကြီးသို့ချဲ့ခြင်း"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ဘလူးတုသ်ချိတ်ဆက်ထားမှု"</string>
@@ -178,6 +179,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"လေယာဉ် မုဒ်ကို ဖွင့်ထားလိုက်ပြီ။"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"မနှောင့်ယှက်ပါနှင့် ဖွင့်ထားသည်၊ ဦးစားပေးများသာ။"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"မနှောင့်ယှက်ပါနှင့် ဖွင့်ထားသည်၊ အနှောင့်အယှက်များ မရှိပါ။"</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"အနှောင့်ယှက်ရ ဖွင့်ထားသည်။ နှိုးစက်များသာ။"</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"မနှောင့်ယှက်ပါနှင့် ကိုပိတ်ထားသည်။"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"မနှောင့်ယှက်ပါနှင့် ကိုပိတ်ထားသည်။"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"မနှောင့်ယှက်ပါနှင့်ကို ဖွင့်ထားသည်။"</string>
@@ -228,9 +230,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"မုန့်ထည့်သော ပုံး"</string>
     <string name="start_dreams" msgid="7219575858348719790">"ဒေးဒရင်းမ်"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"အီသာနက်"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"လေယာဥ်ပျံပေါ်အသုံးပြုသောစနစ်"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"မနှောက်ယှက်ပါနှင့်"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"ဦးစားပေးများသာ"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"နှိုးစက်များသာ"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"ကြားဖြတ်ဝင်မှု ခွင့်မပြုရန်"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ဘလူးတု"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ဘလူးတု (<xliff:g id="NUMBER">%d</xliff:g> စက်များ)"</string>
@@ -301,6 +303,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"ကြားဖြတ်ဝင်မှုများ မရှိခဲ့။ နှိုးစက်ပင် မရှိခဲ့။"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"ကြားဖြတ်ဝင်မှု ခွင့်မပြုရန်"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"ဦးစားပေး ကြားဖြတ်ဝင်မှုများ သာလျှင်"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"နှိုးစက်များသာ"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"သင်၏ နောက် နှိုးစက်၏ အချိန်မှာ<xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"သင်၏ နောက် နှိုးစက်မှာ <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"သင်သည် သင်၏ <xliff:g id="ALARM_TIME">%s</xliff:g> နှိုးစက်ကို ကြားရမည် မဟုတ်"</string>
@@ -310,9 +313,15 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"သော့ဖွင့်ရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
     <string name="phone_hint" msgid="3101468054914424646">"ဖုန်း အတွက် ညာသို့ ပွတ်ဆွဲပါ"</string>
     <string name="camera_hint" msgid="5241441720959174226">"ကင်မရာ အတွက် ဘယ်သို့ ပွတ်ဆွဲပါ"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"မရှိ"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"ဦးစားပေးမှု"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"နှိုးစက်များသာ"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"အားလုံး"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">\n"ကြားဝင်မှု မရှိပါ"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ဦးစားပေးမှု\nသာ"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"နှိုးစက်များ\nသာ"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> အပြည့် အထိ) အားသွင်းနေ"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"အသုံးပြုသူကို ပြောင်းလဲရန်"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"အသုံးပြုသူကို ပြောင်းရန်၊ လက်ရှိ အသုံးပြုသူ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -380,4 +389,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ငြင်းပယ်သည်"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အသံဒိုင်ယာလော့ခ်ဖြစ်သည်"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"မူရင်းအားပြန်လည်သိမ်းဆည်းရန် ထိပါ။"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 0a67650..f38c304 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Slå på batterisparing"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Innstillinger"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Trådløse nettverk"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flymodus"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Roter skjerm automatisk"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEMPET"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"lås opp"</string>
     <string name="phone_label" msgid="2320074140205331708">"åpne telefonen"</string>
     <string name="camera_label" msgid="7261107956054836961">"åpne kamera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Velg en ny utforming for oppgaver"</string>
+    <string name="cancel" msgid="6442560571259935130">"Avbryt"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoomknapp for kompatibilitet."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom fra mindre til større skjerm."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth er tilkoblet."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Flymodus er slått på."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"«Ikke forstyrr» er på – bare prioritert."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"«Ikke forstyrr» er på – ingen avbrytelser."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"«Ikke forstyrr» er av."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"«Ikke forstyrr» er slått av."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"«Ikke forstyrr» er slått på."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessertmonter"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Dagdrøm"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flymodus"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"«Ikke forstyrr»"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Bare prioritet"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Ingen forstyrrelser"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheter)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ingen nettverk"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi er av"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Ingen lagrede nettverk er tilgjengelige"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Cast"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Casting"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Enhet uten navn"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Klar til å caste"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Ingen forstyrrelser, ikke engang alarmer."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Ingen forstyrrelser"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Bare prioriterte forstyrrelser"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Den neste alarmen din er stilt inn kl. <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Den neste alarmen din er stilt inn <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Du kommer ikke til å høre alarmen kl. <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Sveip oppover for å låse opp"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Sveip mot høyre for å åpne telefonen"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Sveip mot venstre for å åpne kameraet"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Ingen"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritet"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Lader (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Bytt bruker"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Bytt bruker, gjeldende bruker er <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ikke tillat"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er volumdialogen"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Trykk for å gå tilbake til den opprinnelige volumdialogen."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 3d5d213..301c4ef 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"ब्याट्री बचत खोल्नुहोस्"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"सेटिङहरू"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"वाइफाइ"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"हवाइजहाज मोड"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"स्वत:घुम्ने स्क्रिन"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"म्युट गर्नुहोस्"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"स्वतः"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"खोल्नुहोस्"</string>
     <string name="phone_label" msgid="2320074140205331708">"फोन खोल्नुहोस्"</string>
     <string name="camera_label" msgid="7261107956054836961">"क्यामेरा खोल्नुहोस्"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"नयाँ कार्य लेआउट चयन गर्नुहोस्"</string>
+    <string name="cancel" msgid="6442560571259935130">"रद्द गर्नुहोस्"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"मिलाउने जुम बटन।"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"स्क्रिनलाई सानोबाट ठूलो पार्नुहोस्।"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लुटुथ जडान भयो।"</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"हवाइजहाज मोड खोलियो।"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"प्राथमिकतालाई मात्र बाधा नपुर्‍याउनुहोस्।"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"बाधा नपुर्याउँनुहोस्, कुनै पनि अवरोध छैनन्।"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"निष्क्रियलाई बाधा नपुर्‍याउनुहोस्"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"निष्क्रिय गरिएकालाई अवरोध नपुर्‍याउनुहोस्।"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"सक्रिय रहेकोलाई अवरोध नपुर्‍याउनुहोस्।"</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"दिवासपना"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"हवाइजहाज मोड"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"बाधा नपुर्याउँनुहोस्"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"प्राथमिकता मात्र"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"कुनै अवरोधहरू छैन"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब्लुटुथ"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लुटुथ (<xliff:g id="NUMBER">%d</xliff:g> उपकरणहरू)"</string>
@@ -301,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"कुनै रुकावट छैन। चेतावनी समेत छैन।"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"कुनै रुकावटहरू छैन"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"प्राथमिकता रुकावटहरूमा मात्र"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"तपाईंको अर्को सचेतक <xliff:g id="ALARM_TIME">%s</xliff:g> मा छ"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"तपाईंको अर्को सचेतक <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> हो"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> मा तपाईंले आफ्नो सचेतक सुन्नुहुने छैन"</string>
@@ -310,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"अनलक गर्न स्वाप गर्नुहोस्"</string>
     <string name="phone_hint" msgid="3101468054914424646">"फोनका लागि दाँया स्वाइप"</string>
     <string name="camera_hint" msgid="5241441720959174226">"क्यामेराका लागि बाँया स्वाइप"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"कुनै पनि होइन"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"प्राथमिकता"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"सबै"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"चार्ज हुँदै (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> पूर्ण भएसम्म)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"प्रयोगकर्ता फेर्नुहोस्"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"प्रयोगकर्ता, हालको प्रयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g> मा स्विच गर्नुहोस्"</string>
@@ -380,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"अस्वीकार गर्नुहोस्"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> भोल्यूम संवाद हो"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"मूल पुनर्स्थापना गर्न छुनुहोस्।"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 16d4eea..5d97ad9 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Accubesparing inschakelen"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Instellingen"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wifi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Vliegtuigmodus"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Scherm automatisch draaien"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEMPEN"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ontgrendelen"</string>
     <string name="phone_label" msgid="2320074140205331708">"telefoon openen"</string>
     <string name="camera_label" msgid="7261107956054836961">"camera openen"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Nieuwe taakindeling selecteren"</string>
+    <string name="cancel" msgid="6442560571259935130">"Annuleren"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knop voor compatibiliteitszoom."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kleiner scherm uitzoomen naar groter scherm."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-verbinding ingesteld."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Vliegtuigmodus ingeschakeld."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Niet storen aan, alleen prioriteit."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Niet storen aan, geen onderbrekingen."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Niet storen uit."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Niet storen uitgeschakeld."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Niet storen ingeschakeld."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessertshowcase"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Dagdroom"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Vliegtuigmodus"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Niet storen"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Alleen prioriteit"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Geen onderbrekingen"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> apparaten)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Geen netwerk"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wifi uit"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Geen opgeslagen netwerken beschikbaar"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Casten"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Casten"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Naamloos apparaat"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Klaar om te casten"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Geen onderbrekingen. Zelfs geen alarm."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Geen onderbrekingen"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Alleen prioriteitsonderbrekingen"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Uw volgende alarm is om <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Uw volgende alarm is <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"U hoort uw alarm niet om <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Veeg omhoog om te ontgrendelen"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Veeg naar rechts voor telefoon"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Veeg naar links voor camera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Geen"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioriteit"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Gebruiker wijzigen"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Schakelen tussen gebruikers, huidige gebruiker <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Afwijzen"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is het volumedialoogvenster"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Tik hierop om het origineel te herstellen."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3b9efe7..d35b7e0 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -46,7 +46,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Włącz oszczędzanie baterii"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ustawienia"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Tryb samolotowy"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Autoobracanie ekranu"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"WYGAŚ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
@@ -90,6 +89,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"odblokuj"</string>
     <string name="phone_label" msgid="2320074140205331708">"otwórz telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"otwórz aparat"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Wybierz nowy układ zadań"</string>
+    <string name="cancel" msgid="6442560571259935130">"Anuluj"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Przycisk powiększenia na potrzeby zgodności."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Powiększa mniejszy ekran do większego."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth połączony."</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Tryb samolotowy został włączony."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Nie przeszkadzać (włączone, tylko priorytetowe)."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Nie przeszkadzać (włączone, bez przeszkadzania)."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Nie przeszkadzać (wyłączone)."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Nieprzeszkadzanie wyłączone."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Nieprzeszkadzanie włączone."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Półka ze słodkościami"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Wygaszacz ekranu"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Tryb samolotowy"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Nie przeszkadzać"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Tylko priorytetowe"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Bez przeszkadzania"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (urządzenia: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Brak sieci"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi wyłączone"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Brak dostępnych zapisanych sieci"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Przesyłanie"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Przesyłam"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Urządzenie bez nazwy"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Wszystko gotowe do przesyłania"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Żadnych powiadomień. Nawet alarmów."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Bez przerw"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Tylko dźwięki priorytetowe"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Następny alarm o <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Następny alarm: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Nie usłyszysz alarmu o <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Przesuń w górę, by odblokować"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Przesuń w prawo, by przełączyć się na telefon"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Przesuń w lewo, by włączyć aparat"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Żadne"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Priorytetowe"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Wszystkie"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ładuje się (pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Przełącz użytkownika"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Przełącz użytkownika. Bieżący użytkownik: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmów"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> steruje głośnością"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Dotknij, by przywrócić pierwotną."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 03ca5ee..fc99d94 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Ativar a poupança de bateria"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Definições"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo de avião"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Rodar ecrã automaticamente"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"D. SOM"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
     <string name="phone_label" msgid="2320074140205331708">"abrir telemóvel"</string>
     <string name="camera_label" msgid="7261107956054836961">"abrir câmara"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Selecionar novo esquema de tarefa"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão zoom de compatibilidade."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom menor para ecrã maior."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ligado."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Modo de avião ligado."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Não incomodar ligado, apenas prioridade."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Não incomodar ligado, sem interrupções."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Não incomodar desligado."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Não incomodar desligado."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Não incomodar ligado."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Vitrina de sobremesas"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo de avião"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Não incomodar"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Apenas prioridade"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Sem interrupções"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Dispositivos)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sem Rede"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Desligado"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Sem redes guardadas disponíveis"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Transmitir"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Transmissão"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Dispositivo sem nome"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Pronto para transmitir"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Sem interrupções. Nem mesmo alarmes."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Sem interrupções"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Apenas interrupções com prioridade"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"O próximo alarme é à(s) <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"O próximo alarme é <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Não vai ouvir o alarme à(s) <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Deslizar rapidamente com o dedo para cima para desbloquear"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Deslize rapidamente para a direita para aceder ao telemóvel"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Deslize rapidamente para a esquerda para aceder à câmara"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Nenhum"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioridade"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Tudo"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"A carregar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até à carga máxima)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Mudar utilizador"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Mudar de utilizador; o utilizador atual é <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Recusar"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo do volume"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 5a68f7d..2909735 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Ativar a economia de bateria"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configurações"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo avião"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Girar automaticamente a tela"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUDO"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
     <string name="phone_label" msgid="2320074140205331708">"abrir telefone"</string>
     <string name="camera_label" msgid="7261107956054836961">"abrir câmera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Selecionar novo layout da tarefa"</string>
+    <string name="cancel" msgid="6442560571259935130">"Cancelar"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão de zoom da compatibilidade."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aumentar a tela com zoom."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado."</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"O modo avião foi ativado."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\"Não perturbe\" ativado, somente prioridade."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\"Não perturbe\" ativado, sem interrupções."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Não perturbe\" desativado."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Não perturbe\" desativado."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Não perturbe\" ativado."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Mostruário de sobremesas"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avião"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Não perturbe"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Só prioridade"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Sem interrupções"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sem rede"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desligado"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Não há redes salvas disponíveis"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Transmitir"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Transmitindo"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Dispositivo sem nome"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Pronto para transmitir"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Sem interrupções. Nem mesmo alarmes."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Sem interrupções"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Apenas interrupções prioritárias"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Seu próximo alarme será às <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Seu próximo alarme será em <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Você não ouvirá o alarme às <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Deslize para cima para desbloquear"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Deslize à direita p/ usar o telefone"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Deslize à esquerda p/ usar a câmera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Nenhum"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioridade"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Tudo"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até concluir)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Trocar usuário"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Alternar usuário. Usuário atual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Negar"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo referente ao volume"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 5887c79..1330327 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -45,7 +45,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Activați economisirea bateriei"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Setări"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mod Avion"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Rotire automată a ecranului"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEZAC."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
@@ -89,6 +88,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"deblocați"</string>
     <string name="phone_label" msgid="2320074140205331708">"deschideți telefonul"</string>
     <string name="camera_label" msgid="7261107956054836961">"deschideți camera foto"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Selectați noul aspect pentru activitate"</string>
+    <string name="cancel" msgid="6442560571259935130">"Anulați"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Buton zoom pentru compatibilitate."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Faceţi zoom de la o imagine mai mică la una mai mare."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Conectat prin Bluetooth."</string>
@@ -179,6 +180,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Modul Avion este activat."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Setarea „Nu deranja” este activată – numai prioritare."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Setarea „Nu deranja” este activată – fără întreruperi."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Setarea „Nu deranja” este dezactivată."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Setarea „Nu deranja” a fost dezactivată."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Setarea „Nu deranja” a fost activată."</string>
@@ -229,9 +232,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Vitrina cu dulciuri"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mod Avion"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Nu deranja"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Numai cu prioritate"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Fără întreruperi"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispozitive)"</string>
@@ -258,8 +262,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nicio reţea"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi deconectat"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Nicio rețea salvată disponibilă"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Proiectați"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Se proiectează"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Dispozitiv nedenumit"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Pregătit pentru proiecție"</string>
@@ -303,6 +306,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Fără întreruperi. Nici măcar alarme."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Fără întreruperi"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Numai întreruperi cu prioritate"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Următoarea alarmă este setată la <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Următoarea alarmă este la <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Nu veți auzi alarma la <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -312,9 +317,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Glisați în sus pentru a debloca"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Glisați la dreapta pentru a acesa telefonul"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Glisați la stânga pentru a accesa camera foto"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Niciuna"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritate"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Toate"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Se încarcă (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Comutați între utilizatori"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Schimbați utilizatorul (utilizator actual <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
@@ -382,4 +397,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuzați"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> afișează caseta de dialog pentru volum"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Atingeți pentru a reveni la setarea inițială."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 23e8b3a..4e5f5c2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -46,7 +46,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Включить режим энергосбережения"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Настройки"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим полета"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Автоповорот экрана"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ВЫКЛ."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АВТО"</string>
@@ -90,6 +89,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"Разблокировать."</string>
     <string name="phone_label" msgid="2320074140205331708">"Открыть телефон."</string>
     <string name="camera_label" msgid="7261107956054836961">"Открыть камеру."</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Выберите другой макет"</string>
+    <string name="cancel" msgid="6442560571259935130">"Отмена"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка масштабирования (режим совместимости)"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Уменьшение изображения для увеличения свободного места на экране."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-соединение установлено."</string>
@@ -182,6 +183,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Режим полета включен."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Режим \"Не беспокоить\" включен. Будут показаны только важные оповещения."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Включен режим \"Не беспокоить\". Все оповещения отключены."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Режим \"Не беспокоить\" выключен."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Режим \"Не беспокоить\" выключен."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Режим \"Не беспокоить\" включен."</string>
@@ -232,9 +235,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Коробка со сладостями"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Заставка"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим полета"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Не беспокоить"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Только важные"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Без оповещений"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -261,8 +265,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нет сети"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi выкл."</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Нет доступных сохраненных сетей"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Wi-Fi-монитор"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Передача изображения"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Безымянное устройство"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Готово к передаче"</string>
@@ -306,6 +309,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Никаких оповещений, даже от будильника."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Не беспокоить"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Только важные оповещения"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Следующий будильник: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Следующий будильник: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Следующий будильник: <xliff:g id="ALARM_TIME">%s</xliff:g>. Звук отключен."</string>
@@ -315,9 +320,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Проведите вверх, чтобы разблокировать"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Чтобы позвонить, пролистните вправо"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Чтобы включить камеру, пролистните влево"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Не беспокоить"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Важные"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Все"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Зарядка батареи (осталось <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Сменить пользователя."</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Сменить аккаунт. Вход выполнен под именем <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>."</string>
@@ -385,4 +400,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Нет"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> назначено регулятором громкости"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Нажмите, чтобы восстановить приложение по умолчанию."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index ef864de..2631c56 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"බැටරි සුරැකීම සක්‍රිය කරන්න"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"සැකසීම්"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"අහස්යානා ආකාරය"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"ස්වයංක්‍රීයව-භ්‍රමණය වන තිරය"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"නිශ්ශබ්ද කරන්න"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ස්වයංක්‍රීය"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"අඟුල අරින්න"</string>
     <string name="phone_label" msgid="2320074140205331708">"දුරකථනය විවෘත කරන්න"</string>
     <string name="camera_label" msgid="7261107956054836961">"කැමරාව විවෘත කරන්න"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"නව කාර්යය සැකැස්ම තෝරන්න"</string>
+    <string name="cancel" msgid="6442560571259935130">"අවලංගු කරන්න"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ගැළපෙන විශාලන බොත්තම."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"විශාල තිරය වෙත කුඩාව විශාලනය කරන්න."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"බ්ලූටූත් සම්බන්ධිතයි."</string>
@@ -178,6 +179,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"අහස්යානා ආකාරය සක්‍රීයයි."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"බාධා නොකරන්න ක්‍රියාත්මකයි, ප්‍රමුඛතා පමණි."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"බාධා නොකරන්න ක්‍රියාත්මකයි, බාධා කිරීම් නැත."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"බාධා නොකරන්න ක්‍රියාත්මකයි, ප්‍රමුඛතා පමණි."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"බාධා නොකරන්න ක්‍රියා විරහිතයි."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"බාධා නොකරන්න ක්‍රියා විරහිත කරන ලදි."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"බාධා නොකරන්න ක්‍රියාත්මක කරන ලදි"</string>
@@ -228,9 +230,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"අතුරුපස අවස්තාව"</string>
     <string name="start_dreams" msgid="7219575858348719790">"දවල් හීනය"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ඊතර නෙට්"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"අහස්යානා ආකාරය"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"බාධා නොකරන්න"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"ප්‍රමුඛතාව පමණයි"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"ඇඟවීම් පමණි"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"බාධා කිරීම් නැත"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"බ්ලූටූත්"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"බ්ලූටූත් (උපාංග <xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -301,6 +303,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"අතුරු බිඳීම් නැත. අඩුම තරමේ අනතුරු ඇඟවීමක්වත් නැත."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"අතුරු බිදුම් නැත"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"ප්‍රමුඛ අතුරු බිඳීම් පමණයි"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"ඇඟවීම් පමණි"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"ඔබගේ ඊළඟ සීනුව <xliff:g id="ALARM_TIME">%s</xliff:g> තිබේ"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"ඔබගේ ඊළඟ සීනුව <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> වේ"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> හි තිබෙන ඔබගේ සීනුව ඔබට ඇසෙන්නේ නැත"</string>
@@ -310,9 +313,15 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"අගුළු ඇරීමට ස්වයිප් කරන්න."</string>
     <string name="phone_hint" msgid="3101468054914424646">"දුරකථන සඳහා දකුණට ස්වයිප් කරන්න"</string>
     <string name="camera_hint" msgid="5241441720959174226">"කැමරාව සඳහා දකුණට ස්වයිප් කරන්න"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"කිසිවක් නැත"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"ප්‍රමුඛතාව"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"ඇඟවීම් පමණි"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"සියලු"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"බාධා\nනොකරන්න"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"ප්‍රමුඛතා\nපමණි"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"ඇඟවීම්\nපමණි"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ආරෝපණය වෙමින් (සම්පුර්ණ වන තෙක් <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"පරිශීලක මාරුව"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"පරිශීලකයා මාරු කරන්න,දැන් සිටින පරිශීලකයා <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -380,4 +389,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ප්‍රතික්ෂේප කරන්න"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ධාරිතා සංවාදයයි"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"මුල් තත්ත්වය නැවත ප්‍රතිසාධනය කිරීමට ස්පර්ශ කරන්න."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 4fc086d..f05b8c1 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -46,7 +46,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Zapnúť šetrič batérie"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavenia"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Režim v lietadle"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Automatické otočenie obrazovky"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"STLMIŤ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -90,6 +89,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"odomknúť"</string>
     <string name="phone_label" msgid="2320074140205331708">"otvoriť telefón"</string>
     <string name="camera_label" msgid="7261107956054836961">"spustiť fotoaparát"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Vyberte nové rozloženie úlohy"</string>
+    <string name="cancel" msgid="6442560571259935130">"Zrušiť"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačidlo úpravy veľkosti z dôvodu kompatibility."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zväčšiť menší obrázok na väčšiu obrazovku."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth pripojené."</string>
@@ -182,6 +183,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Režim v lietadle je zapnutý."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Stav Nerušiť je zapnutý, iba prioritné."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Stav Nerušiť je zapnutý, žiadne prerušenia."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Stav Nerušiť je zapnutý, iba budíky."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Stav Nerušiť je vypnutý."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Stav Nerušiť je vypnutý."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Stav Nerušiť je zapnutý."</string>
@@ -232,9 +234,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"Pult s dezertami"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Šetrič obrazovky"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Režim v lietadle"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Nerušiť"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Iba prioritné"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Iba budíky"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Žiadne prerušenia"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Rozhranie Bluetooth (počet zariadení: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -261,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Žiadna sieť"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Sieť Wi-Fi je vypnutá"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Nie sú k dispozícii žiadne uložené siete"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Prenášanie"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Prenáša sa"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Nepomenované zariadenie"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Pripravené na prenášanie"</string>
@@ -306,6 +307,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Žiadne vyrušenia, ani budíky"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Žiadne vyrušenia"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Iba prioritné vyrušenia"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"Iba budíky"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Ďalší budík: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Ďalší budík: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Váš budík o <xliff:g id="ALARM_TIME">%s</xliff:g> sa nespustí"</string>
@@ -315,9 +317,13 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Zariadenie odomknete prejdením prstom nahor"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Telefón otvoríte prejdením prstom doľava"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Fotoaparát otvoríte prejdením prstom doľava"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Žiadne"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritné"</string>
+    <string name="interruption_level_none" msgid="8284541443482072628">"Žiadne prerušenia"</string>
+    <string name="interruption_level_priority" msgid="6426766465363855505">"Iba prioritné"</string>
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"Iba budíky"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"Všetky"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"Žiadne\nprerušenia"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Iba\nprioritné"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Iba\nbudíky"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nabíja sa (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Prepnutie používateľa"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Prepnúť používateľa (súčasný používateľ: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
@@ -385,4 +391,5 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmietnuť"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialóg hlasitosti"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string>
+    <string name="volume_zen_switch_text" msgid="6388350641576595452">"Blokovanie prerušení"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index f20596b..f34b66f 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -46,7 +46,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Vklop varčevanja z energijo"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavitve"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Način za letalo"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Samodejno zasukaj zaslon"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"TIHO"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"SAMOD."</string>
@@ -90,6 +89,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"odkleni"</string>
     <string name="phone_label" msgid="2320074140205331708">"odpri telefon"</string>
     <string name="camera_label" msgid="7261107956054836961">"odpri fotoaparat"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Izberite novo postavitev opravil"</string>
+    <string name="cancel" msgid="6442560571259935130">"Prekliči"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb povečave za združljivost."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Povečava manjšega na večji zaslon."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Povezava Bluetooth vzpostavljena."</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Način za letalo je vklopljen."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Način »ne moti« je vklopljen, samo prednostno."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Način »ne moti« je vklopljen, ni prekinitev."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Način »ne moti« je izklopljen."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Način »ne moti« je izklopljen."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Način »ne moti« je vklopljen."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Vitrina za sladice"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Sanjarjenje"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Način za letalo"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Ne moti"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Samo prednostno"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Brez prekinitev"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (št. naprav: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ni omrežja"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi izklopljen"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Na voljo ni nobeno shranjeno omrežje"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Predvajanje"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Predvajanje"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Neimenovana naprava"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Pripravljeno za predvajanje"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Brez motenj. Celo brez alarmov."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Brez prekinitev"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Samo prednostne prekinitve"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Vaš naslednji alarm je ob <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Vaš naslednji alarm: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Alarma ob <xliff:g id="ALARM_TIME">%s</xliff:g> ne boste slišali"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Povlecite, da odklenete"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Povlecite v desno za telefon"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Povlecite v levo za fotoaparat"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Nič"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prednost"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Vse"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napolnjenosti)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Preklop med uporabniki"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Preklop med uporabniki, trenutni uporabnik <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Zavrni"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je pogovorno okno glede prostornine"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Dotaknite se, če želite obnoviti izvirnik."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 74b44f4..1c97e7e 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -45,7 +45,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Укључи штедњу батерије"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Подешавања"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим рада у авиону"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Аутоматско ротирање екрана"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"УГАСИ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АУТОM."</string>
@@ -89,6 +88,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"откључај"</string>
     <string name="phone_label" msgid="2320074140205331708">"отвори телефон"</string>
     <string name="camera_label" msgid="7261107956054836961">"отвори камеру"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Изабери нови распоред задатака"</string>
+    <string name="cancel" msgid="6442560571259935130">"Откажи"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Дугме Зум компатибилности."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Зумирање са мањег на већи екран."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth је прикључен."</string>
@@ -179,6 +180,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Режим рада у авиону је укључен."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Подешавање Не узнемиравај је укључено, само приоритетни прекиди."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Подешавање Не узнемиравај је укључено, без прекида."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Подешавање Не узнемиравај је искључено."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Подешавање Не узнемиравај је искључено."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Подешавање Не узнемиравај је укључено."</string>
@@ -229,9 +232,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Витрина са посластицама"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Сањарење"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Етернет"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим рада у авиону"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Не узнемиравај"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Само приоритетни прекиди"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Без прекида"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> уређаја)"</string>
@@ -258,8 +262,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нема мреже"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi је искључен"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Није доступна ниједна сачувана мрежа"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Пребацивање"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Пребацивање"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Неименовани уређај"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Спремно за пребацивање"</string>
@@ -303,6 +306,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Нема прекида. Чак ни аларма."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Без прекида"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Само приоритетни прекиди"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Следећи аларм је у <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Следећи аларм: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Нећете чути аларм у <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -312,9 +317,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Превуците нагоре да бисте откључали"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Превуците удесно за телефон"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Превуците улево за камеру"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Ниједан"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Приоритет"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Све"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Пуњење (пун је за <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Замени корисника"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Промените корисника, актуелни корисник је <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -382,4 +397,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Одбиј"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> је дијалог за јачину звука"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Додирните да бисте вратили оригинал."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index de4b84c..9308d8a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Aktivera batterisparläge"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Inställningar"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flygplansläge"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Rotera skärmen automatiskt"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"TYST"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"lås upp"</string>
     <string name="phone_label" msgid="2320074140205331708">"öppna mobilen"</string>
     <string name="camera_label" msgid="7261107956054836961">"öppna kameran"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Välj en ny layout för uppgiften"</string>
+    <string name="cancel" msgid="6442560571259935130">"Avbryt"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knapp för kompatibilitetszoom."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zooma mindre skärm till större."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ansluten."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Flygplansläget har aktiverats."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Stör ej har aktiverats. Endast prioriterade."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Stör ej har aktiverats. Inga avbrott."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Stör ej av."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Stör ej har inaktiverats."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Stör ej har aktiverats."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessertdisken"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Dagdröm"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Flygplansläge"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Stör ej"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Endast prioriterade"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Inga avbrott"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheter)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Inget nätverk"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi av"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Inga sparade nätverk tillgängliga"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Casta"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Castar"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Namnlös enhet"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Redo att casta"</string>
@@ -301,7 +304,9 @@
     <string name="description_direction_left" msgid="7207478719805562165">"Dra åt vänster för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Inga avbrott. Inte ens alarm."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Inga avbrott"</string>
-    <string name="zen_important_interruptions" msgid="3477041776609757628">"Endast prioriterade samtal och aviseringar"</string>
+    <string name="zen_important_interruptions" msgid="3477041776609757628">"Bara prioriterade samtal och aviseringar"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Nästa alarm är kl. <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Nästa alarm är <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Alarmet kommer inte att höras kl. <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Dra uppåt om du vill låsa upp"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Dra åt höger om du vill visa telefonen"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Dra åt vänster om du vill visa kameran"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Ingen"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritet"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Alla"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laddar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tills batteriet är fulladdat)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Byt användare"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Byt användare. Aktuell användare: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Neka"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> används som volymkontroll"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Tryck här om du vill återställa den ursprungliga appen."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index c6c4ff0..b8dff6c 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Washa kiokoa betri"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Mipangilio"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Mtandao-Hewa"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Hali ya Ndege"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Skrini ijizungushe kiotomatiki"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"PUUZA"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"KIOTOMATIKI"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"fungua"</string>
     <string name="phone_label" msgid="2320074140205331708">"fungua simu"</string>
     <string name="camera_label" msgid="7261107956054836961">"fungua kamera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Chagua muundo mpya wa kazi"</string>
+    <string name="cancel" msgid="6442560571259935130">"Ghairi"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kichupo cha kukuza kwa utangamanifu"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kuza kidogo kwa skrini kubwa."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth imeunganishwa."</string>
@@ -178,6 +179,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Hali ya ndegeni imewashwa."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Kipengee cha usinisumbue kimewashwa, kipaumbele pekee."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Kipengee cha usinisumbue kimewashwa, hakuna kukatizwa."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Kipengee cha usinisumbue kimewashwa, kengele pekee."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Kipengee cha usinisumbue kimezimwa."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Kipengee cha usinisumbue kimezimwa."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Kipengee cha usinisumbue kimewashwa."</string>
@@ -228,9 +230,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"Sanduku la Vitindamlo"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Hali Tulivu"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Hali ya ndege"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Usinisumbue"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Kipaumbele tu"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Kengele pekee"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Hakuna kukatizwa"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (Vifaa <xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -257,8 +259,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Hakuna Mtandao"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Imezimwa"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Hakuna mitandao iliyohifadhiwa inayopatikana"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Tuma"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Inatuma"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Kifaa hakina jina"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Tayari kutuma"</string>
@@ -302,6 +303,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Hakuna kukatizwa. Hata kama ni kengele."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Hakuna kukatizwa"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Mambo yenye kipaumbele pekee yakatize"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"Kengele pekee"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Kengele yako inayofuata itakuwa saa <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Kengele yako inayofuata itakuwa <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Hutasikia kengele yako ifikapo <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +313,15 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Telezesha kidole ili ufungue"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Telezesha kidole kulia ili ufikie simu"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Telezesha kidole kushoto ili ufikie kamera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Hamna"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Kipaumbele"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"Kengele pekee"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"Zote"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"Hakuna\nukatizaji"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Kipaumbele\npekee"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Kengele\npekee"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Inachaji (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ijae)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Badili mtumiaji"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Badili mtumiaji, mtumiaji wa sasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +389,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Kataa"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ni mazungumzo ya sauti"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Gusa ili urejeshe ya awali."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/styles.xml b/packages/SystemUI/res/values-sw600dp/styles.xml
index 156fa65..4d7d6b5 100644
--- a/packages/SystemUI/res/values-sw600dp/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp/styles.xml
@@ -19,12 +19,6 @@
         <item name="android:layout_width">480dp</item>
     </style>
 
-    <style name="SearchPanelScrim">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">@dimen/search_panel_scrim_height</item>
-        <item name="android:layout_gravity">bottom</item>
-    </style>
-
     <style name="UserDetailView">
         <item name="numColumns">4</item>
     </style>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index c9da1b8..5535708 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"பேட்டரி சேமிப்பானை இயக்கு"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"அமைப்பு"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"வைஃபை"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"விமானப் பயன்முறை"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"திரையைத் தானாகச் சுழற்று"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"முடக்கு"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"தானியங்கு"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"திற"</string>
     <string name="phone_label" msgid="2320074140205331708">"ஃபோனைத் திற"</string>
     <string name="camera_label" msgid="7261107956054836961">"கேமராவைத் திற"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"புதிய பணி தளவமைப்பைத் தேர்ந்தெடுக்கவும்"</string>
+    <string name="cancel" msgid="6442560571259935130">"ரத்துசெய்"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"பொருந்துமாறு அளவை மாற்றும் பொத்தான்."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"சிறியதிலிருந்து பெரிய திரைக்கு அளவை மாற்றும்."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"புளூடூத் இணைக்கப்பட்டது."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"விமானப் பயன்முறை இயக்கப்பட்டது."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"தொந்தரவு செய்ய வேண்டாம் என்பது இயக்கப்பட்டது, முதன்மை மட்டும்."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"தொந்தரவு செய்ய வேண்டாம் என்பது இயக்கப்பட்டது, குறுக்கீடுகள் இல்லை."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"தொந்தரவு செய்ய வேண்டாம் என்பது முடக்கப்பட்டது."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"தொந்தரவு செய்ய வேண்டாம் என்பது முடக்கப்பட்டது."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"தொந்தரவு செய்ய வேண்டாம் என்பது இயக்கப்பட்டது."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"இனிப்பு வடிவங்கள்"</string>
     <string name="start_dreams" msgid="7219575858348719790">"பகல்கனா"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ஈதர்நெட்"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"விமானப் பயன்முறை"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"தொந்தரவு செய்ய வேண்டாம்"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"முதன்மை மட்டும்"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"குறுக்கீடுகள் வேண்டாம்"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"புளூடூத்"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"புளூடூத் (<xliff:g id="NUMBER">%d</xliff:g> சாதனங்கள்)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"நெட்வொர்க் இல்லை"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"வைஃபையை முடக்கு"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"சேமித்த நெட்வொர்க்குகள் இல்லை"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"அனுப்பு"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"அனுப்புகிறது"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"பெயரிடப்படாத சாதனம்"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"அனுப்பத் தயார்"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"அறிவிப்பும் இல்லை. அலாரங்களும் இல்லை."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"தெரிவிக்காதே"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"முக்கிய அறிவிப்புகள் மட்டும்"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"அடுத்த அலாரம் - <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"அடுத்த அலாரம் - <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> க்கு அலாரத்தைக் கேட்க மாட்டீர்கள்"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"திறக்க, மேலே ஸ்வைப் செய்யவும்"</string>
     <string name="phone_hint" msgid="3101468054914424646">"ஃபோனுக்கு, வலப்புறம் ஸ்வைப் செய்க"</string>
     <string name="camera_hint" msgid="5241441720959174226">"கேமராவிற்கு இடப்புறம் ஸ்வைப் செய்க"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"ஏதுமில்லை"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"முன்னுரிமை"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"எல்லாம்"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"சார்ஜாகிறது (முழு சார்ஜிற்கு <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ஆகும்)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"பயனரை மாற்று"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"பயனரை மாற்று, தற்போதைய பயனர் <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"நிராகரி"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"ஒலியளவு செய்தி: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"அசலை மீட்டமைக்கத் தொடவும்."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 62c377e..21d2abe 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"బ్యాటరీ సేవర్‌ను ఆన్ చేయి"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"సెట్టింగ్‌లు"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"ఎయిర్‌ప్లేన్ మోడ్"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"స్క్రీన్‌ను స్వయంచాలకంగా తిప్పండి"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"మ్యూట్"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"స్వయంచాలకం"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"అన్‌లాక్ చేయి"</string>
     <string name="phone_label" msgid="2320074140205331708">"ఫోన్‌ను తెరువు"</string>
     <string name="camera_label" msgid="7261107956054836961">"కెమెరాను తెరువు"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"కొత్త విధి లేఅవుట్‌ను ఎంచుకోండి"</string>
+    <string name="cancel" msgid="6442560571259935130">"రద్దు చేయండి"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"అనుకూలత జూమ్ బటన్."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"చిన్న స్క్రీన్ నుండి పెద్దదానికి జూమ్ చేయండి."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"బ్లూటూత్ కనెక్ట్ చేయబడింది."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"ఎయిర్‌ప్లైన్ మోడ్ ఆన్ చేయబడింది."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"అంతరాయం కలిగించవద్దు ఆన్‌లో ఉంది, ప్రాధాన్యత మాత్రమే."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"అంతరాయం కలిగించవద్దు ఆన్‌లో ఉంది, అంతరాయాలు ఉండవు."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"అంతరాయం కలిగించవద్దు ఆఫ్‌లో ఉంది."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"అంతరాయం కలిగించవద్దు ఆఫ్ చేయబడింది."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"డెజర్ట్ కేస్"</string>
     <string name="start_dreams" msgid="7219575858348719790">"డేడ్రీమ్"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ఈథర్‌నెట్"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ఎయిర్‌ప్లేన్ మోడ్"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"అంతరాయం కలిగించవద్దు"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"ప్రాధాన్యత మాత్రమే"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"అంతరాయాలు ఉండవు"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"బ్లూటూత్"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"బ్లూటూత్ (<xliff:g id="NUMBER">%d</xliff:g> పరికరాలు)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"నెట్‌వర్క్ లేదు"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ఆఫ్‌లో ఉంది"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"సేవ్ చేసిన నెట్‌వర్క్‌లు ఏవీ అందుబాటులో లేవు"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"ప్రసారం చేయండి"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"ప్రసారం చేస్తోంది"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"పేరులేని పరికరం"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"ప్రసారం చేయడానికి సిద్ధంగా ఉంది"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"అంతరాయాలు లేవు. అలారాలు కూడా లేవు."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"అంతరాయాలు లేకుండా"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"ప్రాధాన్య అంతరాయాలు మాత్రమే"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"మీ తదుపరి అలారం <xliff:g id="ALARM_TIME">%s</xliff:g>కి ఉంది"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"మీ తదుపరి అలారం <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"మీరు <xliff:g id="ALARM_TIME">%s</xliff:g>కి సెట్ చేసిన అలారం మీకు వినిపించదు"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"అన్‌లాక్ చేయడానికి ఎగువకు స్వైప్ చేయండి"</string>
     <string name="phone_hint" msgid="3101468054914424646">"ఫోన్ కోసం కుడివైపుకి స్వైప్ చేయండి"</string>
     <string name="camera_hint" msgid="5241441720959174226">"కెమెరా కోసం ఎడమవైపుకి స్వైప్ చేయండి"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"వేటికీ వద్దు"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"ప్రాధాన్యత"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"అన్నిటికీ"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ఛార్జ్ అవుతోంది (పూర్తిగా నిండటానికి <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"వినియోగదారుని మార్చు"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"వినియోగదారుని మార్చు, ప్రస్తుత వినియోగదారు <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"తిరస్కరించు"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"అసలుదాన్ని పునరుద్ధరించడానికి తాకండి."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 6ef2791..5cc4f5e 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"เปิดโหมดประหยัดแบตเตอรี่"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"การตั้งค่า"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WiFi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"โหมดใช้งานบนเครื่องบิน"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"หมุนหน้าจออัตโนมัติ"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ปิดเสียง"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"อัตโนมัติ"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"ปลดล็อก"</string>
     <string name="phone_label" msgid="2320074140205331708">"เปิดโทรศัพท์"</string>
     <string name="camera_label" msgid="7261107956054836961">"เปิดกล้อง"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"เลือกรูปแบบงานใหม่"</string>
+    <string name="cancel" msgid="6442560571259935130">"ยกเลิก"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ปุ่มซูมที่ใช้งานร่วมกันได้"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ซูมหน้าจอให้มีขนาดใหญ่ขึ้น"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"เชื่อมต่อบลูทูธแล้ว"</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"เปิดโหมดบนเครื่องบินแล้ว"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"การห้ามรบกวนเปิดอยู่ เฉพาะเรื่องสำคัญเท่านั้น"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"การห้ามรบกวนเปิดอยู่ ห้ามรบกวน"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"การห้ามรบกวนปิดอยู่"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"ปิดการห้ามรบกวนแล้ว"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"เปิดการห้ามรบกวนแล้ว"</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"ชั้นแสดงของหวาน"</string>
     <string name="start_dreams" msgid="7219575858348719790">"เดย์ดรีม"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"อีเทอร์เน็ต"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"โหมดใช้บนเครื่องบิน"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"ห้ามรบกวน"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"เฉพาะเรื่องสำคัญ"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"ไม่มีการรบกวน"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"บลูทูธ"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"บลูทูธ (<xliff:g id="NUMBER">%d</xliff:g> อุปกรณ์)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ไม่มีเครือข่าย"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"ปิด WiFi"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"เครือข่ายที่บันทึกไว้ทั้งหมดไม่พร้อมใช้งาน"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"ส่ง"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"กำลังส่ง"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"อุปกรณ์ที่ไม่มีชื่อ"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"พร้อมที่จะส่ง"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"ไม่มีการรบกวน แม้แต่นาฬิกาปลุก"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"ไม่มีการรบกวน"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"เฉพาะเรื่องสำคัญเท่านั้น"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"การปลุกครั้งถัดไปของคุณคือเวลา <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"การปลุกครั้งถัดไปของคุณคือ <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"คุณจะไม่ได้ยินเสียงปลุกในเวลา <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"กวาดขึ้นเพื่อปลดล็อก"</string>
     <string name="phone_hint" msgid="3101468054914424646">"กวาดไปทางขวาเพื่อใช้โทรศัพท์"</string>
     <string name="camera_hint" msgid="5241441720959174226">"กวาดไปทางซ้ายเพื่อใช้กล้องถ่ายรูป"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"ไม่มี"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"สำคัญ"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"ทั้งหมด"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"กำลังชาร์จ (อีก <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> เต็ม)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"สลับผู้ใช้"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"เปลี่ยนผู้ใช้จากผู้ใช้ปัจจุบัน <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ปฏิเสธ"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> เป็นช่องโต้ตอบระดับเสียง"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"แตะเพื่อคืนค่าดั้งเดิม"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index f60a85a..6038d71 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"I-on ang pagtitipid ng baterya"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Mga Setting"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Airplane mode"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"I-auto-rotate ang screen"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"i-unlock"</string>
     <string name="phone_label" msgid="2320074140205331708">"buksan ang telepono"</string>
     <string name="camera_label" msgid="7261107956054836961">"buksan ang camera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Pumili ng bagong layout ng gawain"</string>
+    <string name="cancel" msgid="6442560571259935130">"Kanselahin"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Button ng zoom ng pagiging tugma."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Mag-zoom nang mas maliit sa mas malaking screen."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Nakakonekta ang Bluetooth."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Na-on ang Airplane mode."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Naka-on ang huwag istorbohin, priyoridad lang."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Naka-on ang huwag istorbohin, walang mga paggambala."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Naka-off ang huwag istorbohin."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Na-off na ang huwag istorbohin"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Na-on na ang huwag istorbohin."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Airplane mode"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Huwag istorbohin"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Priyoridad lang"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Walang mga paggambala"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> (na) Device)"</string>
@@ -301,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Walang mga pagkaantala. Kahit mga alarma."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Walang mga paggambala"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Mga may priyoridad na paggambala lang"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Ang susunod mong alarma ay sa <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Ang susunod mong alarma ay <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Hindi mo maririnig ang alarma mo ng <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -310,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Mag-swipe pataas upang i-unlock"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Mag-swipe pakanan para sa telepono"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Mag-swipe pakaliwa para sa camera"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Wala"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Prayoridad"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Lahat"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nagtsa-charge (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hanggang mapuno)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Magpalit ng user"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Magpalit ng user, kasalukuyang user <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -380,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tanggihan"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ang volume dialog"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Pindutin upang ibalik ang orihinal."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index df07342..5275730 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Pil tasarrufunu aç"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ayarlar"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Kablosuz"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Uçak modu"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Ekranı otomatik döndür"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"KAPAT"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"OTOMTK"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"kilidi aç"</string>
     <string name="phone_label" msgid="2320074140205331708">"telefonu aç"</string>
     <string name="camera_label" msgid="7261107956054836961">"kamerayı aç"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Yeni görev düzenini seçin"</string>
+    <string name="cancel" msgid="6442560571259935130">"İptal"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Uyumluluk zum düğmesi."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Daha büyük ekrana daha küçük yakınlaştır."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth bağlandı."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Uçak modu açıldı."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Rahatsız etmeyin ayarı açık, yalnızca öncelikliler."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Rahatsız etmeyin ayarı açık, kesme yok."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Rahatsız etmeyin\" ayarı kapalı."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Rahatsız etmeyin\" ayarı kapalı."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Rahatsız etmeyin\" ayarı açık."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Tatlı Kutusu"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Hafif uyku"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Uçak modu"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Rahatsız etmeyin"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Yalnızca öncelikliler"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Kesme yok"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Cihaz)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ağ yok"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Kablosuz Kapalı"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Kullanılabilir kaydedilmiş ağ yok"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Yayınlama"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Yayınlanıyor"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Adsız cihaz"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Yayın için hazır"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Kesinti yok. Uyarı bile yok."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Kesinti yok"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Sadece öncelikli kesintiler"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Bir sonraki alarmın saati: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Bir sonraki alarmınız: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"<xliff:g id="ALARM_TIME">%s</xliff:g> olarak ayarlanan alarmı duymayacaksınız"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Kilidi açmak için hızlıca yukarı kaydırın"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Telefon için sağa kaydırın"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Kamera için sola kaydırın"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Yok"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Öncelik"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Tümü"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Şarj oluyor (tamamen dolmasına <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kaldı)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Kullanıcı değiştirme"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Kullanıcı değiştir. Geçerli kullanıcı: <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Reddet"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ses denetimi iletişim kutusu olarak ayarlandı"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Orijinali geri yüklemek için dokunun."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 879bbbc..7b740a6 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -46,7 +46,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Увімкнути режим заощадження заряду акумулятора"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Налаштування"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим польоту"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Повертати екран автоматично"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ІГНОР."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АВТОМ."</string>
@@ -90,6 +89,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"розблокувати"</string>
     <string name="phone_label" msgid="2320074140205331708">"відкрити телефон"</string>
     <string name="camera_label" msgid="7261107956054836961">"відкрити камеру"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Виберіть новий макет завдання"</string>
+    <string name="cancel" msgid="6442560571259935130">"Скасувати"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Кнопка масштабування сумісності."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Збільшення екрана."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth під’єднано."</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Режим польоту ввімкнено."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Режим \"Не турбувати\" ввімкнено, лише пріоритетні."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Режим \"Не турбувати\" ввімкнено, без сповіщень."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Режим \"Не турбувати\" вимкнено."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Режим \"Не турбувати\" вимкнено."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Режим \"Не турбувати\" ввімкнено."</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Вітрина десертів"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Заставка"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим польоту"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Не турбувати"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Лише пріоритетні"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Без сповіщень"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (пристроїв: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Немає мережі"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi вимкнено"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Немає збережених мереж"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Трансляція"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Трансляція"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Пристрій без назви"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Можна транслювати"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Без сповіщень і сигналів будильника."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Без сповіщень"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Лише пріоритетні сповіщення"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Наступний сигнал: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Наступний сигнал: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Сигнал не лунатиме о <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Проведіть пальцем угору, щоб розблокувати"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Проведіть пальцем праворуч, щоб скористатися телефоном"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Проведіть пальцем ліворуч, щоб скористатися камерою"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Немає"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Пріоритетні"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Усі"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Заряджання (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до повного зарядження)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Змінити користувача"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Змінити користувача, поточний користувач – <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Відхилити"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> призначено регулятором гучності"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Торкніться, щоб відновити оригінал."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 25cdd2d..1906561 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"بیٹری کی بچت آن کریں"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ترتیبات"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"ہوائی جہاز وضع"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"سکرین کو خودکار طور پر گھمائیں"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"خاموش کریں"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"خودکار"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"غیر مقفل کریں"</string>
     <string name="phone_label" msgid="2320074140205331708">"فون کھولیں"</string>
     <string name="camera_label" msgid="7261107956054836961">"کیمرا کھولیں"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"نئے کام کا لے آؤٹ منتخب کریں"</string>
+    <string name="cancel" msgid="6442560571259935130">"منسوخ کریں"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"مطابقت پذیری زوم بٹن۔"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"چھوٹی سے بڑی اسکرین پر زوم کریں۔"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"بلوٹوتھ مربوط ہے۔"</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"ہوائی جہاز وضع کو آن کر دیا گیا۔"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"ڈسٹرب نہ کریں آن ہے، صرف ترجیحی۔"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"ڈسٹرب نہ کریں آن ہے، کوئی مداخلتیں نہیں۔"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"ڈسٹرب نہ کریں آف ہے۔"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"ڈسٹرب نہ کریں کو آف کر دیا گیا۔"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"ڈسٹرب نہ کریں کو آن کر دیا گیا۔"</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"ڈیزرٹ کیس"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ایتھرنیٹ"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ہوائی جہاز طرز"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"ڈسٹرب نہ کریں"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"صرف ترجیحی"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"کوئی مداخلتیں نہیں"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوٹوتھ"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوٹوتھ (<xliff:g id="NUMBER">%d</xliff:g> آلات)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"کوئی نیٹ ورک نہیں ہے"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"‏Wi-Fi آف ہے"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"کوئی محفوظ کردہ نیٹ ورکس دستیاب نہیں ہیں"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"کاسٹ کریں"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"کاسٹنگ"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"بغیر نام والا آلہ"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"کاسٹ کرنے کیلئے تیار"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"کوئی مداخلتیں نہیں ہیں۔ یہاں تک کہ الارمز بھی نہیں ہیں۔"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"کوئی مداخلتیں نہیں ہیں"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"صرف ترجیحی مداخلتیں"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"آپ کا اگلا الارم <xliff:g id="ALARM_TIME">%s</xliff:g> بجے ہے"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"آپ کا اگلا الارم <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g> ہے"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"آپ کو <xliff:g id="ALARM_TIME">%s</xliff:g> بجے اپنا الارم سنائی نہیں دیگا"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"غیر مقفل کرنے کیلئے اوپر سوائپ کریں"</string>
     <string name="phone_hint" msgid="3101468054914424646">"فون کیلئے دائیں سوائپ کریں"</string>
     <string name="camera_hint" msgid="5241441720959174226">"کیمرہ کیلئے بائیں سوائپ کریں"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"کوئی نہیں"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"ترجیح"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"سبھی"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"چارج ہو رہا ہے (مکمل ہونے تک <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> باقی ہیں)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"صارف سوئچ کریں"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"صارف سوئچ کریں، موجودہ صارف <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"مسترد کریں"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> والیوم ڈائلاگ ہے"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"اصل کو بحال کرنے کیلئے ٹچ کریں۔"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 7d7df5f..c3907f2 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Quvvat tejash funksiyasini yoqing"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Sozlamalar"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Parvoz rejimi"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Ekranni avtomatik burish"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"qulfdan chiqarish"</string>
     <string name="phone_label" msgid="2320074140205331708">"telefonni ochish"</string>
     <string name="camera_label" msgid="7261107956054836961">"kamerani ochish"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Yangi vazifa tartibini tanlash"</string>
+    <string name="cancel" msgid="6442560571259935130">"Bekor qilish"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kattalashtirish tugmasi mosligi."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kattaroq ekran uchun kichikroqni kattalashtirish."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ulandi."</string>
@@ -178,6 +179,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Parvoz rejimi yoqildi."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"“Bezovta qilinmasin” funksiyasi yoqilgan, faqat muhim bildirishnomalar ko‘rsatiladi."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"“Bezovta qilinmasin” funksiyasi yoqilgan, bezovta qilinmaydi."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Bezovta qilinmasin, faqat signallar"</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"“Bezovta qilinmasin” funksiyasi o‘chirilgan."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"“Bezovta qilinmasin” funksiyasi o‘chirildi."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"“Bezovta qilinmasin” funksiyasi yoqildi."</string>
@@ -228,9 +230,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Tush kurish"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Parvoz rejimi"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Bezovta qilinmasin"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Faqat muhimlari"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Faqat signallar"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Tanaffuslarsiz"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g>ta qurilma)"</string>
@@ -257,8 +259,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tarmoq mavjud emas"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi o‘chirilgan"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Saqlangan tarmoqlar mavjud emas"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Translatsiya"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Translatsiya qilinmoqda"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Nomsiz qurilma"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Tarqatish uchun tayyor"</string>
@@ -302,6 +303,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Hech narsa bezovta qilmaydi, hatto uyg‘otkichlar ham."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Tanaffuslarsiz"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Faqat ustuvor tanaffuslar"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"Faqat signallar"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Keyingi uyg‘otkich: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Keyingi uyg‘otkich: <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Keyingi uyg‘otkich: <xliff:g id="ALARM_TIME">%s</xliff:g>. Ovoz eshitilmaydi."</string>
@@ -311,9 +313,15 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Qulfdan chiqarish uchun yuqoriga suring"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Telefonni ochish uchun o‘ngga"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Kamerani ochish uchun chapga suring"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Hech biri"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Ustuvorlik"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"Faqat signallar"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"Barchasi"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"Uzilishlar\nbo‘lmasin"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Faqat\nmuhimlar"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Faqat\nsignallar"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Quvvat olmoqda (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>da to‘ladi)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Foydalanuvchini almashtirish"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Foydalanuvchini o‘zgartirish. Joriy foydalanuvchi – <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +389,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rad etish"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ovoz balandligini boshqaradi"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Aslini tiklash uchun bosing."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 14b8e1e..687b056 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Bật trình tiết kiệm pin"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Cài đặt"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Chế độ trên máy bay"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Tự động xoay màn hình"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"TẮT TIẾNG"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"TỰ ĐỘNG"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"mở khóa"</string>
     <string name="phone_label" msgid="2320074140205331708">"mở điện thoại"</string>
     <string name="camera_label" msgid="7261107956054836961">"mở máy ảnh"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Chọn bố cục tác vụ mới"</string>
+    <string name="cancel" msgid="6442560571259935130">"Hủy"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Nút thu phóng khả năng tương thích."</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Thu phóng màn hình lớn hơn hoặc nhỏ hơn."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Đã kết nối bluetooth."</string>
@@ -178,6 +179,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Đã bật chế độ trên máy bay."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Bật tính năng không làm phiền, chỉ ưu tiên."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Bật tính năng không làm phiền, không có gián đoạn."</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Tắt tính năng không làm phiền."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Đã tắt tính năng không làm phiền."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Đã bật tính năng không làm phiền."</string>
@@ -228,9 +231,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Tủ trưng bày bánh ngọt"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Chế độ ngủ"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Chế độ trên máy bay"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Không làm phiền"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Chỉ ưu tiên"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Không có gián đoạn nào"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> thiết bị)"</string>
@@ -257,8 +261,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Không có mạng nào"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Tắt Wi-Fi"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Không có mạng nào được lưu"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Truyền"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Đang truyền"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Thiết bị không có tên"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Sẵn sàng truyền"</string>
@@ -302,6 +305,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Không có gián đoạn. Thậm chí không có cảnh báo."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Không có gián đoạn nào"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Chỉ các gián đoạn ưu tiên"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"Lần báo thức tiếp theo của bạn vào lúc <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"Lần báo thức tiếp theo của bạn là <xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Bạn sẽ không nghe thấy báo thức lúc <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +316,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Vuốt lên để mở khóa"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Vuốt sang phải để mở điện thoại"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Vuốt sang trái để mở máy ảnh"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Không có"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Ưu tiên"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"Tất cả"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Đang sạc (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> cho đến khi đầy)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Chuyển đổi người dùng"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Chuyển người dùng, người dùng hiện tại <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +396,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Từ chối"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> là hộp thoại khối lượng"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Chạm để khôi phục bản gốc."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 43dd4f1..4d45942 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"开启节电助手"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"设置"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WLAN"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"飞行模式"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"自动旋转屏幕"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"静音"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"自动"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"解锁"</string>
     <string name="phone_label" msgid="2320074140205331708">"打开电话"</string>
     <string name="camera_label" msgid="7261107956054836961">"打开相机"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"选择新的任务布局"</string>
+    <string name="cancel" msgid="6442560571259935130">"取消"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"兼容性缩放按钮。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"将小屏幕的图片放大在较大屏幕上显示。"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"蓝牙已连接。"</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"飞行模式已开启。"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"勿扰模式已开启,仅限优先打扰。"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"勿扰模式已开启,禁止打扰。"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"勿扰模式关闭。"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"已关闭勿扰模式。"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"已开启勿扰模式。"</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"甜品盒"</string>
     <string name="start_dreams" msgid="7219575858348719790">"互动屏保"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"有线网络"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飞行模式"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"勿扰"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"仅限优先打扰"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"禁止打扰"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"蓝牙"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"蓝牙(<xliff:g id="NUMBER">%d</xliff:g> 台设备)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"无网络"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WLAN:关闭"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"没有可用的已保存网络"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"投射"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"正在投射"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"未命名设备"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"已准备好投射"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"零打扰(甚至不发出闹钟提醒)。"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"禁止打扰"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"仅限优先打扰内容"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"下次闹钟响铃时间:<xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"下次闹钟响铃时间:<xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"您在<xliff:g id="ALARM_TIME">%s</xliff:g>将不会听到闹钟响铃"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"向上滑动即可解锁"</string>
     <string name="phone_hint" msgid="3101468054914424646">"向右滑动可打开拨号界面"</string>
     <string name="camera_hint" msgid="5241441720959174226">"向左滑动可打开相机"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"无"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"优先"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"正在充电(还需<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>充满)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"切换用户"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"切换用户,当前用户为<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒绝"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”已用作音量控制对话框"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"触摸即可恢复原始设置。"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 6636693..ad6eddb 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"開啟省電模式"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"設定"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"飛行模式"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"自動旋轉螢幕"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"關閉"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"自動"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"解鎖"</string>
     <string name="phone_label" msgid="2320074140205331708">"開啟電話"</string>
     <string name="camera_label" msgid="7261107956054836961">"開啟相機"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"選取新的工作版面配置"</string>
+    <string name="cancel" msgid="6442560571259935130">"取消"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"藍牙連線已建立。"</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"飛行模式已開啟。"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"開啟「請勿騷擾」,僅限優先。"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"開啟「請勿騷擾」,不允許干擾。"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"「請勿騷擾」關閉"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"已關閉「請勿騷擾」。"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"已開啟「請勿騷擾」。"</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"以太網"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飛行模式"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"請勿騷擾"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"僅限優先"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"不允許干擾"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 部裝置)"</string>
@@ -303,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"不干擾 (即使鬧鐘也不例外)。"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"不允許干擾"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"只限重要干擾"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"下次鬧鐘時間:<xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"下次鬧鐘時間:<xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"您不會聽到<xliff:g id="ALARM_TIME">%s</xliff:g> 的鬧鐘"</string>
@@ -312,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"向上快速滑動即可解鎖"</string>
     <string name="phone_hint" msgid="3101468054914424646">"向右快速滑動即可使用手機功能"</string>
     <string name="camera_hint" msgid="5241441720959174226">"向左快速滑動即可使用相機功能"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"無"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"重要"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後完成充電)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"切換使用者"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"切換使用者,目前使用者是<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -382,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒絕"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為音量對話框"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸即可復原。"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 5505db4..dccdd4f 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"開啟節約耗電量模式"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"設定"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"飛行模式"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"自動旋轉螢幕"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"關閉"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"自動"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"解除鎖定"</string>
     <string name="phone_label" msgid="2320074140205331708">"開啟電話"</string>
     <string name="camera_label" msgid="7261107956054836961">"開啟攝影機"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"選取新工作版面配置"</string>
+    <string name="cancel" msgid="6442560571259935130">"取消"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"藍牙連線已建立。"</string>
@@ -180,6 +181,8 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"飛航模式已開啟。"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"「零打擾」設定為開啟,只會顯示優先通知。"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"「零打擾」設定為開啟,不接受任何干擾。"</string>
+    <!-- no translation found for accessibility_quick_settings_dnd_alarms_on (9152834845587554157) -->
+    <skip />
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"「零打擾」設定為關閉。"</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"已停用「零打擾」設定。"</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"已啟用「零打擾」設定。"</string>
@@ -230,9 +233,10 @@
     <string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
     <string name="start_dreams" msgid="7219575858348719790">"休眠模式"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"乙太網路"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飛航模式"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"零打擾"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"僅顯示優先通知"</string>
+    <!-- no translation found for quick_settings_dnd_alarms_label (2559229444312445858) -->
+    <skip />
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"無干擾"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 個裝置)"</string>
@@ -259,8 +263,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網路"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 已關閉"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"找不到已儲存的網路"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"投放"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"投放"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"未命名的裝置"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"可以開始投放了"</string>
@@ -304,6 +307,8 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"不干擾 (即使鬧鐘也不例外)。"</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"不允許干擾"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"僅限優先干擾"</string>
+    <!-- no translation found for zen_alarms (5055668280767657759) -->
+    <skip />
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"下次鬧鐘時間:<xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"下次鬧鐘時間:<xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"您不會聽到<xliff:g id="ALARM_TIME">%s</xliff:g> 的鬧鐘"</string>
@@ -313,9 +318,19 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"向上滑動即可解鎖"</string>
     <string name="phone_hint" msgid="3101468054914424646">"向右滑動可使用手機功能"</string>
     <string name="camera_hint" msgid="5241441720959174226">"向左滑動可使用相機功能"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"無"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"優先"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms (5226306993448328896) -->
+    <skip />
     <string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
+    <!-- no translation found for interruption_level_none_twoline (3942121050170227056) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority_twoline (1564715335217164124) -->
+    <skip />
+    <!-- no translation found for interruption_level_alarms_twoline (3266909566410106146) -->
+    <skip />
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後充飽)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"切換使用者"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"切換使用者,目前使用者是<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -383,4 +398,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒絕"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」現在是預設的音量控制對話方塊。"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸這裡即可恢復原始設定。"</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index a020f21..3609d35 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -44,7 +44,6 @@
     <string name="battery_saver_start_action" msgid="5576697451677486320">"Vula isilondolozi sebhethri"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Izilungiselelo"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"I-Wi-Fi"</string>
-    <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Imodi yendiza"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Ukuzulazula kweskrini okuzenzakalelayo"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"THULISA"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"OKUZENZAKALELAYO"</string>
@@ -88,6 +87,8 @@
     <string name="unlock_label" msgid="8779712358041029439">"vula"</string>
     <string name="phone_label" msgid="2320074140205331708">"vula ifoni"</string>
     <string name="camera_label" msgid="7261107956054836961">"vula ikhamera"</string>
+    <string name="recents_caption_resize" msgid="3517056471774958200">"Khetha isakhiwo somsebenzi omusha"</string>
+    <string name="cancel" msgid="6442560571259935130">"Khansela"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Inkinobho evumelekile yokusondeza"</string>
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Sondeza kancane esikrinini esikhudlwana"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ixhunyiwe"</string>
@@ -178,6 +179,7 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Imodi yendiza ivuliwe."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Ukungaphazamisi kuvuliwe, okubalulekile kuphela."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Ungaphazamisi, akukho ukuphazamiseka."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Ukungaphazamisi kuvuliwe, ama-alamu kuphela."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Ukungaphazamisi kuvaliwe."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Ukungaphazamisi kuvaliwe."</string>
     <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Ukungaphazamisi kuvuliwe."</string>
@@ -228,9 +230,9 @@
     <string name="dessert_case" msgid="1295161776223959221">"Isikhwama soswidi"</string>
     <string name="start_dreams" msgid="7219575858348719790">"Ukuphupha emini"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"I-Ethernet"</string>
-    <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Isimo sendiza"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Ungaphazamisi"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Okubalulekile kuphela"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Ama-alamu kuphela"</string>
     <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Azikho iziphazamiso"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"I-Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"I-Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> amadivayisi)"</string>
@@ -257,8 +259,7 @@
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ayikho inethiwekhi"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"I-Wi-Fi icimile"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Awekho amanethiwekhi alondoloziwe atholakalayo"</string>
-    <!-- no translation found for quick_settings_cast_title (7709016546426454729) -->
-    <skip />
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"Abalingisi"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"Ukusakaza"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Idivayisi engenalo igama"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Ilungele ukusakaza"</string>
@@ -302,6 +303,7 @@
     <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Akukho ukuphazamiseka. Nama-alamu imbala."</string>
     <string name="zen_no_interruptions" msgid="7970973750143632592">"Azikho iziphazamiso"</string>
     <string name="zen_important_interruptions" msgid="3477041776609757628">"Iziphazamiso ezibalulekile kuphela"</string>
+    <string name="zen_alarms" msgid="5055668280767657759">"Ama-alamu kuphela"</string>
     <string name="zen_alarm_information_time" msgid="5235772206174372272">"I-alamu yakho elandelayo ingo<xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_information_day_time" msgid="8422733576255047893">"I-alamu yakho elandelayo ingo-<xliff:g id="ALARM_DAY_AND_TIME">%s</xliff:g>"</string>
     <string name="zen_alarm_warning" msgid="6873910860111498041">"Ngeke uzwe i-alamu yakho ngo-<xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
@@ -311,9 +313,15 @@
     <string name="keyguard_unlock" msgid="8043466894212841998">"Swayiphela phezulu ukuze uvule"</string>
     <string name="phone_hint" msgid="3101468054914424646">"Swayiphela ngakwesokudla ukuze uthole ifoni"</string>
     <string name="camera_hint" msgid="5241441720959174226">"Swayiphela ngakwesokunxele ukuze uthole ikhamela"</string>
-    <string name="interruption_level_none" msgid="3831278883136066646">"Lutho"</string>
-    <string name="interruption_level_priority" msgid="6517366750688942030">"Okubalulekile"</string>
+    <!-- no translation found for interruption_level_none (8284541443482072628) -->
+    <skip />
+    <!-- no translation found for interruption_level_priority (6426766465363855505) -->
+    <skip />
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"Ama-alamu kuphela"</string>
     <string name="interruption_level_all" msgid="1330581184930945764">"Konke"</string>
+    <string name="interruption_level_none_twoline" msgid="3942121050170227056">"Akukho\nukuphazamiseka"</string>
+    <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Okubalulekile\nkuphela"</string>
+    <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Ama-alamu\nkuphela"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Iyashaja (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ize igcwale)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Shintsha umsebenzisi"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Shintsha umsebenzisi, umsebenzisi wamanje ngu-<xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
@@ -381,4 +389,6 @@
     <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Phika"</string>
     <string name="volumeui_notification_title" msgid="4906770126345910955">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> yingxoxo yevolumu"</string>
     <string name="volumeui_notification_text" msgid="1826889705095768656">"Thinta ukuze ubuyisele kokwangempela."</string>
+    <!-- no translation found for volume_zen_switch_text (6388350641576595452) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 6ecdca3..24f92ef 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -72,5 +72,15 @@
         <attr name="verticalSpacing" format="dimension" />
         <attr name="horizontalSpacing" format="dimension" />
     </declare-styleable>
+
+    <!-- Theme for icons in the status bar (light/dark). background/fillColor is used for dual tone
+         icons like wifi and signal, and singleToneColor is used for icons with only one tone.
+         Contract: Pixel with fillColor blended over backgroundColor blended over translucent should
+         equal to singleToneColor blended over translucent. -->
+    <declare-styleable name="TonedIcon">
+        <attr name="backgroundColor" format="integer" />
+        <attr name="fillColor" format="integer" />
+        <attr name="singleToneColor" format="integer" />
+    </declare-styleable>
 </resources>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index d4aeab6..ded7c4e 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -108,8 +108,7 @@
     <color name="notification_guts_text_color">#b2FFFFFF</color>
     <color name="notification_guts_btn_color">#FFFFFFFF</color>
 
-    <color name="search_panel_circle_color">#ffffff</color>
-    <color name="search_panel_ripple_color">#ffbbbbbb</color>
+    <color name="assist_orb_color">#ffffff</color>
 
     <color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
     <color name="doze_small_icon_background_color">#ff434343</color>
@@ -130,5 +129,12 @@
     <color name="segmented_button_selected">#FFFFFFFF</color>
     <color name="segmented_button_unselected">#B3B0BEC5</color><!-- 70% blue grey 200 -->
     <color name="volume_panel_divider">#1FFFFFFF</color><!-- 12% white -->
-    <color name="light_mode_icon_color">#FF616161</color><!-- grey 700 -->
+
+    <color name="dark_mode_icon_color_single_tone">#99000000</color>
+    <color name="dark_mode_icon_color_dual_tone_background">#3d000000</color>
+    <color name="dark_mode_icon_color_dual_tone_fill">#7a000000</color>
+
+    <color name="light_mode_icon_color_single_tone">#ffffff</color>
+    <color name="light_mode_icon_color_dual_tone_background">#4dffffff</color>
+    <color name="light_mode_icon_color_dual_tone_fill">#ffffff</color>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c24cd64..c9e1fee 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -471,22 +471,23 @@
     <dimen name="go_to_full_shade_appearing_translation">200dp</dimen>
 
     <!-- The diameter of the search panel circle. -->
-    <dimen name="search_panel_circle_size">88dp</dimen>
+    <dimen name="assist_orb_size">144dp</dimen>
 
-    <!-- The margin to the edge of the screen from where the circle starts to appear -->
-    <dimen name="search_panel_circle_base_margin">80dp</dimen>
+    <!-- The margin to the edge of the screen from where the orb starts to appear -->
+    <dimen name="assist_orb_base_margin">22dp</dimen>
 
-    <!-- The amount the circle translates when appearing -->
-    <dimen name="search_panel_circle_travel_distance">80dp</dimen>
+    <!-- The amount the orb translates when appearing -->
+    <dimen name="assist_orb_travel_distance">26dp</dimen>
 
-    <!-- The elevation of the search panel circle -->
-    <dimen name="search_panel_circle_elevation">12dp</dimen>
+    <!-- The elevation of the orb -->
+    <dimen name="assist_orb_elevation">12dp</dimen>
 
-    <!-- The height of the scrim behind the search panel circle. -->
-    <dimen name="search_panel_scrim_height">250dp</dimen>
+    <!-- The height of the scrim behind the orb. -->
+    <dimen name="assist_orb_scrim_height">250dp</dimen>
 
-    <!-- How far the user needs to drag up to invoke search. -->
-    <dimen name="search_panel_threshold">100dp</dimen>
+    <!-- The height of the scrim behind the search panel circle. Should be navigation_bar_height
+         + 8dp. -->
+    <dimen name="assist_orb_navbar_scrim_height">56dp</dimen>
 
     <!-- The width/height of the phone/camera/unlock icon view on keyguard. -->
     <dimen name="keyguard_affordance_height">56dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b696787..3705157 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -100,9 +100,6 @@
     <!-- Name of the button that links to the Wifi settings screen. [CHAR LIMIT=NONE] -->
     <string name="status_bar_settings_wifi_button">Wi-Fi</string>
 
-    <!-- Label in the system panel for airplane mode (all radios are turned off)[CHAR LIMIT=30] -->
-    <string name="status_bar_settings_airplane">Airplane mode</string>
-
     <!-- Label in system panel saying the device will use the orientation sensor to rotate [CHAR LIMIT=30] -->
     <string name="status_bar_settings_auto_rotation">Auto-rotate screen</string>
 
@@ -438,6 +435,8 @@
     <string name="accessibility_quick_settings_dnd_priority_on">Do not disturb on, priority only.</string>
     <!-- Content description of the do not disturb tile in quick settings when on in none (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_dnd_none_on">Do not disturb on, no interruptions.</string>
+    <!-- Content description of the do not disturb tile in quick settings when on in alarms only (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_dnd_alarms_on">Do not disturb on, alarms only.</string>
      <!-- Content description of the do not disturb tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_dnd_off">Do not disturb off.</string>
     <!-- Announcement made when do not disturb changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -566,12 +565,12 @@
     <!-- Textual description of Ethernet connections -->
     <string name="ethernet_label">Ethernet</string>
 
-    <!-- QuickSettings: Airplane mode [CHAR LIMIT=NONE] -->
-    <string name="quick_settings_airplane_mode_label">Airplane mode</string>
     <!-- QuickSettings: Do not disturb [CHAR LIMIT=NONE] -->
     <string name="quick_settings_dnd_label">Do not disturb</string>
     <!-- QuickSettings: Do not disturb - Priority only [CHAR LIMIT=NONE] -->
     <string name="quick_settings_dnd_priority_label">Priority only</string>
+    <!-- QuickSettings: Do not disturb - Alarms only [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_dnd_alarms_label">Alarms only</string>
     <!-- QuickSettings: Do not disturb - No interruptions [CHAR LIMIT=NONE] -->
     <string name="quick_settings_dnd_none_label">No interruptions</string>
     <!-- QuickSettings: Bluetooth [CHAR LIMIT=NONE] -->
@@ -730,6 +729,9 @@
     <!-- Zen mode: Only important interruptions. [CHAR LIMIT=40] -->
     <string name="zen_important_interruptions">Priority interruptions only</string>
 
+    <!-- Zen mode: Only alarms. [CHAR LIMIT=40] -->
+    <string name="zen_alarms">Alarms only</string>
+
     <!-- Zen mode: Next alarm information - just a time. [CHAR LIMIT=40] -->
     <string name="zen_alarm_information_time">Your next alarm is at <xliff:g id="alarm_time" example="5:00 PM">%s</xliff:g></string>
 
@@ -758,14 +760,26 @@
     <string name="camera_hint">Swipe left for camera</string>
 
     <!-- Interruption level: None. [CHAR LIMIT=20] -->
-    <string name="interruption_level_none">None</string>
+    <string name="interruption_level_none">No interruptions</string>
 
     <!-- Interruption level: Priority. [CHAR LIMIT=20] -->
-    <string name="interruption_level_priority">Priority</string>
+    <string name="interruption_level_priority">Priority only</string>
+
+    <!-- Interruption level: Alarms only. [CHAR LIMIT=20] -->
+    <string name="interruption_level_alarms">Alarms only</string>
 
     <!-- Interruption level: All. [CHAR LIMIT=20] -->
     <string name="interruption_level_all">All</string>
 
+    <!-- Interruption level: None.  Optimized for narrow two-line display. [CHAR LIMIT=20] -->
+    <string name="interruption_level_none_twoline">No\ninterruptions</string>
+
+    <!-- Interruption level: Priority.  Optimized for narrow two-line display. [CHAR LIMIT=20] -->
+    <string name="interruption_level_priority_twoline">Priority\nonly</string>
+
+    <!-- Interruption level: Alarms only.  Optimized for narrow two-line display. [CHAR LIMIT=20] -->
+    <string name="interruption_level_alarms_twoline">Alarms\nonly</string>
+
     <!-- Indication on the keyguard that is shown when the device is charging. [CHAR LIMIT=40]-->
     <string name="keyguard_indication_charging_time">Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%s</xliff:g> until full)</string>
 
@@ -965,4 +979,7 @@
 
     <!-- VolumeUI restoration notification: text -->
     <string name="volumeui_notification_text">Touch to restore the original.</string>
+
+    <!-- Volume dialog zen toggle switch title -->
+    <string name="volume_zen_switch_text">Block interruptions</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 07fcb82..107a8ec 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -246,12 +246,6 @@
         <item name="android:layout_height">match_parent</item>
     </style>
 
-    <style name="SearchPanelScrim">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">@dimen/search_panel_scrim_height</item>
-        <item name="android:layout_gravity">bottom</item>
-    </style>
-
     <style name="UserDetailView">
         <item name="numColumns">3</item>
     </style>
@@ -265,4 +259,15 @@
         <item name="android:backgroundDimEnabled">false</item>
         <item name="android:alertDialogTheme">@style/Theme.SystemUI.Dialog.Alert</item>
     </style>
+
+    <style name="DualToneLightTheme">
+        <item name="backgroundColor">@color/light_mode_icon_color_dual_tone_background</item>
+        <item name="fillColor">@color/light_mode_icon_color_dual_tone_fill</item>
+        <item name="singleToneColor">@color/light_mode_icon_color_single_tone</item>
+    </style>
+    <style name="DualToneDarkTheme">
+        <item name="backgroundColor">@color/dark_mode_icon_color_dual_tone_background</item>
+        <item name="fillColor">@color/dark_mode_icon_color_dual_tone_fill</item>
+        <item name="singleToneColor">@color/dark_mode_icon_color_single_tone</item>
+    </style>
 </resources>
diff --git a/packages/SystemUI/res/values/volume.xml b/packages/SystemUI/res/values/volume.xml
new file mode 100644
index 0000000..f516104
--- /dev/null
+++ b/packages/SystemUI/res/values/volume.xml
@@ -0,0 +1,87 @@
+<!--
+     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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item name="volume_expand_animation_duration" type="integer">300</item>
+
+    <color name="volume_icon_color">#ffffffff</color>
+    <color name="volume_settings_icon_color">#7fffffff</color>
+
+    <dimen name="volume_slider_interspacing">2dp</dimen>
+    <dimen name="volume_offset_top">0dp</dimen>
+    <dimen name="volume_button_size">48dp</dimen>
+
+    <item name="volume_secondary_alpha" format="float" type="dimen">0.3</item>
+
+    <style name="VolumeDialogAnimations">
+        <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
+        <item name="android:windowExitAnimation">@android:anim/fade_out</item>
+    </style>
+
+    <style name="VolumeButtons" parent="@android:style/Widget.Material.Button.Borderless">
+        <item name="android:background">@drawable/btn_borderless_rect</item>
+    </style>
+
+    <style name="TextAppearance" />
+
+    <style name="TextAppearance.Volume">
+        <item name="android:textStyle">normal</item>
+        <item name="android:textColor">#ffffffff</item>
+        <item name="android:fontFamily">sans-serif</item>
+    </style>
+
+    <style name="TextAppearance.Volume.ZenSwitch">
+        <item name="android:textSize">16sp</item>
+        <item name="android:fontFamily">sans-serif-medium</item>
+    </style>
+
+    <style name="TextAppearance.Volume.ZenSwitchSummary">
+        <item name="android:textSize">14sp</item>
+        <item name="android:fontFamily">sans-serif-medium</item>
+    </style>
+
+    <style name="TextAppearance.Volume.ZenSwitchDetail">
+        <item name="android:textSize">14sp</item>
+        <item name="android:fontFamily">sans-serif</item>
+        <item name="android:textColor">#ffb0b3c5</item>
+    </style>
+
+    <string-array name="volume_stream_titles" translatable="false">
+        <item>Voice calls</item> <!-- STREAM_VOICE_CALL -->
+        <item>System</item> <!-- STREAM_SYSTEM -->
+        <item>Notifications</item> <!-- STREAM_RING -->
+        <item>Media</item> <!-- STREAM_MUSIC -->
+        <item>Alarms</item> <!-- STREAM_ALARM -->
+        <item></item> <!-- STREAM_NOTIFICATION -->
+        <item>Bluetooth calls</item> <!-- STREAM_BLUETOOTH_SCO -->
+        <item></item> <!-- STREAM_SYSTEM_ENFORCED -->
+        <item></item> <!-- STREAM_DTMF -->
+        <item></item> <!-- STREAM_TTS -->
+    </string-array>
+
+    <string name="volume_dnd_is_on" translatable="false">Do not disturb is on</string>
+    <string name="volume_turn_off" translatable="false">Turn off</string>
+    <string name="volume_stream_muted" translatable="false">%s silent</string>
+    <string name="volume_stream_vibrate" translatable="false">%s vibrate</string>
+    <string name="volume_stream_suppressed" translatable="false">%1$s silent — %2$s</string>
+    <string name="volume_stream_muted_dnd" translatable="false">%s silent — No interruptions</string>
+    <string name="volume_stream_limited_dnd" translatable="false">%s — Priority only</string>
+    <string name="volume_stream_vibrate_dnd" translatable="false">%s vibrate — Priority only</string>
+    <string name="volume_dnd_ends_in" translatable="false">Do not disturb ends in %s</string>
+    <string name="volume_dnd_ends_at" translatable="false">Do not disturb ends at %s</string>
+    <string name="volume_end_now" translatable="false">End now</string>
+
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 2e95498..292c9c2 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui;
 
+import android.animation.ArgbEvaluator;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -80,6 +81,12 @@
     private BatteryController mBatteryController;
     private boolean mPowerSaveEnabled;
 
+    private int mDarkModeBackgroundColor;
+    private int mDarkModeFillColor;
+
+    private int mLightModeBackgroundColor;
+    private int mLightModeFillColor;
+
     private class BatteryTracker extends BroadcastReceiver {
         public static final int UNKNOWN_LEVEL = -1;
 
@@ -245,6 +252,13 @@
         mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mBoltPaint.setColor(context.getColor(R.color.batterymeter_bolt_color));
         mBoltPoints = loadBoltPoints(res);
+
+        mDarkModeBackgroundColor =
+                context.getColor(R.color.dark_mode_icon_color_dual_tone_background);
+        mDarkModeFillColor = context.getColor(R.color.dark_mode_icon_color_dual_tone_fill);
+        mLightModeBackgroundColor =
+                context.getColor(R.color.light_mode_icon_color_dual_tone_background);
+        mLightModeFillColor = context.getColor(R.color.light_mode_icon_color_dual_tone_fill);
     }
 
     public void setBatteryController(BatteryController batteryController) {
@@ -309,14 +323,30 @@
         return color;
     }
 
-    public void setIconTint(int tint) {
-        mIconTint = tint;
-        mFramePaint.setColorFilter(new PorterDuffColorFilter(tint, PorterDuff.Mode.SRC_ATOP));
-        mBoltPaint.setColor(tint);
-        mChargeColor = tint;
+    public void setDarkIntensity(float darkIntensity) {
+        int backgroundColor = getBackgroundColor(darkIntensity);
+        int fillColor = getFillColor(darkIntensity);
+        mIconTint = fillColor;
+        mFramePaint.setColor(backgroundColor);
+        mBoltPaint.setColor(backgroundColor);
+        mChargeColor = fillColor;
         invalidate();
     }
 
+    private int getBackgroundColor(float darkIntensity) {
+        return getColorForDarkIntensity(
+                darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor);
+    }
+
+    private int getFillColor(float darkIntensity) {
+        return getColorForDarkIntensity(
+                darkIntensity, mLightModeFillColor, mDarkModeFillColor);
+    }
+
+    private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) {
+        return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor);
+    }
+
     @Override
     public void draw(Canvas c) {
         BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker;
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelCircleView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelCircleView.java
deleted file mode 100644
index f33e2b8..0000000
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelCircleView.java
+++ /dev/null
@@ -1,592 +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
- */
-
-package com.android.systemui;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.PropertyValuesHolder;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Outline;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewOutlineProvider;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
-
-import java.util.ArrayList;
-
-public class SearchPanelCircleView extends FrameLayout {
-
-    private final int mCircleMinSize;
-    private final int mBaseMargin;
-    private final int mStaticOffset;
-    private final Paint mBackgroundPaint = new Paint();
-    private final Paint mRipplePaint = new Paint();
-    private final Rect mCircleRect = new Rect();
-    private final Rect mStaticRect = new Rect();
-    private final Interpolator mFastOutSlowInInterpolator;
-    private final Interpolator mAppearInterpolator;
-    private final Interpolator mDisappearInterpolator;
-
-    private boolean mClipToOutline;
-    private final int mMaxElevation;
-    private boolean mAnimatingOut;
-    private float mOutlineAlpha;
-    private float mOffset;
-    private float mCircleSize;
-    private boolean mHorizontal;
-    private boolean mCircleHidden;
-    private ImageView mLogo;
-    private boolean mDraggedFarEnough;
-    private boolean mOffsetAnimatingIn;
-    private float mCircleAnimationEndValue;
-    private ArrayList<Ripple> mRipples = new ArrayList<Ripple>();
-
-    private ValueAnimator mOffsetAnimator;
-    private ValueAnimator mCircleAnimator;
-    private ValueAnimator mFadeOutAnimator;
-    private ValueAnimator.AnimatorUpdateListener mCircleUpdateListener
-            = new ValueAnimator.AnimatorUpdateListener() {
-        @Override
-        public void onAnimationUpdate(ValueAnimator animation) {
-            applyCircleSize((float) animation.getAnimatedValue());
-            updateElevation();
-        }
-    };
-    private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() {
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            mCircleAnimator = null;
-        }
-    };
-    private ValueAnimator.AnimatorUpdateListener mOffsetUpdateListener
-            = new ValueAnimator.AnimatorUpdateListener() {
-        @Override
-        public void onAnimationUpdate(ValueAnimator animation) {
-            setOffset((float) animation.getAnimatedValue());
-        }
-    };
-
-
-    public SearchPanelCircleView(Context context) {
-        this(context, null);
-    }
-
-    public SearchPanelCircleView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public SearchPanelCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public SearchPanelCircleView(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                if (mCircleSize > 0.0f) {
-                    outline.setOval(mCircleRect);
-                } else {
-                    outline.setEmpty();
-                }
-                outline.setAlpha(mOutlineAlpha);
-            }
-        });
-        setWillNotDraw(false);
-        mCircleMinSize = context.getResources().getDimensionPixelSize(
-                R.dimen.search_panel_circle_size);
-        mBaseMargin = context.getResources().getDimensionPixelSize(
-                R.dimen.search_panel_circle_base_margin);
-        mStaticOffset = context.getResources().getDimensionPixelSize(
-                R.dimen.search_panel_circle_travel_distance);
-        mMaxElevation = context.getResources().getDimensionPixelSize(
-                R.dimen.search_panel_circle_elevation);
-        mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
-                android.R.interpolator.linear_out_slow_in);
-        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(mContext,
-                android.R.interpolator.fast_out_slow_in);
-        mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
-                android.R.interpolator.fast_out_linear_in);
-        mBackgroundPaint.setAntiAlias(true);
-        mBackgroundPaint.setColor(context.getColor(R.color.search_panel_circle_color));
-        mRipplePaint.setColor(context.getColor(R.color.search_panel_ripple_color));
-        mRipplePaint.setAntiAlias(true);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        drawBackground(canvas);
-        drawRipples(canvas);
-    }
-
-    private void drawRipples(Canvas canvas) {
-        for (int i = 0; i < mRipples.size(); i++) {
-            Ripple ripple = mRipples.get(i);
-            ripple.draw(canvas);
-        }
-    }
-
-    private void drawBackground(Canvas canvas) {
-        canvas.drawCircle(mCircleRect.centerX(), mCircleRect.centerY(), mCircleSize / 2,
-                mBackgroundPaint);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mLogo = (ImageView) findViewById(R.id.search_logo);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        mLogo.layout(0, 0, mLogo.getMeasuredWidth(), mLogo.getMeasuredHeight());
-        if (changed) {
-            updateCircleRect(mStaticRect, mStaticOffset, true);
-        }
-    }
-
-    public void setCircleSize(float circleSize) {
-        setCircleSize(circleSize, false, null, 0, null);
-    }
-
-    public void setCircleSize(float circleSize, boolean animated, final Runnable endRunnable,
-            int startDelay, Interpolator interpolator) {
-        boolean isAnimating = mCircleAnimator != null;
-        boolean animationPending = isAnimating && !mCircleAnimator.isRunning();
-        boolean animatingOut = isAnimating && mCircleAnimationEndValue == 0;
-        if (animated || animationPending || animatingOut) {
-            if (isAnimating) {
-                if (circleSize == mCircleAnimationEndValue) {
-                    return;
-                }
-                mCircleAnimator.cancel();
-            }
-            mCircleAnimator = ValueAnimator.ofFloat(mCircleSize, circleSize);
-            mCircleAnimator.addUpdateListener(mCircleUpdateListener);
-            mCircleAnimator.addListener(mClearAnimatorListener);
-            mCircleAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    if (endRunnable != null) {
-                        endRunnable.run();
-                    }
-                }
-            });
-            Interpolator desiredInterpolator = interpolator != null ? interpolator
-                    : circleSize == 0 ? mDisappearInterpolator : mAppearInterpolator;
-            mCircleAnimator.setInterpolator(desiredInterpolator);
-            mCircleAnimator.setDuration(300);
-            mCircleAnimator.setStartDelay(startDelay);
-            mCircleAnimator.start();
-            mCircleAnimationEndValue = circleSize;
-        } else {
-            if (isAnimating) {
-                float diff = circleSize - mCircleAnimationEndValue;
-                PropertyValuesHolder[] values = mCircleAnimator.getValues();
-                values[0].setFloatValues(diff, circleSize);
-                mCircleAnimator.setCurrentPlayTime(mCircleAnimator.getCurrentPlayTime());
-                mCircleAnimationEndValue = circleSize;
-            } else {
-                applyCircleSize(circleSize);
-                updateElevation();
-            }
-        }
-    }
-
-    private void applyCircleSize(float circleSize) {
-        mCircleSize = circleSize;
-        updateLayout();
-    }
-
-    private void updateElevation() {
-        float t = (mStaticOffset - mOffset) / (float) mStaticOffset;
-        t = 1.0f - Math.max(t, 0.0f);
-        float offset = t * mMaxElevation;
-        setElevation(offset);
-    }
-
-    /**
-     * Sets the offset to the edge of the screen. By default this not not animated.
-     *
-     * @param offset The offset to apply.
-     */
-    public void setOffset(float offset) {
-        setOffset(offset, false, 0, null, null);
-    }
-
-    /**
-     * Sets the offset to the edge of the screen.
-     *
-     * @param offset The offset to apply.
-     * @param animate Whether an animation should be performed.
-     * @param startDelay The desired start delay if animated.
-     * @param interpolator The desired interpolator if animated. If null,
-     *                     a default interpolator will be taken designed for appearing or
-     *                     disappearing.
-     * @param endRunnable The end runnable which should be executed when the animation is finished.
-     */
-    private void setOffset(float offset, boolean animate, int startDelay,
-            Interpolator interpolator, final Runnable endRunnable) {
-        if (!animate) {
-            mOffset = offset;
-            updateLayout();
-            if (endRunnable != null) {
-                endRunnable.run();
-            }
-        } else {
-            if (mOffsetAnimator != null) {
-                mOffsetAnimator.removeAllListeners();
-                mOffsetAnimator.cancel();
-            }
-            mOffsetAnimator = ValueAnimator.ofFloat(mOffset, offset);
-            mOffsetAnimator.addUpdateListener(mOffsetUpdateListener);
-            mOffsetAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mOffsetAnimator = null;
-                    if (endRunnable != null) {
-                        endRunnable.run();
-                    }
-                }
-            });
-            Interpolator desiredInterpolator = interpolator != null ?
-                    interpolator : offset == 0 ? mDisappearInterpolator : mAppearInterpolator;
-            mOffsetAnimator.setInterpolator(desiredInterpolator);
-            mOffsetAnimator.setStartDelay(startDelay);
-            mOffsetAnimator.setDuration(300);
-            mOffsetAnimator.start();
-            mOffsetAnimatingIn = offset != 0;
-        }
-    }
-
-    private void updateLayout() {
-        updateCircleRect();
-        updateLogo();
-        invalidateOutline();
-        invalidate();
-        updateClipping();
-    }
-
-    private void updateClipping() {
-        boolean clip = mCircleSize < mCircleMinSize || !mRipples.isEmpty();
-        if (clip != mClipToOutline) {
-            setClipToOutline(clip);
-            mClipToOutline = clip;
-        }
-    }
-
-    private void updateLogo() {
-        boolean exitAnimationRunning = mFadeOutAnimator != null;
-        Rect rect = exitAnimationRunning ? mCircleRect : mStaticRect;
-        float translationX = (rect.left + rect.right) / 2.0f - mLogo.getWidth() / 2.0f;
-        float translationY = (rect.top + rect.bottom) / 2.0f - mLogo.getHeight() / 2.0f;
-        float t = (mStaticOffset - mOffset) / (float) mStaticOffset;
-        if (!exitAnimationRunning) {
-            if (mHorizontal) {
-                translationX += t * mStaticOffset * 0.3f;
-            } else {
-                translationY += t * mStaticOffset * 0.3f;
-            }
-            float alpha = 1.0f-t;
-            alpha = Math.max((alpha - 0.5f) * 2.0f, 0);
-            mLogo.setAlpha(alpha);
-        } else {
-            translationY += (mOffset - mStaticOffset) / 2;
-        }
-        mLogo.setTranslationX(translationX);
-        mLogo.setTranslationY(translationY);
-    }
-
-    private void updateCircleRect() {
-        updateCircleRect(mCircleRect, mOffset, false);
-    }
-
-    private void updateCircleRect(Rect rect, float offset, boolean useStaticSize) {
-        int left, top;
-        float circleSize = useStaticSize ? mCircleMinSize : mCircleSize;
-        if (mHorizontal) {
-            left = (int) (getWidth() - circleSize / 2 - mBaseMargin - offset);
-            top = (int) ((getHeight() - circleSize) / 2);
-        } else {
-            left = (int) (getWidth() - circleSize) / 2;
-            top = (int) (getHeight() - circleSize / 2 - mBaseMargin - offset);
-        }
-        rect.set(left, top, (int) (left + circleSize), (int) (top + circleSize));
-    }
-
-    public void setHorizontal(boolean horizontal) {
-        mHorizontal = horizontal;
-        updateCircleRect(mStaticRect, mStaticOffset, true);
-        updateLayout();
-    }
-
-    public void setDragDistance(float distance) {
-        if (!mAnimatingOut && (!mCircleHidden || mDraggedFarEnough)) {
-            float circleSize = mCircleMinSize + rubberband(distance);
-            setCircleSize(circleSize);
-        }
-
-    }
-
-    private float rubberband(float diff) {
-        return (float) Math.pow(Math.abs(diff), 0.6f);
-    }
-
-    public void startAbortAnimation(Runnable endRunnable) {
-        if (mAnimatingOut) {
-            if (endRunnable != null) {
-                endRunnable.run();
-            }
-            return;
-        }
-        setCircleSize(0, true, null, 0, null);
-        setOffset(0, true, 0, null, endRunnable);
-        mCircleHidden = true;
-    }
-
-    public void startEnterAnimation() {
-        if (mAnimatingOut) {
-            return;
-        }
-        applyCircleSize(0);
-        setOffset(0);
-        setCircleSize(mCircleMinSize, true, null, 50, null);
-        setOffset(mStaticOffset, true, 50, null, null);
-        mCircleHidden = false;
-    }
-
-
-    public void startExitAnimation(final Runnable endRunnable) {
-        if (!mHorizontal) {
-            float offset = getHeight() / 2.0f;
-            setOffset(offset - mBaseMargin, true, 50, mFastOutSlowInInterpolator, null);
-            float xMax = getWidth() / 2;
-            float yMax = getHeight() / 2;
-            float maxRadius = (float) Math.ceil(Math.hypot(xMax, yMax) * 2);
-            setCircleSize(maxRadius, true, null, 50, mFastOutSlowInInterpolator);
-            performExitFadeOutAnimation(50, 300, endRunnable);
-        } else {
-
-            // when in landscape, we don't wan't the animation as it interferes with the general
-            // rotation animation to the homescreen.
-            endRunnable.run();
-        }
-    }
-
-    private void performExitFadeOutAnimation(int startDelay, int duration,
-            final Runnable endRunnable) {
-        mFadeOutAnimator = ValueAnimator.ofFloat(mBackgroundPaint.getAlpha() / 255.0f, 0.0f);
-
-        // Linear since we are animating multiple values
-        mFadeOutAnimator.setInterpolator(new LinearInterpolator());
-        mFadeOutAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                float animatedFraction = animation.getAnimatedFraction();
-                float logoValue = animatedFraction > 0.5f ? 1.0f : animatedFraction / 0.5f;
-                logoValue = PhoneStatusBar.ALPHA_OUT.getInterpolation(1.0f - logoValue);
-                float backgroundValue = animatedFraction < 0.2f ? 0.0f :
-                        PhoneStatusBar.ALPHA_OUT.getInterpolation((animatedFraction - 0.2f) / 0.8f);
-                backgroundValue = 1.0f - backgroundValue;
-                mBackgroundPaint.setAlpha((int) (backgroundValue * 255));
-                mOutlineAlpha = backgroundValue;
-                mLogo.setAlpha(logoValue);
-                invalidateOutline();
-                invalidate();
-            }
-        });
-        mFadeOutAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (endRunnable != null) {
-                    endRunnable.run();
-                }
-                mLogo.setAlpha(1.0f);
-                mBackgroundPaint.setAlpha(255);
-                mOutlineAlpha = 1.0f;
-                mFadeOutAnimator = null;
-            }
-        });
-        mFadeOutAnimator.setStartDelay(startDelay);
-        mFadeOutAnimator.setDuration(duration);
-        mFadeOutAnimator.start();
-    }
-
-    public void setDraggedFarEnough(boolean farEnough) {
-        if (farEnough != mDraggedFarEnough) {
-            if (farEnough) {
-                if (mCircleHidden) {
-                    startEnterAnimation();
-                }
-                if (mOffsetAnimator == null) {
-                    addRipple();
-                } else {
-                    postDelayed(new Runnable() {
-                        @Override
-                        public void run() {
-                            addRipple();
-                        }
-                    }, 100);
-                }
-            } else {
-                startAbortAnimation(null);
-            }
-            mDraggedFarEnough = farEnough;
-        }
-
-    }
-
-    private void addRipple() {
-        if (mRipples.size() > 1) {
-            // we only want 2 ripples at the time
-            return;
-        }
-        float xInterpolation, yInterpolation;
-        if (mHorizontal) {
-            xInterpolation = 0.75f;
-            yInterpolation = 0.5f;
-        } else {
-            xInterpolation = 0.5f;
-            yInterpolation = 0.75f;
-        }
-        float circleCenterX = mStaticRect.left * (1.0f - xInterpolation)
-                + mStaticRect.right * xInterpolation;
-        float circleCenterY = mStaticRect.top * (1.0f - yInterpolation)
-                + mStaticRect.bottom * yInterpolation;
-        float radius = Math.max(mCircleSize, mCircleMinSize * 1.25f) * 0.75f;
-        Ripple ripple = new Ripple(circleCenterX, circleCenterY, radius);
-        ripple.start();
-    }
-
-    public void reset() {
-        mDraggedFarEnough = false;
-        mAnimatingOut = false;
-        mCircleHidden = true;
-        mClipToOutline = false;
-        if (mFadeOutAnimator != null) {
-            mFadeOutAnimator.cancel();
-        }
-        mBackgroundPaint.setAlpha(255);
-        mOutlineAlpha = 1.0f;
-    }
-
-    /**
-     * Check if an animation is currently running
-     *
-     * @param enterAnimation Is the animating queried the enter animation.
-     */
-    public boolean isAnimationRunning(boolean enterAnimation) {
-        return mOffsetAnimator != null && (enterAnimation == mOffsetAnimatingIn);
-    }
-
-    public void performOnAnimationFinished(final Runnable runnable) {
-        if (mOffsetAnimator != null) {
-            mOffsetAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    if (runnable != null) {
-                        runnable.run();
-                    }
-                }
-            });
-        } else {
-            if (runnable != null) {
-                runnable.run();
-            }
-        }
-    }
-
-    public void setAnimatingOut(boolean animatingOut) {
-        mAnimatingOut = animatingOut;
-    }
-
-    /**
-     * @return Whether the circle is currently launching to the search activity or aborting the
-     * interaction
-     */
-    public boolean isAnimatingOut() {
-        return mAnimatingOut;
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        // not really true but it's ok during an animation, as it's never permanent
-        return false;
-    }
-
-    private class Ripple {
-        float x;
-        float y;
-        float radius;
-        float endRadius;
-        float alpha;
-
-        Ripple(float x, float y, float endRadius) {
-            this.x = x;
-            this.y = y;
-            this.endRadius = endRadius;
-        }
-
-        void start() {
-            ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 1.0f);
-
-            // Linear since we are animating multiple values
-            animator.setInterpolator(new LinearInterpolator());
-            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    alpha = 1.0f - animation.getAnimatedFraction();
-                    alpha = mDisappearInterpolator.getInterpolation(alpha);
-                    radius = mAppearInterpolator.getInterpolation(animation.getAnimatedFraction());
-                    radius *= endRadius;
-                    invalidate();
-                }
-            });
-            animator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mRipples.remove(Ripple.this);
-                    updateClipping();
-                }
-
-                public void onAnimationStart(Animator animation) {
-                    mRipples.add(Ripple.this);
-                    updateClipping();
-                }
-            });
-            animator.setDuration(400);
-            animator.start();
-        }
-
-        public void draw(Canvas canvas) {
-            mRipplePaint.setAlpha((int) (alpha * 255));
-            canvas.drawCircle(x, y, radius, mRipplePaint);
-        }
-    }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
deleted file mode 100644
index 445b499..0000000
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-import android.app.ActivityOptions;
-import android.app.SearchManager;
-import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.media.AudioAttributes;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-import com.android.systemui.statusbar.BaseStatusBar;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.StatusBarPanel;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
-
-public class SearchPanelView extends FrameLayout implements StatusBarPanel {
-
-    private static final String TAG = "SearchPanelView";
-    private static final String ASSIST_ICON_METADATA_NAME =
-            "com.android.systemui.action_assist_icon";
-
-    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-            .build();
-
-    private final Context mContext;
-    private BaseStatusBar mBar;
-
-    private SearchPanelCircleView mCircle;
-    private ImageView mLogo;
-    private View mScrim;
-
-    private int mThreshold;
-    private boolean mHorizontal;
-
-    private boolean mLaunching;
-    private boolean mDragging;
-    private boolean mDraggedFarEnough;
-    private float mStartTouch;
-    private float mStartDrag;
-    private boolean mLaunchPending;
-
-    public SearchPanelView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public SearchPanelView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        mContext = context;
-        mThreshold = context.getResources().getDimensionPixelSize(R.dimen.search_panel_threshold);
-    }
-
-    private void startAssistActivity() {
-        if (!mBar.isDeviceProvisioned()) return;
-
-        // Close Recent Apps if needed
-        mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL);
-
-        final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
-        if (intent == null) return;
-
-        try {
-            final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
-                    R.anim.search_launch_enter, R.anim.search_launch_exit);
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            AsyncTask.execute(new Runnable() {
-                @Override
-                public void run() {
-                    mContext.startActivityAsUser(intent, opts.toBundle(),
-                            new UserHandle(UserHandle.USER_CURRENT));
-                }
-            });
-        } catch (ActivityNotFoundException e) {
-            Log.w(TAG, "Activity not found for " + intent.getAction());
-        }
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        mCircle = (SearchPanelCircleView) findViewById(R.id.search_panel_circle);
-        mLogo = (ImageView) findViewById(R.id.search_logo);
-        mScrim = findViewById(R.id.search_panel_scrim);
-    }
-
-    private void maybeSwapSearchIcon() {
-        Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
-        if (intent != null) {
-            ComponentName component = intent.getComponent();
-            replaceDrawable(mLogo, component, ASSIST_ICON_METADATA_NAME);
-        } else {
-            mLogo.setImageDrawable(null);
-        }
-    }
-
-    public void replaceDrawable(ImageView v, ComponentName component, String name) {
-        if (component != null) {
-            try {
-                PackageManager packageManager = mContext.getPackageManager();
-                // Look for the search icon specified in the activity meta-data
-                Bundle metaData = packageManager.getActivityInfo(
-                        component, PackageManager.GET_META_DATA).metaData;
-                if (metaData != null) {
-                    int iconResId = metaData.getInt(name);
-                    if (iconResId != 0) {
-                        Resources res = packageManager.getResourcesForActivity(component);
-                        v.setImageDrawable(res.getDrawable(iconResId));
-                        return;
-                    }
-                }
-            } catch (PackageManager.NameNotFoundException e) {
-                Log.w(TAG, "Failed to swap drawable; "
-                        + component.flattenToShortString() + " not found", e);
-            } catch (Resources.NotFoundException nfe) {
-                Log.w(TAG, "Failed to swap drawable from "
-                        + component.flattenToShortString(), nfe);
-            }
-        }
-        v.setImageDrawable(null);
-    }
-
-    @Override
-    public boolean isInContentArea(int x, int y) {
-        return true;
-    }
-
-    private void vibrate() {
-        Context context = getContext();
-        if (Settings.System.getIntForUser(context.getContentResolver(),
-                Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0) {
-            Resources res = context.getResources();
-            Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
-            vibrator.vibrate(res.getInteger(R.integer.config_search_panel_view_vibration_duration),
-                    VIBRATION_ATTRIBUTES);
-        }
-    }
-
-    public void show(final boolean show, boolean animate) {
-        if (show) {
-            maybeSwapSearchIcon();
-            if (getVisibility() != View.VISIBLE) {
-                setVisibility(View.VISIBLE);
-                vibrate();
-                if (animate) {
-                    startEnterAnimation();
-                } else {
-                    mScrim.setAlpha(1f);
-                }
-            }
-            setFocusable(true);
-            setFocusableInTouchMode(true);
-            requestFocus();
-        } else {
-            if (animate) {
-                startAbortAnimation();
-            } else {
-                setVisibility(View.INVISIBLE);
-            }
-        }
-    }
-
-    private void startEnterAnimation() {
-        mCircle.startEnterAnimation();
-        mScrim.setAlpha(0f);
-        mScrim.animate()
-                .alpha(1f)
-                .setDuration(300)
-                .setStartDelay(50)
-                .setInterpolator(PhoneStatusBar.ALPHA_IN)
-                .start();
-
-    }
-
-    private void startAbortAnimation() {
-        mCircle.startAbortAnimation(new Runnable() {
-                    @Override
-                    public void run() {
-                        mCircle.setAnimatingOut(false);
-                        setVisibility(View.INVISIBLE);
-                    }
-                });
-        mCircle.setAnimatingOut(true);
-        mScrim.animate()
-                .alpha(0f)
-                .setDuration(300)
-                .setStartDelay(0)
-                .setInterpolator(PhoneStatusBar.ALPHA_OUT);
-    }
-
-    public void hide(boolean animate) {
-        if (mBar != null) {
-            // This will indirectly cause show(false, ...) to get called
-            mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
-        } else {
-            if (animate) {
-                startAbortAnimation();
-            } else {
-                setVisibility(View.INVISIBLE);
-            }
-        }
-    }
-
-    @Override
-    public boolean dispatchHoverEvent(MotionEvent event) {
-        // Ignore hover events outside of this panel bounds since such events
-        // generate spurious accessibility events with the panel content when
-        // tapping outside of it, thus confusing the user.
-        final int x = (int) event.getX();
-        final int y = (int) event.getY();
-        if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
-            return super.dispatchHoverEvent(event);
-        }
-        return true;
-    }
-
-    /**
-     * Whether the panel is showing, or, if it's animating, whether it will be
-     * when the animation is done.
-     */
-    public boolean isShowing() {
-        return getVisibility() == View.VISIBLE && !mCircle.isAnimatingOut();
-    }
-
-    public void setBar(BaseStatusBar bar) {
-        mBar = bar;
-    }
-
-    public boolean isAssistantAvailable() {
-        return ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (mLaunching || mLaunchPending) {
-            return false;
-        }
-        int action = event.getActionMasked();
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mStartTouch = mHorizontal ? event.getX() : event.getY();
-                mDragging = false;
-                mDraggedFarEnough = false;
-                mCircle.reset();
-                break;
-            case MotionEvent.ACTION_MOVE:
-                float currentTouch = mHorizontal ? event.getX() : event.getY();
-                if (getVisibility() == View.VISIBLE && !mDragging &&
-                        (!mCircle.isAnimationRunning(true /* enterAnimation */)
-                                || Math.abs(mStartTouch - currentTouch) > mThreshold)) {
-                    mStartDrag = currentTouch;
-                    mDragging = true;
-                }
-                if (mDragging) {
-                    float offset = Math.max(mStartDrag - currentTouch, 0.0f);
-                    mCircle.setDragDistance(offset);
-                    mDraggedFarEnough = Math.abs(mStartTouch - currentTouch) > mThreshold;
-                    mCircle.setDraggedFarEnough(mDraggedFarEnough);
-                }
-                break;
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                if (mDraggedFarEnough) {
-                    if (mCircle.isAnimationRunning(true  /* enterAnimation */)) {
-                        mLaunchPending = true;
-                        mCircle.setAnimatingOut(true);
-                        mCircle.performOnAnimationFinished(new Runnable() {
-                            @Override
-                            public void run() {
-                                startExitAnimation();
-                            }
-                        });
-                    } else {
-                        startExitAnimation();
-                    }
-                } else {
-                    startAbortAnimation();
-                }
-                break;
-        }
-        return true;
-    }
-
-    private void startExitAnimation() {
-        mLaunchPending = false;
-        if (mLaunching || getVisibility() != View.VISIBLE) {
-            return;
-        }
-        mLaunching = true;
-        startAssistActivity();
-        vibrate();
-        mCircle.setAnimatingOut(true);
-        mCircle.startExitAnimation(new Runnable() {
-                    @Override
-                    public void run() {
-                        mLaunching = false;
-                        mCircle.setAnimatingOut(false);
-                        setVisibility(View.INVISIBLE);
-                    }
-                });
-        mScrim.animate()
-                .alpha(0f)
-                .setDuration(300)
-                .setStartDelay(0)
-                .setInterpolator(PhoneStatusBar.ALPHA_OUT);
-    }
-
-    public void setHorizontal(boolean horizontal) {
-        mHorizontal = horizontal;
-        mCircle.setHorizontal(horizontal);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistGestureManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistGestureManager.java
new file mode 100644
index 0000000..36be355
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistGestureManager.java
@@ -0,0 +1,292 @@
+package com.android.systemui.assist;
+
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.SearchManager;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.media.AudioAttributes;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.Vibrator;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.ImageView;
+
+import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+
+/**
+ * Class to manage everything around the assist gesture.
+ */
+public class AssistGestureManager {
+
+    private static final String TAG = "AssistGestureManager";
+    private static final String ASSIST_ICON_METADATA_NAME =
+            "com.android.systemui.action_assist_icon";
+
+    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
+            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+            .build();
+
+    private static final long TIMEOUT_SERVICE = 2500;
+    private static final long TIMEOUT_ACTIVITY = 1000;
+
+    private final Context mContext;
+    private final WindowManager mWindowManager;
+    private AssistOrbContainer mView;
+    private final PhoneStatusBar mBar;
+    private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
+
+    private IVoiceInteractionSessionShowCallback mShowCallback =
+            new IVoiceInteractionSessionShowCallback.Stub() {
+
+        @Override
+        public void onFailed() throws RemoteException {
+            mView.post(mHideRunnable);
+        }
+
+        @Override
+        public void onShown() throws RemoteException {
+            mView.post(mHideRunnable);
+        }
+    };
+
+    private Runnable mHideRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mView.removeCallbacks(this);
+            mView.show(false /* show */, true /* animate */);
+        }
+    };
+
+    public AssistGestureManager(PhoneStatusBar bar, Context context) {
+        mContext = context;
+        mBar = bar;
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mVoiceInteractionManagerService = IVoiceInteractionManagerService.Stub.asInterface(
+                ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
+    }
+
+    public void onConfigurationChanged() {
+        boolean visible = false;
+        if (mView != null) {
+            visible = mView.isShowing();
+            mWindowManager.removeView(mView);
+        }
+
+        mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
+                R.layout.assist_orb, null);
+        mView.setVisibility(View.GONE);
+        mView.setSystemUiVisibility(
+                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+        WindowManager.LayoutParams lp = getLayoutParams();
+        mWindowManager.addView(mView, lp);
+        mBar.getNavigationBarView().setDelegateView(mView);
+        if (visible) {
+            mView.show(true /* show */, false /* animate */);
+        }
+    }
+
+    public void onGestureInvoked(boolean vibrate) {
+        boolean isVoiceInteractorActive = getVoiceInteractorSupportsAssistGesture();
+        if (!isVoiceInteractorActive && !isAssistantIntentAvailable()) {
+            return;
+        }
+        if (vibrate) {
+            vibrate();
+        }
+        if (!isVoiceInteractorActive || !isVoiceSessionRunning()) {
+            showOrb();
+            mView.postDelayed(mHideRunnable, isVoiceInteractorActive
+                    ? TIMEOUT_SERVICE
+                    : TIMEOUT_ACTIVITY);
+        }
+        startAssist();
+    }
+
+    private WindowManager.LayoutParams getLayoutParams() {
+        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height),
+                WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING,
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+                PixelFormat.TRANSLUCENT);
+        if (ActivityManager.isHighEndGfx()) {
+            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        }
+        lp.gravity = Gravity.BOTTOM | Gravity.START;
+        lp.setTitle("AssistPreviewPanel");
+        lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
+                | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+        return lp;
+    }
+
+    private void showOrb() {
+        maybeSwapSearchIcon();
+        mView.show(true /* show */, true /* animate */);
+    }
+
+    private void startAssist() {
+        if (getVoiceInteractorSupportsAssistGesture()) {
+            startVoiceInteractor();
+        } else {
+            startAssistActivity();
+        }
+    }
+
+    private void startAssistActivity() {
+        if (!mBar.isDeviceProvisioned()) {
+            return;
+        }
+
+        // Close Recent Apps if needed
+        mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL |
+                CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL);
+
+        final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
+        if (intent == null) {
+            return;
+        }
+
+        try {
+            final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+                    R.anim.search_launch_enter, R.anim.search_launch_exit);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            AsyncTask.execute(new Runnable() {
+                @Override
+                public void run() {
+                    mContext.startActivityAsUser(intent, opts.toBundle(),
+                            new UserHandle(UserHandle.USER_CURRENT));
+                }
+            });
+        } catch (ActivityNotFoundException e) {
+            Log.w(TAG, "Activity not found for " + intent.getAction());
+        }
+    }
+
+    private void startVoiceInteractor() {
+        try {
+            mVoiceInteractionManagerService.showSessionForActiveService(mShowCallback);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call showSessionForActiveService", e);
+        }
+    }
+
+    private boolean getVoiceInteractorSupportsAssistGesture() {
+        try {
+            return mVoiceInteractionManagerService.activeServiceSupportsAssistGesture();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call activeServiceSupportsAssistGesture", e);
+            return false;
+        }
+    }
+
+    private ComponentName getVoiceInteractorComponentName() {
+        try {
+            return mVoiceInteractionManagerService.getActiveServiceComponentName();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call getActiveServiceComponentName", e);
+            return null;
+        }
+    }
+
+    private boolean isVoiceSessionRunning() {
+        try {
+            return mVoiceInteractionManagerService.isSessionRunning();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to call isSessionRunning", e);
+            return false;
+        }
+    }
+
+    public void destroy() {
+        mWindowManager.removeViewImmediate(mView);
+    }
+
+    private void maybeSwapSearchIcon() {
+        Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
+        ComponentName component = null;
+        boolean isService = false;
+        if (getVoiceInteractorSupportsAssistGesture()) {
+            component = getVoiceInteractorComponentName();
+            isService = true;
+        } else if (intent != null) {
+            component = intent.getComponent();
+        }
+        if (component != null) {
+            replaceDrawable(mView.getOrb().getLogo(), component, ASSIST_ICON_METADATA_NAME,
+                    isService);
+        } else {
+            mView.getOrb().getLogo().setImageDrawable(null);
+        }
+    }
+
+    public void replaceDrawable(ImageView v, ComponentName component, String name,
+            boolean isService) {
+        if (component != null) {
+            try {
+                PackageManager packageManager = mContext.getPackageManager();
+                // Look for the search icon specified in the activity meta-data
+                Bundle metaData = isService
+                        ? packageManager.getServiceInfo(
+                                component, PackageManager.GET_META_DATA).metaData
+                        : packageManager.getActivityInfo(
+                                component, PackageManager.GET_META_DATA).metaData;
+                if (metaData != null) {
+                    int iconResId = metaData.getInt(name);
+                    if (iconResId != 0) {
+                        Resources res = packageManager.getResourcesForApplication(
+                                component.getPackageName());
+                        v.setImageDrawable(res.getDrawable(iconResId));
+                        return;
+                    }
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.w(TAG, "Failed to swap drawable; "
+                        + component.flattenToShortString() + " not found", e);
+            } catch (Resources.NotFoundException nfe) {
+                Log.w(TAG, "Failed to swap drawable from "
+                        + component.flattenToShortString(), nfe);
+            }
+        }
+        v.setImageDrawable(null);
+    }
+
+    private void vibrate() {
+        if (Settings.System.getIntForUser(mContext.getContentResolver(),
+                Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0) {
+            Resources res = mContext.getResources();
+            Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
+            vibrator.vibrate(res.getInteger(R.integer.config_search_panel_view_vibration_duration),
+                    VIBRATION_ATTRIBUTES);
+        }
+    }
+
+    public boolean isAssistantIntentAvailable() {
+        return ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+                .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java
new file mode 100644
index 0000000..67017db
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java
@@ -0,0 +1,155 @@
+/*
+ * 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.assist;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
+
+import com.android.systemui.R;
+
+public class AssistOrbContainer extends FrameLayout {
+
+    private static final long EXIT_START_DELAY = 150;
+
+    private final Interpolator mLinearOutSlowInInterpolator;
+    private final Interpolator mFastOutLinearInInterpolator;
+
+    private View mScrim;
+    private View mNavbarScrim;
+    private AssistOrbView mOrb;
+
+    private boolean mAnimatingOut;
+
+    public AssistOrbContainer(Context context) {
+        this(context, null);
+    }
+
+    public AssistOrbContainer(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public AssistOrbContainer(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+                android.R.interpolator.linear_out_slow_in);
+        mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
+                android.R.interpolator.fast_out_slow_in);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mScrim = findViewById(R.id.assist_orb_scrim);
+        mNavbarScrim = findViewById(R.id.assist_orb_navbar_scrim);
+        mOrb = (AssistOrbView) findViewById(R.id.assist_orb);
+    }
+
+    public void show(final boolean show, boolean animate) {
+        if (show) {
+            if (getVisibility() != View.VISIBLE) {
+                setVisibility(View.VISIBLE);
+                if (animate) {
+                    startEnterAnimation();
+                } else {
+                    reset();
+                }
+            }
+        } else {
+            if (animate) {
+                startExitAnimation(new Runnable() {
+                    @Override
+                    public void run() {
+                        mAnimatingOut = false;
+                        setVisibility(View.GONE);
+                    }
+                });
+            } else {
+                setVisibility(View.GONE);
+            }
+        }
+    }
+
+    private void reset() {
+        mAnimatingOut = false;
+        mOrb.reset();
+        mScrim.setAlpha(1f);
+        mNavbarScrim.setAlpha(1f);
+    }
+
+    private void startEnterAnimation() {
+        if (mAnimatingOut) {
+            return;
+        }
+        mOrb.startEnterAnimation();
+        mScrim.setAlpha(0f);
+        mNavbarScrim.setAlpha(0f);
+        post(new Runnable() {
+            @Override
+            public void run() {
+                mScrim.animate()
+                        .alpha(1f)
+                        .setDuration(300)
+                        .setStartDelay(0)
+                        .setInterpolator(mLinearOutSlowInInterpolator);
+                mNavbarScrim.animate()
+                        .alpha(1f)
+                        .setDuration(300)
+                        .setStartDelay(0)
+                        .setInterpolator(mLinearOutSlowInInterpolator);
+            }
+        });
+    }
+
+    private void startExitAnimation(final Runnable endRunnable) {
+        if (mAnimatingOut) {
+            if (endRunnable != null) {
+                endRunnable.run();
+            }
+            return;
+        }
+        mAnimatingOut = true;
+        mOrb.startExitAnimation(EXIT_START_DELAY);
+        mScrim.animate()
+                .alpha(0f)
+                .setDuration(250)
+                .setStartDelay(EXIT_START_DELAY)
+                .setInterpolator(mFastOutLinearInInterpolator);
+        mNavbarScrim.animate()
+                .alpha(0f)
+                .setDuration(250)
+                .setStartDelay(EXIT_START_DELAY)
+                .setInterpolator(mFastOutLinearInInterpolator)
+                .withEndAction(endRunnable);
+    }
+
+    /**
+     * Whether the panel is showing, or, if it's animating, whether it will be
+     * when the animation is done.
+     */
+    public boolean isShowing() {
+        return getVisibility() == View.VISIBLE && !mAnimatingOut;
+    }
+
+    public AssistOrbView getOrb() {
+        return mOrb;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
new file mode 100644
index 0000000..a3372a8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.assist;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Outline;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.view.animation.OvershootInterpolator;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+
+public class AssistOrbView extends FrameLayout {
+
+    private final int mCircleMinSize;
+    private final int mBaseMargin;
+    private final int mStaticOffset;
+    private final Paint mBackgroundPaint = new Paint();
+    private final Rect mCircleRect = new Rect();
+    private final Rect mStaticRect = new Rect();
+    private final Interpolator mAppearInterpolator;
+    private final Interpolator mDisappearInterpolator;
+    private final Interpolator mOvershootInterpolator = new OvershootInterpolator();
+
+    private boolean mClipToOutline;
+    private final int mMaxElevation;
+    private float mOutlineAlpha;
+    private float mOffset;
+    private float mCircleSize;
+    private ImageView mLogo;
+    private float mCircleAnimationEndValue;
+
+    private ValueAnimator mOffsetAnimator;
+    private ValueAnimator mCircleAnimator;
+
+    private ValueAnimator.AnimatorUpdateListener mCircleUpdateListener
+            = new ValueAnimator.AnimatorUpdateListener() {
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            applyCircleSize((float) animation.getAnimatedValue());
+            updateElevation();
+        }
+    };
+    private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mCircleAnimator = null;
+        }
+    };
+    private ValueAnimator.AnimatorUpdateListener mOffsetUpdateListener
+            = new ValueAnimator.AnimatorUpdateListener() {
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            mOffset = (float) animation.getAnimatedValue();
+            updateLayout();
+        }
+    };
+
+
+    public AssistOrbView(Context context) {
+        this(context, null);
+    }
+
+    public AssistOrbView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        setOutlineProvider(new ViewOutlineProvider() {
+            @Override
+            public void getOutline(View view, Outline outline) {
+                if (mCircleSize > 0.0f) {
+                    outline.setOval(mCircleRect);
+                } else {
+                    outline.setEmpty();
+                }
+                outline.setAlpha(mOutlineAlpha);
+            }
+        });
+        setWillNotDraw(false);
+        mCircleMinSize = context.getResources().getDimensionPixelSize(
+                R.dimen.assist_orb_size);
+        mBaseMargin = context.getResources().getDimensionPixelSize(
+                R.dimen.assist_orb_base_margin);
+        mStaticOffset = context.getResources().getDimensionPixelSize(
+                R.dimen.assist_orb_travel_distance);
+        mMaxElevation = context.getResources().getDimensionPixelSize(
+                R.dimen.assist_orb_elevation);
+        mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
+                android.R.interpolator.linear_out_slow_in);
+        mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
+                android.R.interpolator.fast_out_linear_in);
+        mBackgroundPaint.setAntiAlias(true);
+        mBackgroundPaint.setColor(getResources().getColor(R.color.assist_orb_color));
+    }
+
+    public ImageView getLogo() {
+        return mLogo;
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        drawBackground(canvas);
+    }
+
+    private void drawBackground(Canvas canvas) {
+        canvas.drawCircle(mCircleRect.centerX(), mCircleRect.centerY(), mCircleSize / 2,
+                mBackgroundPaint);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mLogo = (ImageView) findViewById(R.id.search_logo);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        mLogo.layout(0, 0, mLogo.getMeasuredWidth(), mLogo.getMeasuredHeight());
+        if (changed) {
+            updateCircleRect(mStaticRect, mStaticOffset, true);
+        }
+    }
+
+    public void animateCircleSize(float circleSize, long duration,
+            long startDelay, Interpolator interpolator) {
+        if (circleSize == mCircleAnimationEndValue) {
+            return;
+        }
+        if (mCircleAnimator != null) {
+            mCircleAnimator.cancel();
+        }
+        mCircleAnimator = ValueAnimator.ofFloat(mCircleSize, circleSize);
+        mCircleAnimator.addUpdateListener(mCircleUpdateListener);
+        mCircleAnimator.addListener(mClearAnimatorListener);
+        mCircleAnimator.setInterpolator(interpolator);
+        mCircleAnimator.setDuration(duration);
+        mCircleAnimator.setStartDelay(startDelay);
+        mCircleAnimator.start();
+        mCircleAnimationEndValue = circleSize;
+    }
+
+    private void applyCircleSize(float circleSize) {
+        mCircleSize = circleSize;
+        updateLayout();
+    }
+
+    private void updateElevation() {
+        float t = (mStaticOffset - mOffset) / (float) mStaticOffset;
+        t = 1.0f - Math.max(t, 0.0f);
+        float offset = t * mMaxElevation;
+        setElevation(offset);
+    }
+
+    /**
+     * Animates the offset to the edge of the screen.
+     *
+     * @param offset The offset to apply.
+     * @param startDelay The desired start delay if animated.
+     *
+     * @param interpolator The desired interpolator if animated. If null,
+     *                     a default interpolator will be taken designed for appearing or
+     *                     disappearing.
+     */
+    private void animateOffset(float offset, long duration, long startDelay,
+            Interpolator interpolator) {
+        if (mOffsetAnimator != null) {
+            mOffsetAnimator.removeAllListeners();
+            mOffsetAnimator.cancel();
+        }
+        mOffsetAnimator = ValueAnimator.ofFloat(mOffset, offset);
+        mOffsetAnimator.addUpdateListener(mOffsetUpdateListener);
+        mOffsetAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mOffsetAnimator = null;
+            }
+        });
+        mOffsetAnimator.setInterpolator(interpolator);
+        mOffsetAnimator.setStartDelay(startDelay);
+        mOffsetAnimator.setDuration(duration);
+        mOffsetAnimator.start();
+    }
+
+    private void updateLayout() {
+        updateCircleRect();
+        updateLogo();
+        invalidateOutline();
+        invalidate();
+        updateClipping();
+    }
+
+    private void updateClipping() {
+        boolean clip = mCircleSize < mCircleMinSize;
+        if (clip != mClipToOutline) {
+            setClipToOutline(clip);
+            mClipToOutline = clip;
+        }
+    }
+
+    private void updateLogo() {
+        float translationX = (mCircleRect.left + mCircleRect.right) / 2.0f - mLogo.getWidth() / 2.0f;
+        float translationY = (mCircleRect.top + mCircleRect.bottom) / 2.0f
+                - mLogo.getHeight() / 2.0f - mCircleMinSize / 7f;
+        float t = (mStaticOffset - mOffset) / (float) mStaticOffset;
+        translationY += t * mStaticOffset * 0.1f;
+        float alpha = 1.0f-t;
+        alpha = Math.max((alpha - 0.5f) * 2.0f, 0);
+        mLogo.setImageAlpha((int) (alpha * 255));
+        mLogo.setTranslationX(translationX);
+        mLogo.setTranslationY(translationY);
+    }
+
+    private void updateCircleRect() {
+        updateCircleRect(mCircleRect, mOffset, false);
+    }
+
+    private void updateCircleRect(Rect rect, float offset, boolean useStaticSize) {
+        int left, top;
+        float circleSize = useStaticSize ? mCircleMinSize : mCircleSize;
+        left = (int) (getWidth() - circleSize) / 2;
+        top = (int) (getHeight() - circleSize / 2 - mBaseMargin - offset);
+        rect.set(left, top, (int) (left + circleSize), (int) (top + circleSize));
+    }
+
+    public void startExitAnimation(long delay) {
+        animateCircleSize(0, 200, delay, mDisappearInterpolator);
+        animateOffset(0, 200, delay, mDisappearInterpolator);
+    }
+
+    public void startEnterAnimation() {
+        applyCircleSize(0);
+        post(new Runnable() {
+            @Override
+            public void run() {
+                animateCircleSize(mCircleMinSize, 300, 0 /* delay */, mOvershootInterpolator);
+                animateOffset(mStaticOffset, 400, 0 /* delay */, mAppearInterpolator);
+            }
+        });
+    }
+
+    public void reset() {
+        mClipToOutline = false;
+        mBackgroundPaint.setAlpha(255);
+        mOutlineAlpha = 1.0f;
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        // not really true but it's ok during an animation, as it's never permanent
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 275a6be..dd28734 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -436,7 +436,8 @@
             }
         }
 
-        public void onFingerprintRecognized(int userId) {
+        @Override
+        public void onFingerprintAuthenticated(int userId) {
             if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                 mViewMediatorCallback.keyguardDone(true);
             } else {
@@ -636,7 +637,7 @@
                 doKeyguardLocked(null);
             }
         }
-        KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurndOff(why);
+        KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurnedOff(why);
     }
 
     private void doKeyguardLaterLocked() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 2dd02a5..2bc31fc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -72,7 +72,7 @@
         final boolean airplaneMode = value != 0;
         state.value = airplaneMode;
         state.visible = true;
-        state.label = mContext.getString(R.string.quick_settings_airplane_mode_label);
+        state.label = mContext.getString(R.string.airplane_mode);
         if (airplaneMode) {
             state.icon = mEnable;
             state.contentDescription =  mContext.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 79600f5..64730c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.view.LayoutInflater;
@@ -40,31 +41,37 @@
     private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE";
     private static final String EXTRA_VISIBLE = "visible";
     private static final String PREF_KEY_VISIBLE = "DndTileVisible";
+    private static final String PREF_KEY_COMBINED_ICON = "DndTileCombinedIcon";
 
     private final ZenModeController mController;
     private final DndDetailAdapter mDetailAdapter;
 
     private boolean mListening;
-    private boolean mVisible;
     private boolean mShowingDetail;
 
     public DndTile(Host host) {
         super(host);
         mController = host.getZenModeController();
         mDetailAdapter = new DndDetailAdapter();
-        mVisible = getSharedPrefs(mContext).getBoolean(PREF_KEY_VISIBLE, false);
         mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
     }
 
     public static void setVisible(Context context, boolean visible) {
-        context.sendBroadcast(new Intent(DndTile.ACTION_SET_VISIBLE)
-                .putExtra(DndTile.EXTRA_VISIBLE, visible));
+        getSharedPrefs(context).edit().putBoolean(PREF_KEY_VISIBLE, visible).commit();
     }
 
     public static boolean isVisible(Context context) {
         return getSharedPrefs(context).getBoolean(PREF_KEY_VISIBLE, false);
     }
 
+    public static void setCombinedIcon(Context context, boolean combined) {
+        getSharedPrefs(context).edit().putBoolean(PREF_KEY_COMBINED_ICON, combined).commit();
+    }
+
+    public static boolean isCombinedIcon(Context context) {
+        return getSharedPrefs(context).getBoolean(PREF_KEY_COMBINED_ICON, false);
+    }
+
     @Override
     public DetailAdapter getDetailAdapter() {
         return mDetailAdapter;
@@ -89,7 +96,7 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
         state.value = zen != Global.ZEN_MODE_OFF;
-        state.visible = mVisible;
+        state.visible = isVisible(mContext);
         switch (zen) {
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
                 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
@@ -103,6 +110,12 @@
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_quick_settings_dnd_none_on);
                 break;
+            case Global.ZEN_MODE_ALARMS:
+                state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
+                state.label = mContext.getString(R.string.quick_settings_dnd_alarms_label);
+                state.contentDescription = mContext.getString(
+                        R.string.accessibility_quick_settings_dnd_alarms_on);
+                break;
             default:
                 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_off);
                 state.label = mContext.getString(R.string.quick_settings_dnd_label);
@@ -130,26 +143,38 @@
         mListening = listening;
         if (mListening) {
             mController.addCallback(mZenCallback);
+            getSharedPrefs(mContext).registerOnSharedPreferenceChangeListener(mPrefListener);
         } else {
             mController.removeCallback(mZenCallback);
+            getSharedPrefs(mContext).unregisterOnSharedPreferenceChangeListener(mPrefListener);
         }
     }
 
+    private static SharedPreferences getSharedPrefs(Context context) {
+        return context.getSharedPreferences(context.getPackageName(), 0);
+    }
+
+    private final OnSharedPreferenceChangeListener mPrefListener
+            = new OnSharedPreferenceChangeListener() {
+        @Override
+        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+            if (PREF_KEY_COMBINED_ICON.equals(key) || PREF_KEY_VISIBLE.equals(key)) {
+                refreshState();
+            }
+        }
+    };
+
     private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
         public void onZenChanged(int zen) {
             refreshState(zen);
         }
     };
 
-    private static SharedPreferences getSharedPrefs(Context context) {
-        return context.getSharedPreferences(context.getPackageName(), 0);
-    }
-
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            mVisible = intent.getBooleanExtra(EXTRA_VISIBLE, false);
-            getSharedPrefs(mContext).edit().putBoolean(PREF_KEY_VISIBLE, mVisible).commit();
+            final boolean visible = intent.getBooleanExtra(EXTRA_VISIBLE, false);
+            setVisible(mContext, visible);
             refreshState();
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 5c1a317..cb78deb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -17,7 +17,6 @@
 package com.android.systemui.qs.tiles;
 
 import android.app.ActivityManager;
-import android.os.SystemClock;
 
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
@@ -27,16 +26,11 @@
 public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
         FlashlightController.FlashlightListener {
 
-    /** Grace period for which we consider the flashlight
-     * still available because it was recently on. */
-    private static final long RECENTLY_ON_DURATION_MILLIS = 500;
-
     private final AnimationIcon mEnable
             = new AnimationIcon(R.drawable.ic_signal_flashlight_enable_animation);
     private final AnimationIcon mDisable
             = new AnimationIcon(R.drawable.ic_signal_flashlight_disable_animation);
     private final FlashlightController mFlashlightController;
-    private long mWasLastOn;
 
     public FlashlightTile(Host host) {
         super(host);
@@ -69,33 +63,17 @@
             return;
         }
         boolean newState = !mState.value;
-        mFlashlightController.setFlashlight(newState);
         refreshState(newState ? UserBoolean.USER_TRUE : UserBoolean.USER_FALSE);
+        mFlashlightController.setFlashlight(newState);
     }
 
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
-        if (state.value) {
-            mWasLastOn = SystemClock.uptimeMillis();
-        }
-
+        state.visible = mFlashlightController.isAvailable();
+        state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
         if (arg instanceof UserBoolean) {
             state.value = ((UserBoolean) arg).value;
         }
-
-        if (!state.value && mWasLastOn != 0) {
-            if (SystemClock.uptimeMillis() > mWasLastOn + RECENTLY_ON_DURATION_MILLIS) {
-                mWasLastOn = 0;
-            } else {
-                mHandler.removeCallbacks(mRecentlyOnTimeout);
-                mHandler.postAtTime(mRecentlyOnTimeout, mWasLastOn + RECENTLY_ON_DURATION_MILLIS);
-            }
-        }
-
-        // Always show the tile when the flashlight is or was recently on. This is needed because
-        // the camera is not available while it is being used for the flashlight.
-        state.visible = mWasLastOn != 0 || mFlashlightController.isAvailable();
-        state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
         final AnimationIcon icon = state.value ? mEnable : mDisable;
         icon.setAllowAnimation(arg instanceof UserBoolean && ((UserBoolean) arg).userInitiated);
         state.icon = icon;
@@ -115,8 +93,8 @@
     }
 
     @Override
-    public void onFlashlightOff() {
-        refreshState(UserBoolean.BACKGROUND_FALSE);
+    public void onFlashlightChanged(boolean enabled) {
+        refreshState(enabled ? UserBoolean.BACKGROUND_TRUE : UserBoolean.BACKGROUND_FALSE);
     }
 
     @Override
@@ -128,11 +106,4 @@
     public void onFlashlightAvailabilityChanged(boolean available) {
         refreshState();
     }
-
-    private Runnable mRecentlyOnTimeout = new Runnable() {
-        @Override
-        public void run() {
-            refreshState();
-        }
-    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index f014f09..011c02e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -19,7 +19,6 @@
 import android.app.Activity;
 import android.app.ActivityOptions;
 import android.app.SearchManager;
-import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.BroadcastReceiver;
@@ -35,7 +34,6 @@
 import android.view.View;
 import android.view.ViewStub;
 import android.widget.Toast;
-
 import com.android.systemui.R;
 import com.android.systemui.recents.misc.DebugTrigger;
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
@@ -49,8 +47,6 @@
 import com.android.systemui.recents.views.RecentsView;
 import com.android.systemui.recents.views.SystemBarScrimViews;
 import com.android.systemui.recents.views.ViewAnimation;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
-import com.android.systemui.SystemUIApplication;
 
 import java.lang.ref.WeakReference;
 import java.lang.reflect.InvocationTargetException;
@@ -78,9 +74,9 @@
     RecentsResizeTaskDialog mResizeTaskDebugDialog;
 
     // Search AppWidget
-    RecentsAppWidgetHost mAppWidgetHost;
     AppWidgetProviderInfo mSearchAppWidgetInfo;
-    AppWidgetHostView mSearchAppWidgetHostView;
+    RecentsAppWidgetHost mAppWidgetHost;
+    RecentsAppWidgetHostView mSearchAppWidgetHostView;
 
     // Runnables to finish the Recents activity
     FinishRecentsRunnable mFinishLaunchHomeRunnable;
@@ -245,7 +241,7 @@
             if (mEmptyView != null) {
                 mEmptyView.setVisibility(View.GONE);
             }
-            if (mRecentsView.hasSearchBar()) {
+            if (mRecentsView.hasValidSearchBar()) {
                 mRecentsView.setSearchBarVisibility(View.VISIBLE);
             } else {
                 addSearchBarAppWidgetView();
@@ -295,8 +291,8 @@
         if (Constants.DebugFlags.App.EnableSearchLayout) {
             int appWidgetId = mConfig.searchBarAppWidgetId;
             if (appWidgetId >= 0) {
-                mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
-                        mSearchAppWidgetInfo);
+                mSearchAppWidgetHostView = (RecentsAppWidgetHostView) mAppWidgetHost.createView(
+                        this, appWidgetId, mSearchAppWidgetInfo);
                 Bundle opts = new Bundle();
                 opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
                         AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
@@ -345,6 +341,12 @@
         }
     }
 
+    /** Dismisses Recents directly to Home without transition animation. */
+    void dismissRecentsToHomeWithoutTransitionAnimation() {
+        finish();
+        overridePendingTransition(0, 0);
+    }
+
     /** Dismisses Recents directly to Home if we currently aren't transitioning. */
     boolean dismissRecentsToHome(boolean animated) {
         SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
index 5bae37a..02a7b94 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents;
 
 import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
 import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -61,6 +62,12 @@
     }
 
     @Override
+    protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
+                                             AppWidgetProviderInfo appWidget) {
+        return new RecentsAppWidgetHostView(context);
+    }
+
+    @Override
     protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
         if (mCb == null) return;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHostView.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHostView.java
new file mode 100644
index 0000000..1ed755a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHostView.java
@@ -0,0 +1,59 @@
+/*
+ * 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.recents;
+
+import android.appwidget.AppWidgetHostView;
+import android.content.Context;
+import android.widget.RemoteViews;
+
+public class RecentsAppWidgetHostView extends AppWidgetHostView {
+
+    private Context mContext;
+    private int mPreviousOrientation;
+
+    public RecentsAppWidgetHostView(Context context) {
+        super(context);
+        mContext = context;
+    }
+
+    @Override
+    public void updateAppWidget(RemoteViews remoteViews) {
+        // Store the orientation in which the widget was inflated
+        updateLastInflationOrientation();
+        super.updateAppWidget(remoteViews);
+    }
+
+    /**
+     * Updates the last orientation that this widget was inflated.
+     */
+    private void updateLastInflationOrientation() {
+        mPreviousOrientation = mContext.getResources().getConfiguration().orientation;
+    }
+
+    /**
+     * @return whether the search widget was updated while Recents was in a different orientation
+     *         in the background.
+     */
+    public boolean isReinflateRequired() {
+        // Re-inflate is required if the orientation has changed since last inflated.
+        int orientation = mContext.getResources().getConfiguration().orientation;
+        if (mPreviousOrientation != orientation) {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
index 7c11894..b701e0b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
@@ -24,6 +24,7 @@
 import android.content.DialogInterface;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.Button;
@@ -34,6 +35,8 @@
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.views.RecentsView;
 
+import java.util.ArrayList;
+
 /**
  * A helper for the dialogs that show when task debugging is on.
  */
@@ -46,16 +49,32 @@
     private static final int PLACE_RIGHT = 2;
     private static final int PLACE_TOP = 3;
     private static final int PLACE_BOTTOM = 4;
-    private static final int PLACE_FULL = 5;
+    private static final int PLACE_TOP_LEFT = 5;
+    private static final int PLACE_TOP_RIGHT = 6;
+    private static final int PLACE_BOTTOM_LEFT = 7;
+    private static final int PLACE_BOTTOM_RIGHT = 8;
+    private static final int PLACE_FULL = 9;
+
+    // The button resource ID combined with the arrangement command.
+    private static final int[][] BUTTON_DEFINITIONS =
+           {{R.id.place_left, PLACE_LEFT},
+            {R.id.place_right, PLACE_RIGHT},
+            {R.id.place_top, PLACE_TOP},
+            {R.id.place_bottom, PLACE_BOTTOM},
+            {R.id.place_top_left, PLACE_TOP_LEFT},
+            {R.id.place_top_right, PLACE_TOP_RIGHT},
+            {R.id.place_bottom_left, PLACE_BOTTOM_LEFT},
+            {R.id.place_bottom_right, PLACE_BOTTOM_RIGHT},
+            {R.id.place_full, PLACE_FULL}};
 
     // The task we want to resize.
-    private Task mTaskToResize;
-    private Task mNextTaskToResize;
     private FragmentManager mFragmentManager;
     private View mResizeTaskDialogContent;
     private RecentsActivity mRecentsActivity;
     private RecentsView mRecentsView;
     private SystemServicesProxy mSsp;
+    private Rect[] mBounds = {new Rect(), new Rect(), new Rect(), new Rect()};
+    private Task[] mTasks = {null, null, null, null};
 
     public RecentsResizeTaskDialog(FragmentManager mgr, RecentsActivity activity) {
         mFragmentManager = mgr;
@@ -65,9 +84,8 @@
 
     /** Shows the resize-task dialog. */
     void showResizeTaskDialog(Task mainTask, RecentsView rv) {
-        mTaskToResize = mainTask;
+        mTasks[0] = mainTask;
         mRecentsView = rv;
-        mNextTaskToResize = mRecentsView.getNextTaskOrTopTask(mainTask);
 
         show(mFragmentManager, TAG);
     }
@@ -79,36 +97,18 @@
         mResizeTaskDialogContent =
                 inflater.inflate(R.layout.recents_task_resize_dialog, null, false);
 
-        ((Button)mResizeTaskDialogContent.findViewById(R.id.place_left)).setOnClickListener(
-                new View.OnClickListener() {
-            public void onClick(View v) {
-                placeTasks(PLACE_LEFT);
+        for (int i = 0; i < BUTTON_DEFINITIONS.length; i++) {
+            Button b = (Button)mResizeTaskDialogContent.findViewById(BUTTON_DEFINITIONS[i][0]);
+            if (b != null) {
+                final int action = BUTTON_DEFINITIONS[i][1];
+                b.setOnClickListener(
+                        new View.OnClickListener() {
+                            public void onClick(View v) {
+                                placeTasks(action);
+                            }
+                        });
             }
-        });
-        ((Button)mResizeTaskDialogContent.findViewById(R.id.place_right)).setOnClickListener(
-                new View.OnClickListener() {
-            public void onClick(View v) {
-                placeTasks(PLACE_RIGHT);
-            }
-        });
-        ((Button)mResizeTaskDialogContent.findViewById(R.id.place_top)).setOnClickListener(
-                new View.OnClickListener() {
-            public void onClick(View v) {
-                placeTasks(PLACE_TOP);
-            }
-        });
-        ((Button)mResizeTaskDialogContent.findViewById(R.id.place_bottom)).setOnClickListener(
-                new View.OnClickListener() {
-            public void onClick(View v) {
-                placeTasks(PLACE_BOTTOM);
-            }
-        });
-        ((Button)mResizeTaskDialogContent.findViewById(R.id.place_full)).setOnClickListener(
-                new View.OnClickListener() {
-            public void onClick(View v) {
-                placeTasks(PLACE_FULL);
-            }
-        });
+        }
 
         builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
             @Override
@@ -122,48 +122,111 @@
 
     /** Helper function to place window(s) on the display according to an arrangement request. */
     private void placeTasks(int arrangement) {
-        Rect focusedBounds = mSsp.getWindowRect();
-        Rect otherBounds = new Rect(focusedBounds);
-
+        Rect rect = mSsp.getWindowRect();
+        for (int i = 0; i < mBounds.length; ++i) {
+            mBounds[i].set(rect);
+            if (i != 0) {
+                mTasks[i] = null;
+            }
+        }
+        int additionalTasks = 0;
         switch (arrangement) {
             case PLACE_LEFT:
-                focusedBounds.right = focusedBounds.centerX();
-                otherBounds.left = focusedBounds.right;
+                mBounds[0].right = mBounds[0].centerX();
+                mBounds[1].left = mBounds[0].right;
+                additionalTasks = 1;
                 break;
             case PLACE_RIGHT:
-                otherBounds.right = otherBounds.centerX();
-                focusedBounds.left = otherBounds.right;
+                mBounds[1].right = mBounds[1].centerX();
+                mBounds[0].left = mBounds[1].right;
+                additionalTasks = 1;
                 break;
             case PLACE_TOP:
-                focusedBounds.bottom = focusedBounds.centerY();
-                otherBounds.top = focusedBounds.bottom;
+                mBounds[0].bottom = mBounds[0].centerY();
+                mBounds[1].top = mBounds[0].bottom;
+                additionalTasks = 1;
                 break;
             case PLACE_BOTTOM:
-                otherBounds.bottom = otherBounds.centerY();
-                focusedBounds.top = otherBounds.bottom;
+                mBounds[1].bottom = mBounds[1].centerY();
+                mBounds[0].top = mBounds[1].bottom;
+                additionalTasks = 1;
+                break;
+            case PLACE_TOP_LEFT:  // TL, TR, BL, BR
+                mBounds[0].right = mBounds[0].centerX();
+                mBounds[0].bottom = mBounds[0].centerY();
+                mBounds[1].left = mBounds[0].right;
+                mBounds[1].bottom = mBounds[0].bottom;
+                mBounds[2].right = mBounds[0].right;
+                mBounds[2].top = mBounds[0].bottom;
+                mBounds[3].left = mBounds[0].right;
+                mBounds[3].top = mBounds[0].bottom;
+                additionalTasks = 3;
+                break;
+            case PLACE_TOP_RIGHT:  // TR, TL, BR, BL
+                mBounds[0].left = mBounds[0].centerX();
+                mBounds[0].bottom = mBounds[0].centerY();
+                mBounds[1].right = mBounds[0].left;
+                mBounds[1].bottom = mBounds[0].bottom;
+                mBounds[2].left = mBounds[0].left;
+                mBounds[2].top = mBounds[0].bottom;
+                mBounds[3].right = mBounds[0].left;
+                mBounds[3].top = mBounds[0].bottom;
+                additionalTasks = 3;
+                break;
+            case PLACE_BOTTOM_LEFT:  // BL, BR, TL, TR
+                mBounds[0].right = mBounds[0].centerX();
+                mBounds[0].top = mBounds[0].centerY();
+                mBounds[1].left = mBounds[0].right;
+                mBounds[1].top = mBounds[0].top;
+                mBounds[2].right = mBounds[0].right;
+                mBounds[2].bottom = mBounds[0].top;
+                mBounds[3].left = mBounds[0].right;
+                mBounds[3].bottom = mBounds[0].top;
+                additionalTasks = 3;
+                break;
+            case PLACE_BOTTOM_RIGHT:  // BR, BL, TR, TL
+                mBounds[0].left = mBounds[0].centerX();
+                mBounds[0].top = mBounds[0].centerY();
+                mBounds[1].right = mBounds[0].left;
+                mBounds[1].top = mBounds[0].top;
+                mBounds[2].left = mBounds[0].left;
+                mBounds[2].bottom = mBounds[0].top;
+                mBounds[3].right = mBounds[0].left;
+                mBounds[3].bottom = mBounds[0].top;
+                additionalTasks = 3;
                 break;
             case PLACE_FULL:
-                // Null the rectangle to avoid the other task to show up.
-                otherBounds = new Rect();
+                // Nothing to change.
                 break;
         }
 
-        // Resize all other tasks to go to the other side.
-        if (mNextTaskToResize != null && !otherBounds.isEmpty()) {
-            mSsp.resizeTask(mNextTaskToResize.key.id, otherBounds);
+        // Get the other tasks.
+        for (int i = 1; i <= additionalTasks && mTasks[i - 1] != null; ++i) {
+            mTasks[i] = mRecentsView.getNextTaskOrTopTask(mTasks[i - 1]);
+            // Do stop if we circled back to the first item.
+            if (mTasks[i] == mTasks[0]) {
+                mTasks[i] = null;
+            }
         }
-        mSsp.resizeTask(mTaskToResize.key.id, focusedBounds);
 
         // Get rid of the dialog.
         dismiss();
-        mRecentsActivity.dismissRecentsToHomeRaw(false);
+        mRecentsActivity.dismissRecentsToHomeWithoutTransitionAnimation();
 
-        // Show tasks - beginning with the other first so that the focus ends on the selected one.
-        // TODO: Remove this once issue b/19893373 is resolved.
-        if (mNextTaskToResize != null && !otherBounds.isEmpty()) {
-            mRecentsView.launchTask(mNextTaskToResize);
+        // Resize all tasks beginning from the "oldest" one.
+        for (int i = additionalTasks; i >= 0; --i) {
+            if (mTasks[i] != null) {
+               mSsp.resizeTask(mTasks[i].key.id, mBounds[i]);
+            }
         }
-        mRecentsView.launchTask(mTaskToResize);
+
+        // Show tasks as they might not be currently visible - beginning with the oldest so that
+        // the focus ends on the selected one.
+        for (int i = additionalTasks; i >= 0; --i) {
+            if (mTasks[i] != null) {
+                mRecentsView.launchTask(mTasks[i]);
+            }
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index abed7a5..1377975 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -34,6 +34,7 @@
 import android.widget.FrameLayout;
 import com.android.systemui.R;
 import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.RecentsAppWidgetHostView;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.RecentsPackageMonitor;
@@ -69,7 +70,7 @@
 
     ArrayList<TaskStack> mStacks;
     List<TaskStackView> mTaskStackViews = new ArrayList<>();
-    View mSearchBar;
+    RecentsAppWidgetHostView mSearchBar;
     RecentsViewCallbacks mCb;
 
     public RecentsView(Context context) {
@@ -278,7 +279,7 @@
     }
 
     /** Adds the search bar */
-    public void setSearchBar(View searchBar) {
+    public void setSearchBar(RecentsAppWidgetHostView searchBar) {
         // Create the search bar (and hide it if we have no recent tasks)
         if (Constants.DebugFlags.App.EnableSearchLayout) {
             // Remove the previous search bar if one exists
@@ -294,8 +295,8 @@
     }
 
     /** Returns whether there is currently a search bar */
-    public boolean hasSearchBar() {
-        return mSearchBar != null;
+    public boolean hasValidSearchBar() {
+        return mSearchBar != null && !mSearchBar.isReinflateRequired();
     }
 
     /** Sets the visibility of the search bar */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index e81a1d0..3a97a41 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -815,7 +815,9 @@
         }
 
         // Start dozing
-        mUIDozeTrigger.startDozing();
+        if (!mConfig.multiStackEnabled) {
+            mUIDozeTrigger.startDozing();
+        }
     }
 
     /** Requests this task stacks to start it's enter-recents animation */
@@ -1219,7 +1221,7 @@
         RecentsTaskLoader.getInstance().loadTaskData(task);
 
         // If the doze trigger has already fired, then update the state for this task view
-        if (mUIDozeTrigger.hasTriggered()) {
+        if (mConfig.multiStackEnabled || mUIDozeTrigger.hasTriggered()) {
             tv.setNoUserInteractionState();
         }
 
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 42399a3..60a91bf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -191,10 +191,7 @@
             mApplicationIcon.setImageDrawable(t.applicationIcon);
         }
         mApplicationIcon.setContentDescription(t.activityLabel);
-        // Always update when multi stack debugging is enabled as the stack id can change
-        if (mConfig.multiStackEnabled) {
-            mActivityDescription.setText("[" + t.key.stackId + "] " + t.activityLabel);
-        } else if (!mActivityDescription.getText().toString().equals(t.activityLabel)) {
+        if (!mActivityDescription.getText().toString().equals(t.activityLabel)) {
             mActivityDescription.setText(t.activityLabel);
         }
         // Try and apply the system ui tint
@@ -212,6 +209,9 @@
         mDismissButton.setContentDescription(String.format(mDismissContentDescription,
                 t.activityLabel));
         mMoveTaskButton.setVisibility((mConfig.multiStackEnabled) ? View.VISIBLE : View.INVISIBLE);
+        if (mConfig.multiStackEnabled) {
+            updateResizeTaskBarIcon(t);
+        }
     }
 
     /** Updates the resize task bar button. */
@@ -219,7 +219,7 @@
         Rect display = mSsp.getWindowRect();
         Rect taskRect = mSsp.getTaskBounds(t.key.stackId);
         int resId = R.drawable.star;
-        if (display.equals(taskRect)) {
+        if (display.equals(taskRect) || taskRect.isEmpty()) {
             resId = R.drawable.vector_drawable_place_fullscreen;
         } else {
             boolean top = display.top == taskRect.top;
@@ -234,6 +234,14 @@
                 resId = R.drawable.vector_drawable_place_top;
             } else if (bottom && left && right) {
                 resId = R.drawable.vector_drawable_place_bottom;
+            } else if (top && right) {
+                resId = R.drawable.vector_drawable_place_top_right;
+            } else if (top && left) {
+                resId = R.drawable.vector_drawable_place_top_left;
+            } else if (bottom && right) {
+                resId = R.drawable.vector_drawable_place_bottom_right;
+            } else if (bottom && left) {
+                resId = R.drawable.vector_drawable_place_bottom_left;
             }
         }
         mMoveTaskButton.setImageResource(resId);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index bba7682..a55e026 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -132,6 +132,8 @@
 
     /** Reset the transform on a view. */
     public static void reset(View v) {
+        // Cancel any running animations
+        v.animate().cancel();
         v.setTranslationX(0f);
         v.setTranslationY(0f);
         v.setTranslationZ(0f);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 9d349ab..105bf0f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -122,7 +122,7 @@
 
         // Prepare all the output metadata
         mImageTime = System.currentTimeMillis();
-        String imageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(mImageTime));
+        String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
         mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
 
         mScreenshotDir = new File(Environment.getExternalStoragePublicDirectory(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 55bdcac..f75dd73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -71,7 +71,6 @@
 import android.view.View;
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.view.ViewParent;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
@@ -79,7 +78,6 @@
 import android.view.animation.AnimationUtils;
 import android.widget.DateTimeView;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.RemoteViews;
 import android.widget.TextView;
 
@@ -90,7 +88,6 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
-import com.android.systemui.SearchPanelView;
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.SystemUI;
 import com.android.systemui.recents.Recents;
@@ -132,7 +129,6 @@
     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_CLOSE_SEARCH_PANEL = 1027;
     protected static final int MSG_SHOW_HEADS_UP = 1028;
     protected static final int MSG_HIDE_HEADS_UP = 1029;
     protected static final int MSG_ESCALATE_HEADS_UP = 1030;
@@ -164,9 +160,6 @@
     protected HeadsUpNotificationView mHeadsUpNotificationView;
     protected int mHeadsUpNotificationDecay;
 
-    // Search panel
-    protected SearchPanelView mSearchPanelView;
-
     protected int mCurrentUserId = 0;
     final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
 
@@ -1043,50 +1036,6 @@
         mHandler.sendEmptyMessage(msg);
     }
 
-    @Override
-    public void showSearchPanel() {
-        if (mSearchPanelView != null && mSearchPanelView.isAssistantAvailable()) {
-            mSearchPanelView.show(true, true);
-        }
-    }
-
-    @Override
-    public void hideSearchPanel() {
-        int msg = MSG_CLOSE_SEARCH_PANEL;
-        mHandler.removeMessages(msg);
-        mHandler.sendEmptyMessage(msg);
-    }
-
-    protected abstract WindowManager.LayoutParams getSearchLayoutParams(
-            LayoutParams layoutParams);
-
-    protected void updateSearchPanel() {
-        // Search Panel
-        boolean visible = false;
-        if (mSearchPanelView != null) {
-            visible = mSearchPanelView.isShowing();
-            mWindowManager.removeView(mSearchPanelView);
-        }
-
-        // Provide SearchPanel with a temporary parent to allow layout params to work.
-        LinearLayout tmpRoot = new LinearLayout(mContext);
-        mSearchPanelView = (SearchPanelView) LayoutInflater.from(mContext).inflate(
-                 R.layout.status_bar_search_panel, tmpRoot, false);
-        mSearchPanelView.setOnTouchListener(
-                 new TouchOutsideListener(MSG_CLOSE_SEARCH_PANEL, mSearchPanelView));
-        mSearchPanelView.setVisibility(View.GONE);
-        boolean vertical = mNavigationBarView != null && mNavigationBarView.isVertical();
-        mSearchPanelView.setHorizontal(vertical);
-
-        WindowManager.LayoutParams lp = getSearchLayoutParams(mSearchPanelView.getLayoutParams());
-
-        mWindowManager.addView(mSearchPanelView, lp);
-        mSearchPanelView.setBar(this);
-        if (visible) {
-            mSearchPanelView.show(true, false);
-        }
-    }
-
     protected H createHandler() {
          return new H();
     }
@@ -1263,38 +1212,10 @@
              case MSG_SHOW_PREV_AFFILIATED_TASK:
                   showRecentsPreviousAffiliatedTask();
                   break;
-             case MSG_CLOSE_SEARCH_PANEL:
-                 if (DEBUG) Log.d(TAG, "closing search panel");
-                 if (mSearchPanelView != null && mSearchPanelView.isShowing()) {
-                     mSearchPanelView.show(false, true);
-                 }
-                 break;
             }
         }
     }
 
-    public class TouchOutsideListener implements View.OnTouchListener {
-        private int mMsg;
-        private StatusBarPanel mPanel;
-
-        public TouchOutsideListener(int msg, StatusBarPanel panel) {
-            mMsg = msg;
-            mPanel = panel;
-        }
-
-        public boolean onTouch(View v, MotionEvent ev) {
-            final int action = ev.getAction();
-            if (action == MotionEvent.ACTION_OUTSIDE
-                || (action == MotionEvent.ACTION_DOWN
-                    && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) {
-                mHandler.removeMessages(mMsg);
-                mHandler.sendEmptyMessage(mMsg);
-                return true;
-            }
-            return false;
-        }
-    }
-
     protected void workAroundBadLayerDrawableOpacity(View v) {
     }
 
@@ -1935,7 +1856,7 @@
 
     protected abstract void setAreThereNotifications();
     protected abstract void updateNotifications();
-    protected abstract boolean shouldDisableNavbarGestures();
+    public abstract boolean shouldDisableNavbarGestures();
 
     public abstract void addNotification(StatusBarNotification notification,
             RankingMap ranking, Entry oldEntry);
@@ -2241,9 +2162,6 @@
     }
 
     public void destroy() {
-        if (mSearchPanelView != null) {
-            mWindowManager.removeViewImmediate(mSearchPanelView);
-        }
         mContext.unregisterReceiver(mBroadcastReceiver);
         try {
             mNotificationListener.unregisterAsSystemService();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 8f88e73d..7aa9a90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -96,8 +96,6 @@
         public void toggleRecentApps();
         public void preloadRecentApps();
         public void cancelPreloadRecentApps();
-        public void showSearchPanel();
-        public void hideSearchPanel();
         public void setWindowState(int window, int state);
         public void buzzBeepBlinked();
         public void notificationLightOff();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
index 7ae6764..9e2207e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
@@ -22,11 +22,12 @@
 import android.view.MotionEvent;
 import android.view.View;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
 
 public class DelegateViewHelper {
     private View mDelegateView;
     private View mSourceView;
-    private BaseStatusBar mBar;
+    private PhoneStatusBar mBar;
     private int[] mTempPoint = new int[2];
     private float[] mDownPoint = new float[2];
     private float mTriggerThreshhold;
@@ -45,7 +46,7 @@
         mDelegateView = view;
     }
 
-    public void setBar(BaseStatusBar phoneStatusBar) {
+    public void setBar(PhoneStatusBar phoneStatusBar) {
         mBar = phoneStatusBar;
     }
 
@@ -79,7 +80,7 @@
                 float y = k < historySize ? event.getHistoricalY(k) : event.getY();
                 final float distance = mSwapXY ? (mDownPoint[0] - x) : (mDownPoint[1] - y);
                 if (distance > mTriggerThreshhold) {
-                    mBar.showSearchPanel();
+                    mBar.invokeAssistGesture(false /* vibrate */);
                     mPanelShowing = true;
                     break;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 7286907..a82afcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -59,9 +59,10 @@
     private String mWifiDescription;
     private ArrayList<PhoneState> mPhoneStates = new ArrayList<PhoneState>();
     private int mIconTint = Color.WHITE;
+    private float mDarkIntensity;
 
     ViewGroup mWifiGroup;
-    ImageView mVpn, mWifi, mAirplane, mNoSims;
+    ImageView mVpn, mWifi, mAirplane, mNoSims, mWifiDark, mNoSimsDark;
     View mWifiAirplaneSpacer;
     View mWifiSignalSpacer;
     LinearLayout mMobileSignalGroup;
@@ -115,8 +116,10 @@
         mVpn            = (ImageView) findViewById(R.id.vpn);
         mWifiGroup      = (ViewGroup) findViewById(R.id.wifi_combo);
         mWifi           = (ImageView) findViewById(R.id.wifi_signal);
+        mWifiDark       = (ImageView) findViewById(R.id.wifi_signal_dark);
         mAirplane       = (ImageView) findViewById(R.id.airplane);
         mNoSims         = (ImageView) findViewById(R.id.no_sims);
+        mNoSimsDark     = (ImageView) findViewById(R.id.no_sims_dark);
         mWifiAirplaneSpacer =         findViewById(R.id.wifi_airplane_spacer);
         mWifiSignalSpacer =           findViewById(R.id.wifi_signal_spacer);
         mMobileSignalGroup = (LinearLayout) findViewById(R.id.mobile_signal_group);
@@ -273,6 +276,7 @@
         if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE"));
         if (mWifiVisible) {
             mWifi.setImageResource(mWifiStrengthId);
+            mWifiDark.setImageResource(mWifiStrengthId);
             mWifiGroup.setContentDescription(mWifiDescription);
             mWifiGroup.setVisibility(View.VISIBLE);
         } else {
@@ -317,15 +321,17 @@
         }
 
         mNoSims.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
+        mNoSimsDark.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
 
         boolean anythingVisible = mNoSimsVisible || mWifiVisible || mIsAirplaneMode
                 || anyMobileVisible || mVpnVisible;
         setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0);
     }
 
-    public void setIconTint(int tint) {
-        boolean changed = tint != mIconTint;
+    public void setIconTint(int tint, float darkIntensity) {
+        boolean changed = tint != mIconTint || darkIntensity != mDarkIntensity;
         mIconTint = tint;
+        mDarkIntensity = darkIntensity;
         if (changed && isAttachedToWindow()) {
             applyIconTint();
         }
@@ -333,14 +339,19 @@
 
     private void applyIconTint() {
         setTint(mVpn, mIconTint);
-        setTint(mWifi, mIconTint);
-        setTint(mNoSims, mIconTint);
         setTint(mAirplane, mIconTint);
+        applyDarkIntensity(mDarkIntensity, mNoSims, mNoSimsDark);
+        applyDarkIntensity(mDarkIntensity, mWifi, mWifiDark);
         for (int i = 0; i < mPhoneStates.size(); i++) {
-            mPhoneStates.get(i).setIconTint(mIconTint);
+            mPhoneStates.get(i).setIconTint(mIconTint, mDarkIntensity);
         }
     }
 
+    private void applyDarkIntensity(float darkIntensity, View lightIcon, View darkIcon) {
+        lightIcon.setAlpha(1 - darkIntensity);
+        darkIcon.setAlpha(darkIntensity);
+    }
+
     private void setTint(ImageView v, int tint) {
         v.setImageTintMode(PorterDuff.Mode.SRC_ATOP);
         v.setImageTintList(ColorStateList.valueOf(tint));
@@ -354,7 +365,7 @@
         private String mMobileDescription, mMobileTypeDescription;
 
         private ViewGroup mMobileGroup;
-        private ImageView mMobile, mMobileType;
+        private ImageView mMobile, mMobileDark, mMobileType;
 
         public PhoneState(int subId, Context context) {
             ViewGroup root = (ViewGroup) LayoutInflater.from(context)
@@ -366,12 +377,14 @@
         public void setViews(ViewGroup root) {
             mMobileGroup    = root;
             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);
         }
 
         public boolean apply(boolean isSecondaryIcon) {
             if (mMobileVisible && !mIsAirplaneMode) {
                 mMobile.setImageResource(mMobileStrengthId);
+                mMobileDark.setImageResource(mMobileStrengthId);
                 mMobileType.setImageResource(mMobileTypeId);
                 mMobileGroup.setContentDescription(mMobileTypeDescription
                         + " " + mMobileDescription);
@@ -385,6 +398,8 @@
                     0, 0, 0);
             mMobile.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0,
                     0, 0, 0);
+            mMobileDark.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0,
+                    0, 0, 0);
 
             if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d",
                         (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId));
@@ -401,8 +416,8 @@
             }
         }
 
-        public void setIconTint(int tint) {
-            setTint(mMobile, tint);
+        public void setIconTint(int tint, float darkIntensity) {
+            applyDarkIntensity(darkIntensity, mMobile, mMobileDark);
             setTint(mMobileType, tint);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 3b8fccc..cab152f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -69,7 +69,7 @@
         @Override
         public void onAnimationEnd(Animator animation) {
             mSwipeAnimator = null;
-            setSwipingInProgress(false);
+            mSwipingInProgress = false;
         }
     };
     private Runnable mAnimationEndRunnable = new Runnable() {
@@ -117,14 +117,17 @@
     }
 
     public boolean onTouchEvent(MotionEvent event) {
-        if (mMotionCancelled && event.getActionMasked() != MotionEvent.ACTION_DOWN) {
+        int action = event.getActionMasked();
+        if (mMotionCancelled && action != MotionEvent.ACTION_DOWN
+                && action != MotionEvent.ACTION_UP
+                && action != MotionEvent.ACTION_CANCEL) {
             return false;
         }
         final float y = event.getY();
         final float x = event.getX();
 
         boolean isUp = false;
-        switch (event.getActionMasked()) {
+        switch (action) {
             case MotionEvent.ACTION_DOWN:
                 if (mSwipingInProgress) {
                     cancelAnimation();
@@ -152,7 +155,8 @@
                     mInitialTouchY = y;
                     mInitialTouchX = x;
                     mTranslationOnDown = mTranslation;
-                    setSwipingInProgress(true);
+                    mSwipingInProgress = true;
+                    mCallback.onSwipingStarted(w < -mTouchSlop);
                 }
                 if (mSwipingInProgress) {
                     setTranslation(mTranslationOnDown + x - mInitialTouchX, false, false);
@@ -179,13 +183,6 @@
         }
     }
 
-    private void setSwipingInProgress(boolean inProgress) {
-        mSwipingInProgress = inProgress;
-        if (inProgress) {
-            mCallback.onSwipingStarted();
-        }
-    }
-
     private boolean rightSwipePossible() {
         return mRightIcon.getVisibility() == View.VISIBLE;
     }
@@ -323,6 +320,9 @@
         }
         animator.start();
         mSwipeAnimator = animator;
+        if (snapBack) {
+            mCallback.onSwipingAborted();
+        }
     }
 
     private void startFinishingCircleAnimation(float velocity, Runnable mAnimationEndRunnable) {
@@ -451,7 +451,11 @@
             mSwipeAnimator.cancel();
         }
         setTranslation(0.0f, true, animate);
-        setSwipingInProgress(false);
+        mMotionCancelled = true;
+        if (mSwipingInProgress) {
+            mCallback.onSwipingAborted();
+        }
+        mSwipingInProgress = false;
     }
 
     public interface Callback {
@@ -470,7 +474,9 @@
 
         float getPageWidth();
 
-        void onSwipingStarted();
+        void onSwipingStarted(boolean isRightwardMotion);
+
+        void onSwipingAborted();
 
         KeyguardAffordanceView getLeftIcon();
 
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 0c21b20..628ae84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -100,6 +100,7 @@
     private final TrustDrawable mTrustDrawable;
     private final Interpolator mLinearOutSlowInInterpolator;
     private int mLastUnlockIconRes = 0;
+    private boolean mPrewarmSent;
 
     public KeyguardBottomAreaView(Context context) {
         this(context, null);
@@ -335,13 +336,47 @@
         mLockPatternUtils.requireCredentialEntry(mLockPatternUtils.getCurrentUser());
     }
 
-    public void launchCamera() {
-        mFlashlightController.killFlashlight();
+    public void prewarmCamera() {
         Intent intent = getCameraIntent();
+        String targetPackage = PreviewInflater.getTargetPackage(mContext, intent,
+                mLockPatternUtils.getCurrentUser());
+        if (targetPackage != null) {
+            Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM);
+            prewarm.setPackage(targetPackage);
+            mPrewarmSent = true;
+            mContext.sendBroadcast(prewarm);
+        }
+    }
+
+    public void maybeCooldownCamera() {
+        if (!mPrewarmSent) {
+            return;
+        }
+        mPrewarmSent = false;
+        Intent intent = getCameraIntent();
+        String targetPackage = PreviewInflater.getTargetPackage(mContext, intent,
+                mLockPatternUtils.getCurrentUser());
+        if (targetPackage != null) {
+            Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN);
+            prewarm.setPackage(targetPackage);
+            mContext.sendBroadcast(prewarm);
+        }
+    }
+
+    public void launchCamera() {
+
+        // Reset prewarm state.
+        mPrewarmSent = false;
+        final Intent intent = getCameraIntent();
         boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
                 mContext, intent, mLockPatternUtils.getCurrentUser());
         if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
-            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+            AsyncTask.execute(new Runnable() {
+                @Override
+                public void run() {
+                    mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+                }
+            });
         } else {
 
             // We need to delay starting the activity because ResolverActivity finishes itself if
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 12ff399..c62ad66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -50,6 +50,8 @@
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.DelegateViewHelper;
 import com.android.systemui.statusbar.policy.DeadZone;
+import com.android.systemui.statusbar.policy.KeyButtonView;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -195,7 +197,7 @@
         mDelegateHelper.setDelegateView(view);
     }
 
-    public void setBar(BaseStatusBar phoneStatusBar) {
+    public void setBar(PhoneStatusBar phoneStatusBar) {
         mTaskSwitchHelper.setBar(phoneStatusBar);
         mDelegateHelper.setBar(phoneStatusBar);
     }
@@ -261,8 +263,8 @@
         return mCurrentView.findViewById(R.id.back);
     }
 
-    public View getHomeButton() {
-        return mCurrentView.findViewById(R.id.home);
+    public KeyButtonView getHomeButton() {
+        return (KeyButtonView) mCurrentView.findViewById(R.id.home);
     }
 
     public View getImeSwitchButton() {
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 195da46..216730b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1809,14 +1809,24 @@
     }
 
     @Override
-    public void onSwipingStarted() {
-        mSecureCameraLaunchManager.onSwipingStarted();
+    public void onSwipingStarted(boolean isRightwardMotion) {
+        boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? isRightwardMotion
+                : !isRightwardMotion;
+        if (!start) {
+            mSecureCameraLaunchManager.onSwipingStarted();
+            mKeyguardBottomArea.prewarmCamera();
+        }
         requestDisallowInterceptTouchEvent(true);
         mOnlyAffordanceInThisMotion = true;
         mQsTracking = false;
     }
 
     @Override
+    public void onSwipingAborted() {
+        mKeyguardBottomArea.maybeCooldownCamera();
+    }
+
+    @Override
     public KeyguardAffordanceView getLeftIcon() {
         return getLayoutDirection() == LAYOUT_DIRECTION_RTL
                 ? mKeyguardBottomArea.getCameraView()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 2c389fb..ad78f6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -49,7 +49,6 @@
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
@@ -121,6 +120,7 @@
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.recents.ScreenPinningRequest;
 import com.android.systemui.statusbar.ActivatableNotificationView;
+import com.android.systemui.assist.AssistGestureManager;
 import com.android.systemui.statusbar.BackDropView;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
@@ -225,8 +225,6 @@
     /** Allow some time inbetween the long press for back and recents. */
     private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
 
-    private int mLightModeIconColor;
-
     PhoneStatusBarPolicy mIconPolicy;
 
     // These are no longer handled by the policy, because we need custom strategies for them
@@ -323,6 +321,8 @@
     private int mNavigationIconHints = 0;
     private HandlerThread mHandlerThread;
 
+    private AssistGestureManager mAssistGestureManager;
+
     // ensure quick settings is disabled until the current user makes it through the setup wizard
     private boolean mUserSetup = false;
     private ContentObserver mUserSetupObserver = new ContentObserver(new Handler()) {
@@ -535,7 +535,6 @@
         updateDisplaySize();
         mScrimSrcModeEnabled = mContext.getResources().getBoolean(
                 R.bool.config_status_bar_scrim_behind_use_src);
-        mLightModeIconColor = mContext.getColor(R.color.light_mode_icon_color);
 
         super.start(); // calls createAndAddWindows()
 
@@ -642,8 +641,8 @@
                         new NavigationBarView.OnVerticalChangedListener() {
                     @Override
                     public void onVerticalChanged(boolean isVertical) {
-                        if (mSearchPanelView != null) {
-                            mSearchPanelView.setHorizontal(isVertical);
+                        if (mAssistGestureManager != null) {
+                            mAssistGestureManager.onConfigurationChanged();
                         }
                         mNotificationPanel.setQsScrimEnabled(!isVertical);
                     }
@@ -834,6 +833,8 @@
         mBroadcastReceiver.onReceive(mContext,
                 new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));
 
+        mAssistGestureManager = new AssistGestureManager(this, context);
+
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
@@ -953,60 +954,9 @@
         return mStatusBarWindow;
     }
 
-    @Override
-    protected WindowManager.LayoutParams getSearchLayoutParams(LayoutParams layoutParams) {
-        boolean opaque = false;
-        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                LayoutParams.MATCH_PARENT,
-                LayoutParams.MATCH_PARENT,
-                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
-                | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
-        if (ActivityManager.isHighEndGfx()) {
-            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-        }
-        lp.gravity = Gravity.BOTTOM | Gravity.START;
-        lp.setTitle("SearchPanel");
-        lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
-        | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
-        return lp;
-    }
-
-    @Override
-    protected void updateSearchPanel() {
-        super.updateSearchPanel();
-        if (mNavigationBarView != null) {
-            mNavigationBarView.setDelegateView(mSearchPanelView);
-        }
-    }
-
-    @Override
-    public void showSearchPanel() {
-        super.showSearchPanel();
-        mHandler.removeCallbacks(mShowSearchPanel);
-
-        // we want to freeze the sysui state wherever it is
-        mSearchPanelView.setSystemUiVisibility(mSystemUiVisibility);
-
-        if (mNavigationBarView != null) {
-            WindowManager.LayoutParams lp =
-                (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
-            lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-            mWindowManager.updateViewLayout(mNavigationBarView, lp);
-        }
-    }
-
-    @Override
-    public void hideSearchPanel() {
-        super.hideSearchPanel();
-        if (mNavigationBarView != null) {
-            WindowManager.LayoutParams lp =
-                (android.view.WindowManager.LayoutParams) mNavigationBarView.getLayoutParams();
-            lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
-            mWindowManager.updateViewLayout(mNavigationBarView, lp);
-        }
+    public void invokeAssistGesture(boolean vibrate) {
+        mHandler.removeCallbacks(mInvokeAssist);
+        mAssistGestureManager.onGestureInvoked(vibrate);
     }
 
     public int getStatusBarHeight() {
@@ -1036,30 +986,33 @@
     };
 
     private int mShowSearchHoldoff = 0;
-    private Runnable mShowSearchPanel = new Runnable() {
+    private Runnable mInvokeAssist = new Runnable() {
         public void run() {
-            showSearchPanel();
+            invokeAssistGesture(true /* vibrate */);
             awakenDreams();
+            if (mNavigationBarView != null) {
+                mNavigationBarView.getHomeButton().abortCurrentGesture();
+            }
         }
     };
 
     View.OnTouchListener mHomeActionListener = new View.OnTouchListener() {
         public boolean onTouch(View v, MotionEvent event) {
-            switch(event.getAction()) {
+            switch (event.getAction()) {
                 case MotionEvent.ACTION_DOWN:
-                if (!shouldDisableNavbarGestures()) {
-                    mHandler.removeCallbacks(mShowSearchPanel);
-                    mHandler.postDelayed(mShowSearchPanel, mShowSearchHoldoff);
-                }
-            break;
+                    if (!shouldDisableNavbarGestures()) {
+                        mHandler.removeCallbacks(mInvokeAssist);
+                        mHandler.postDelayed(mInvokeAssist, mShowSearchHoldoff);
+                    }
+                    break;
 
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                mHandler.removeCallbacks(mShowSearchPanel);
-                awakenDreams();
-            break;
-        }
-        return false;
+                case MotionEvent.ACTION_UP:
+                case MotionEvent.ACTION_CANCEL:
+                    mHandler.removeCallbacks(mInvokeAssist);
+                    awakenDreams();
+                    break;
+            }
+            return false;
         }
     };
 
@@ -1083,7 +1036,7 @@
         mNavigationBarView.getBackButton().setLongClickable(true);
         mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener);
         mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);
-        updateSearchPanel();
+        mAssistGestureManager.onConfigurationChanged();
     }
 
     // For small-screen devices (read: phones) that lack hardware navigation buttons
@@ -2060,11 +2013,6 @@
             }
         }
 
-        if ((flags & CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL) == 0) {
-            mHandler.removeMessages(MSG_CLOSE_SEARCH_PANEL);
-            mHandler.sendEmptyMessage(MSG_CLOSE_SEARCH_PANEL);
-        }
-
         if (mStatusBarWindow != null) {
             // release focus immediately to kick off focus change transition
             mStatusBarWindowManager.setStatusBarFocusable(false);
@@ -2324,9 +2272,7 @@
                 boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
                 boolean light = (vis & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0;
 
-                mIconController.setIconTint(
-                        (allowLight && light) ? mLightModeIconColor : Color.WHITE);
-
+                mIconController.setIconsDark(allowLight && light);
             }
             // restore the recents bit
             if (wasRecentsVisible) {
@@ -2989,7 +2935,7 @@
     };
 
     @Override
-    protected boolean shouldDisableNavbarGestures() {
+    public boolean shouldDisableNavbarGestures() {
         return !isDeviceProvisioned()
                 || mExpandedVisible
                 || (mDisabled & StatusBarManager.DISABLE_SEARCH) != 0;
@@ -3058,6 +3004,7 @@
             mHandlerThread = null;
         }
         mContext.unregisterReceiver(mBroadcastReceiver);
+        mAssistGestureManager.destroy();
     }
 
     private boolean mDemoModeAllowed;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 2236aae..ac93ced 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -199,7 +199,7 @@
         int volumeIconId = 0;
         String volumeDescription = null;
 
-        if (DndTile.isVisible(mContext)) {
+        if (DndTile.isVisible(mContext) || DndTile.isCombinedIcon(mContext)) {
             zenVisible = mZen != Global.ZEN_MODE_OFF;
             zenIconId = R.drawable.stat_sys_dnd;
             zenDescription = mContext.getString(R.string.quick_settings_dnd_label);
@@ -218,7 +218,7 @@
             volumeVisible = true;
             volumeIconId = R.drawable.stat_sys_ringer_silent;
             volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
-        } else if (mZen != Global.ZEN_MODE_NO_INTERRUPTIONS &&
+        } else if (mZen != Global.ZEN_MODE_NO_INTERRUPTIONS && mZen != Global.ZEN_MODE_ALARMS &&
                 audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
             volumeVisible = true;
             volumeIconId = R.drawable.stat_sys_ringer_vibrate;
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 c49f620..45da297 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -16,11 +16,11 @@
 
 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.graphics.Color;
-import android.graphics.PorterDuff;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.SystemClock;
@@ -74,12 +74,16 @@
     private int mIconHPadding;
 
     private int mIconTint = Color.WHITE;
+    private float mDarkIntensity;
 
     private boolean mTransitionPending;
     private boolean mTintChangePending;
-    private int mPendingIconTint;
+    private float mPendingDarkIntensity;
     private ValueAnimator mTintAnimator;
 
+    private int mDarkModeIconColorSingleTone;
+    private int mLightModeIconColorSingleTone;
+
     private final Handler mHandler;
     private boolean mTransitionDeferring;
     private long mTransitionDeferringStartTime;
@@ -111,6 +115,8 @@
                 android.R.interpolator.linear_out_slow_in);
         mFastOutSlowIn = AnimationUtils.loadInterpolator(mContext,
                 android.R.interpolator.fast_out_slow_in);
+        mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
+        mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
         mHandler = new Handler();
         updateResources();
     }
@@ -296,30 +302,31 @@
         }
     }
 
-    public void setIconTint(int tint) {
+    public void setIconsDark(boolean dark) {
         if (mTransitionPending) {
-            deferIconTintChange(tint);
+            deferIconTintChange(dark ? 1.0f : 0.0f);
         } else if (mTransitionDeferring) {
-            animateIconTint(tint,
+            animateIconTint(dark ? 1.0f : 0.0f,
                     Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
                     mTransitionDeferringDuration);
         } else {
-            animateIconTint(tint, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+            animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
         }
     }
 
-    private void animateIconTint(int targetTint, long delay, long duration) {
+    private void animateIconTint(float targetDarkIntensity, long delay,
+            long duration) {
         if (mTintAnimator != null) {
             mTintAnimator.cancel();
         }
-        if (mIconTint == targetTint) {
+        if (mDarkIntensity == targetDarkIntensity) {
             return;
         }
-        mTintAnimator = ValueAnimator.ofArgb(mIconTint, targetTint);
+        mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
         mTintAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
-                setIconTintInternal((Integer) animation.getAnimatedValue());
+                setIconTintInternal((Float) animation.getAnimatedValue());
             }
         });
         mTintAnimator.setDuration(duration);
@@ -327,17 +334,20 @@
         mTintAnimator.setInterpolator(mFastOutSlowIn);
         mTintAnimator.start();
     }
-    private void setIconTintInternal(int tint) {
-        mIconTint = tint;
+
+    private void setIconTintInternal(float darkIntensity) {
+        mDarkIntensity = darkIntensity;
+        mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
+                mLightModeIconColorSingleTone, mDarkModeIconColorSingleTone);
         applyIconTint();
     }
 
-    private void deferIconTintChange(int tint) {
-        if (mTintChangePending && tint == mPendingIconTint) {
+    private void deferIconTintChange(float darkIntensity) {
+        if (mTintChangePending && darkIntensity == mPendingDarkIntensity) {
             return;
         }
         mTintChangePending = true;
-        mPendingIconTint = tint;
+        mPendingDarkIntensity = darkIntensity;
     }
 
     private void applyIconTint() {
@@ -345,9 +355,9 @@
             StatusBarIconView v = (StatusBarIconView) mStatusIcons.getChildAt(i);
             v.setImageTintList(ColorStateList.valueOf(mIconTint));
         }
-        mSignalCluster.setIconTint(mIconTint);
+        mSignalCluster.setIconTint(mIconTint, mDarkIntensity);
         mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
-        mBatteryMeterView.setIconTint(mIconTint);
+        mBatteryMeterView.setDarkIntensity(mDarkIntensity);
         mClock.setTextColor(mIconTint);
         applyNotificationIconsTint();
     }
@@ -358,7 +368,6 @@
             boolean isPreL = Boolean.TRUE.equals(v.getTag(R.id.icon_is_pre_L));
             boolean colorize = !isPreL || isGrayscale(v);
             if (colorize) {
-                v.setImageTintMode(PorterDuff.Mode.SRC_ATOP);
                 v.setImageTintList(ColorStateList.valueOf(mIconTint));
             }
         }
@@ -381,7 +390,7 @@
     public void appTransitionCancelled() {
         if (mTransitionPending && mTintChangePending) {
             mTintChangePending = false;
-            animateIconTint(mPendingIconTint, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+            animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
         }
         mTransitionPending = false;
     }
@@ -389,7 +398,7 @@
     public void appTransitionStarting(long startTime, long duration) {
         if (mTransitionPending && mTintChangePending) {
             mTintChangePending = false;
-            animateIconTint(mPendingIconTint,
+            animateIconTint(mPendingDarkIntensity,
                     Math.max(0, startTime - SystemClock.uptimeMillis()),
                     duration);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 5ef345b..65cd268 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -125,7 +125,7 @@
         }
 
         @Override
-        public void onFingerprintRecognized(int userId) {
+        public void onFingerprintAuthenticated(int userId) {
             update(false /* updateAlways */);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index c9ba8f6..cd1914c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -17,20 +17,14 @@
 package com.android.systemui.statusbar.policy;
 
 import android.content.Context;
-import android.graphics.SurfaceTexture;
 import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraMetadata;
-import android.hardware.camera2.CaptureRequest;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
+import android.text.TextUtils;
 import android.util.Log;
-import android.util.Size;
-import android.view.Surface;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -44,7 +38,7 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final int DISPATCH_ERROR = 0;
-    private static final int DISPATCH_OFF = 1;
+    private static final int DISPATCH_CHANGED = 1;
     private static final int DISPATCH_AVAILABILITY_CHANGED = 2;
 
     private final CameraManager mCameraManager;
@@ -57,52 +51,50 @@
     /** Lock on {@code this} when accessing */
     private boolean mFlashlightEnabled;
 
-    private String mCameraId;
-    private boolean mCameraAvailable;
-    private CameraDevice mCameraDevice;
-    private CaptureRequest mFlashlightRequest;
-    private CameraCaptureSession mSession;
-    private SurfaceTexture mSurfaceTexture;
-    private Surface mSurface;
+    private final String mCameraId;
+    private boolean mTorchAvailable;
 
     public FlashlightController(Context mContext) {
         mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
-        initialize();
-    }
 
-    public void initialize() {
+        String cameraId = null;
         try {
-            mCameraId = getCameraId();
+            cameraId = getCameraId();
         } catch (Throwable e) {
             Log.e(TAG, "Couldn't initialize.", e);
             return;
+        } finally {
+            mCameraId = cameraId;
         }
 
         if (mCameraId != null) {
             ensureHandler();
-            mCameraManager.registerAvailabilityCallback(mAvailabilityCallback, mHandler);
+            mCameraManager.registerTorchCallback(mTorchCallback, mHandler);
         }
     }
 
-    public synchronized void setFlashlight(boolean enabled) {
-        if (mFlashlightEnabled != enabled) {
-            mFlashlightEnabled = enabled;
-            postUpdateFlashlight();
-        }
-    }
-
-    public void killFlashlight() {
-        boolean enabled;
+    public void setFlashlight(boolean enabled) {
+        boolean pendingError = false;
         synchronized (this) {
-            enabled = mFlashlightEnabled;
+            if (mFlashlightEnabled != enabled) {
+                mFlashlightEnabled = enabled;
+                try {
+                    mCameraManager.setTorchMode(mCameraId, enabled);
+                } catch (CameraAccessException e) {
+                    Log.e(TAG, "Couldn't set torch mode", e);
+                    mFlashlightEnabled = false;
+                    pendingError = true;
+                }
+            }
         }
-        if (enabled) {
-            mHandler.post(mKillFlashlightRunnable);
+        dispatchModeChanged(mFlashlightEnabled);
+        if (pendingError) {
+            dispatchError();
         }
     }
 
     public synchronized boolean isAvailable() {
-        return mCameraAvailable;
+        return mTorchAvailable;
     }
 
     public void addListener(FlashlightListener l) {
@@ -126,42 +118,6 @@
         }
     }
 
-    private void startDevice() throws CameraAccessException {
-        mCameraManager.openCamera(getCameraId(), mCameraListener, mHandler);
-    }
-
-    private void startSession() throws CameraAccessException {
-        mSurfaceTexture = new SurfaceTexture(false);
-        Size size = getSmallestSize(mCameraDevice.getId());
-        mSurfaceTexture.setDefaultBufferSize(size.getWidth(), size.getHeight());
-        mSurface = new Surface(mSurfaceTexture);
-        ArrayList<Surface> outputs = new ArrayList<>(1);
-        outputs.add(mSurface);
-        mCameraDevice.createCaptureSession(outputs, mSessionListener, mHandler);
-    }
-
-    private Size getSmallestSize(String cameraId) throws CameraAccessException {
-        Size[] outputSizes = mCameraManager.getCameraCharacteristics(cameraId)
-                .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
-                .getOutputSizes(SurfaceTexture.class);
-        if (outputSizes == null || outputSizes.length == 0) {
-            throw new IllegalStateException(
-                    "Camera " + cameraId + "doesn't support any outputSize.");
-        }
-        Size chosen = outputSizes[0];
-        for (Size s : outputSizes) {
-            if (chosen.getWidth() >= s.getWidth() && chosen.getHeight() >= s.getHeight()) {
-                chosen = s;
-            }
-        }
-        return chosen;
-    }
-
-    private void postUpdateFlashlight() {
-        ensureHandler();
-        mHandler.post(mUpdateFlashlightRunnable);
-    }
-
     private String getCameraId() throws CameraAccessException {
         String[] ids = mCameraManager.getCameraIdList();
         for (String id : ids) {
@@ -176,70 +132,12 @@
         return null;
     }
 
-    private void updateFlashlight(boolean forceDisable) {
-        try {
-            boolean enabled;
-            synchronized (this) {
-                enabled = mFlashlightEnabled && !forceDisable;
-            }
-            if (enabled) {
-                if (mCameraDevice == null) {
-                    startDevice();
-                    return;
-                }
-                if (mSession == null) {
-                    startSession();
-                    return;
-                }
-                if (mFlashlightRequest == null) {
-                    CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(
-                            CameraDevice.TEMPLATE_PREVIEW);
-                    builder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
-                    builder.addTarget(mSurface);
-                    CaptureRequest request = builder.build();
-                    mSession.capture(request, null, mHandler);
-                    mFlashlightRequest = request;
-                }
-            } else {
-                if (mCameraDevice != null) {
-                    mCameraDevice.close();
-                    teardown();
-                }
-            }
-
-        } catch (CameraAccessException|IllegalStateException|UnsupportedOperationException e) {
-            Log.e(TAG, "Error in updateFlashlight", e);
-            handleError();
-        }
-    }
-
-    private void teardown() {
-        mCameraDevice = null;
-        mSession = null;
-        mFlashlightRequest = null;
-        if (mSurface != null) {
-            mSurface.release();
-            mSurfaceTexture.release();
-        }
-        mSurface = null;
-        mSurfaceTexture = null;
-    }
-
-    private void handleError() {
-        synchronized (this) {
-            mFlashlightEnabled = false;
-        }
-        dispatchError();
-        dispatchOff();
-        updateFlashlight(true /* forceDisable */);
-    }
-
-    private void dispatchOff() {
-        dispatchListeners(DISPATCH_OFF, false /* argument (ignored) */);
+    private void dispatchModeChanged(boolean enabled) {
+        dispatchListeners(DISPATCH_CHANGED, enabled);
     }
 
     private void dispatchError() {
-        dispatchListeners(DISPATCH_ERROR, false /* argument (ignored) */);
+        dispatchListeners(DISPATCH_CHANGED, false /* argument (ignored) */);
     }
 
     private void dispatchAvailabilityChanged(boolean available) {
@@ -255,8 +153,8 @@
                 if (l != null) {
                     if (message == DISPATCH_ERROR) {
                         l.onFlashlightError();
-                    } else if (message == DISPATCH_OFF) {
-                        l.onFlashlightOff();
+                    } else if (message == DISPATCH_CHANGED) {
+                        l.onFlashlightChanged(argument);
                     } else if (message == DISPATCH_AVAILABILITY_CHANGED) {
                         l.onFlashlightAvailabilityChanged(argument);
                     }
@@ -279,106 +177,57 @@
         }
     }
 
-    private final CameraDevice.StateListener mCameraListener = new CameraDevice.StateListener() {
-        @Override
-        public void onOpened(CameraDevice camera) {
-            mCameraDevice = camera;
-            postUpdateFlashlight();
-        }
+    private final CameraManager.TorchCallback mTorchCallback =
+            new CameraManager.TorchCallback() {
 
         @Override
-        public void onDisconnected(CameraDevice camera) {
-            if (mCameraDevice == camera) {
-                dispatchOff();
-                teardown();
-            }
-        }
-
-        @Override
-        public void onError(CameraDevice camera, int error) {
-            Log.e(TAG, "Camera error: camera=" + camera + " error=" + error);
-            if (camera == mCameraDevice || mCameraDevice == null) {
-                handleError();
-            }
-        }
-    };
-
-    private final CameraCaptureSession.StateListener mSessionListener =
-            new CameraCaptureSession.StateListener() {
-        @Override
-        public void onConfigured(CameraCaptureSession session) {
-            if (session.getDevice() == mCameraDevice) {
-                mSession = session;
-            } else {
-                session.close();
-            }
-            postUpdateFlashlight();
-        }
-
-        @Override
-        public void onConfigureFailed(CameraCaptureSession session) {
-            Log.e(TAG, "Configure failed.");
-            if (mSession == null || mSession == session) {
-                handleError();
-            }
-        }
-    };
-
-    private final Runnable mUpdateFlashlightRunnable = new Runnable() {
-        @Override
-        public void run() {
-            updateFlashlight(false /* forceDisable */);
-        }
-    };
-
-    private final Runnable mKillFlashlightRunnable = new Runnable() {
-        @Override
-        public void run() {
-            synchronized (this) {
-                mFlashlightEnabled = false;
-            }
-            updateFlashlight(true /* forceDisable */);
-            dispatchOff();
-        }
-    };
-
-    private final CameraManager.AvailabilityCallback mAvailabilityCallback =
-            new CameraManager.AvailabilityCallback() {
-        @Override
-        public void onCameraAvailable(String cameraId) {
-            if (DEBUG) Log.d(TAG, "onCameraAvailable(" + cameraId + ")");
-            if (cameraId.equals(mCameraId)) {
-                setCameraAvailable(true);
-            }
-        }
-
-        @Override
-        public void onCameraUnavailable(String cameraId) {
-            if (DEBUG) Log.d(TAG, "onCameraUnavailable(" + cameraId + ")");
-            if (cameraId.equals(mCameraId)) {
+        public void onTorchModeUnavailable(String cameraId) {
+            if (TextUtils.equals(cameraId, mCameraId)) {
                 setCameraAvailable(false);
             }
         }
 
+        @Override
+        public void onTorchModeChanged(String cameraId, boolean enabled) {
+            if (TextUtils.equals(cameraId, mCameraId)) {
+                setCameraAvailable(true);
+                setTorchMode(enabled);
+            }
+        }
+
         private void setCameraAvailable(boolean available) {
             boolean changed;
             synchronized (FlashlightController.this) {
-                changed = mCameraAvailable != available;
-                mCameraAvailable = available;
+                changed = mTorchAvailable != available;
+                mTorchAvailable = available;
             }
             if (changed) {
                 if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")");
                 dispatchAvailabilityChanged(available);
             }
         }
+
+        private void setTorchMode(boolean enabled) {
+            boolean changed;
+            synchronized (FlashlightController.this) {
+                changed = mFlashlightEnabled != enabled;
+                mFlashlightEnabled = enabled;
+            }
+            if (changed) {
+                if (DEBUG) Log.d(TAG, "dispatchModeChanged(" + enabled + ")");
+                dispatchModeChanged(enabled);
+            }
+        }
     };
 
     public interface FlashlightListener {
 
         /**
-         * Called when the flashlight turns off unexpectedly.
+         * Called when the flashlight was turned off or on.
+         * @param enabled true if the flashlight is currently turned on.
          */
-        void onFlashlightOff();
+        void onFlashlightChanged(boolean enabled);
+
 
         /**
          * Called when there is an error that turns the flashlight off.
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 a18daed..6bc51fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -48,6 +48,7 @@
     private int mTouchSlop;
     private boolean mSupportsLongpress = true;
     private AudioManager mAudioManager;
+    private boolean mGestureAborted;
 
     private final Runnable mCheckLongPress = new Runnable() {
         public void run() {
@@ -126,10 +127,15 @@
     public boolean onTouchEvent(MotionEvent ev) {
         final int action = ev.getAction();
         int x, y;
+        if (action == MotionEvent.ACTION_DOWN) {
+            mGestureAborted = false;
+        }
+        if (mGestureAborted) {
+            return false;
+        }
 
         switch (action) {
             case MotionEvent.ACTION_DOWN:
-                //Log.d("KeyButtonView", "press");
                 mDownTime = SystemClock.uptimeMillis();
                 setPressed(true);
                 if (mCode != 0) {
@@ -203,6 +209,11 @@
         InputManager.getInstance().injectInputEvent(ev,
                 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
     }
+
+    public void abortCurrentGesture() {
+        setPressed(false);
+        mGestureAborted = true;
+    }
 }
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
index 34068fd..0dce82f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -106,15 +107,28 @@
 
     public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,
             int currentUserId) {
+        return getTargetPackage(ctx, intent, currentUserId) == null;
+    }
+
+    /**
+     * @return the target package of the intent it resolves to a specific package or {@code null} if
+     *         it resolved to the resolver activity
+     */
+    public static String getTargetPackage(Context ctx, Intent intent,
+            int currentUserId) {
         PackageManager packageManager = ctx.getPackageManager();
         final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
                 intent, PackageManager.MATCH_DEFAULT_ONLY, currentUserId);
         if (appList.size() == 0) {
-            return false;
+            return null;
         }
         ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
                 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, currentUserId);
-        return wouldLaunchResolverActivity(resolved, appList);
+        if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
+            return null;
+        } else {
+            return resolved.activityInfo.packageName;
+        }
     }
 
     private static boolean wouldLaunchResolverActivity(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 2fbb812..f0dd943 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -190,7 +190,8 @@
             NetworkCapabilities networkCapabilities =
                     mConnectivityManager.getNetworkCapabilities(network);
             if (DEBUG) Log.d(TAG, "onAvailable " + network.netId + " : " + networkCapabilities);
-            if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
+            if (networkCapabilities != null &&
+                    networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
                 setCurrentNetid(network.netId);
             }
         };
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 d1e1b71..c272e48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -106,12 +106,6 @@
     }
 
     @Override
-    protected WindowManager.LayoutParams getSearchLayoutParams(
-            LayoutParams layoutParams) {
-        return null;
-    }
-
-    @Override
     protected void setAreThereNotifications() {
     }
 
@@ -120,7 +114,7 @@
     }
 
     @Override
-    protected boolean shouldDisableNavbarGestures() {
+    public boolean shouldDisableNavbarGestures() {
         return true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/packages/SystemUI/src/com/android/systemui/volume/D.java
similarity index 73%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to packages/SystemUI/src/com/android/systemui/volume/D.java
index 272c321..db7c853 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/D.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+package com.android.systemui.volume;
 
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
+import android.util.Log;
+
+class D {
+    public static boolean BUG = Log.isLoggable("volume", Log.DEBUG);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
new file mode 100644
index 0000000..12dca94
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -0,0 +1,190 @@
+/*
+ * 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.volume;
+
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.provider.Settings.Global;
+import android.util.Log;
+
+import com.android.systemui.volume.VolumeDialogController.State;
+
+import java.util.Arrays;
+
+/**
+ *  Interesting events related to the volume.
+ */
+public class Events {
+    private static final String TAG = Util.logTag(Events.class);
+
+    public static final int EVENT_SHOW_DIALOG = 0;  // (reason|int) (keyguard|bool)
+    public static final int EVENT_DISMISS_DIALOG = 1; // (reason|int)
+    public static final int EVENT_ACTIVE_STREAM_CHANGED = 2; // (stream|int)
+    public static final int EVENT_EXPAND = 3; // (expand|bool)
+    public static final int EVENT_KEY = 4;
+    public static final int EVENT_COLLECTION_STARTED = 5;
+    public static final int EVENT_COLLECTION_STOPPED = 6;
+    public static final int EVENT_ICON_CLICK = 7; // (stream|int) (icon_state|int)
+    public static final int EVENT_SETTINGS_CLICK = 8;
+    public static final int EVENT_TOUCH_LEVEL_CHANGED = 9; // (stream|int) (level|int)
+    public static final int EVENT_LEVEL_CHANGED = 10; // (stream|int) (level|int)
+    public static final int EVENT_INTERNAL_RINGER_MODE_CHANGED = 11; // (mode|int)
+    public static final int EVENT_EXTERNAL_RINGER_MODE_CHANGED = 12; // (mode|int)
+    public static final int EVENT_ZEN_MODE_CHANGED = 13; // (mode|int)
+    public static final int EVENT_SUPPRESSOR_CHANGED = 14;  // (component|string) (name|string)
+    public static final int EVENT_MUTE_CHANGED = 15;  // (stream|int) (muted|bool)
+
+    private static final String[] EVENT_TAGS = {
+        "show_dialog",
+        "dismiss_dialog",
+        "active_stream_changed",
+        "expand",
+        "key",
+        "collection_started",
+        "collection_stopped",
+        "icon_click",
+        "settings_click",
+        "touch_level_changed",
+        "level_changed",
+        "internal_ringer_mode_changed",
+        "external_ringer_mode_changed",
+        "zen_mode_changed",
+        "suppressor_changed",
+        "mute_changed",
+    };
+
+    public static final int DISMISS_REASON_UNKNOWN = 0;
+    public static final int DISMISS_REASON_TOUCH_OUTSIDE = 1;
+    public static final int DISMISS_REASON_VOLUME_CONTROLLER = 2;
+    public static final int DISMISS_REASON_TIMEOUT = 3;
+    public static final int DISMISS_REASON_SCREEN_OFF = 4;
+    public static final int DISMISS_REASON_SETTINGS_CLICKED = 5;
+    public static final int DISMISS_REASON_DONE_CLICKED = 6;
+    public static final String[] DISMISS_REASONS = {
+        "unknown",
+        "touch_outside",
+        "volume_controller",
+        "timeout",
+        "screen_off",
+        "settings_clicked",
+        "done_clicked",
+    };
+
+    public static final int SHOW_REASON_UNKNOWN = 0;
+    public static final int SHOW_REASON_VOLUME_CHANGED = 1;
+    public static final int SHOW_REASON_REMOTE_VOLUME_CHANGED = 2;
+    public static final String[] SHOW_REASONS = {
+        "unknown",
+        "volume_changed",
+        "remote_volume_changed"
+    };
+
+    public static final int ICON_STATE_UNKNOWN = 0;
+    public static final int ICON_STATE_UNMUTE = 1;
+    public static final int ICON_STATE_MUTE = 2;
+    public static final int ICON_STATE_VIBRATE = 3;
+
+    public static Callback sCallback;
+
+    public static void writeEvent(int tag, Object... list) {
+        final long time = System.currentTimeMillis();
+        final StringBuilder sb = new StringBuilder("writeEvent ").append(EVENT_TAGS[tag]);
+        if (list != null && list.length > 0) {
+            sb.append(" ");
+            switch (tag) {
+                case EVENT_SHOW_DIALOG:
+                    sb.append(SHOW_REASONS[(Integer) list[0]]).append(" keyguard=").append(list[1]);
+                    break;
+                case EVENT_EXPAND:
+                    sb.append(list[0]);
+                    break;
+                case EVENT_DISMISS_DIALOG:
+                    sb.append(DISMISS_REASONS[(Integer) list[0]]);
+                    break;
+                case EVENT_ACTIVE_STREAM_CHANGED:
+                    sb.append(AudioSystem.streamToString((Integer) list[0]));
+                    break;
+                case EVENT_ICON_CLICK:
+                    sb.append(AudioSystem.streamToString((Integer) list[0])).append(' ')
+                            .append(iconStateToString((Integer) list[1]));
+                    break;
+                case EVENT_TOUCH_LEVEL_CHANGED:
+                case EVENT_LEVEL_CHANGED:
+                case EVENT_MUTE_CHANGED:
+                    sb.append(AudioSystem.streamToString((Integer) list[0])).append(' ')
+                            .append(list[1]);
+                    break;
+                case EVENT_INTERNAL_RINGER_MODE_CHANGED:
+                case EVENT_EXTERNAL_RINGER_MODE_CHANGED:
+                    sb.append(ringerModeToString((Integer) list[0]));
+                    break;
+                case EVENT_ZEN_MODE_CHANGED:
+                    sb.append(zenModeToString((Integer) list[0]));
+                    break;
+                case EVENT_SUPPRESSOR_CHANGED:
+                    sb.append(list[0]).append(' ').append(list[1]);
+                    break;
+                default:
+                    sb.append(Arrays.asList(list));
+                    break;
+            }
+        }
+        Log.i(TAG, sb.toString());
+        if (sCallback != null) {
+            sCallback.writeEvent(time, tag, list);
+        }
+    }
+
+    public static void writeState(long time, State state) {
+        if (sCallback != null) {
+            sCallback.writeState(time, state);
+        }
+    }
+
+    private static String iconStateToString(int iconState) {
+        switch (iconState) {
+            case ICON_STATE_UNMUTE: return "unmute";
+            case ICON_STATE_MUTE: return "mute";
+            case ICON_STATE_VIBRATE: return "vibrate";
+            default: return "unknown_state_" + iconState;
+        }
+    }
+
+    private static String ringerModeToString(int ringerMode) {
+        switch (ringerMode) {
+            case AudioManager.RINGER_MODE_SILENT: return "silent";
+            case AudioManager.RINGER_MODE_VIBRATE: return "vibrate";
+            case AudioManager.RINGER_MODE_NORMAL: return "normal";
+            default: return "unknown";
+        }
+    }
+
+    private static String zenModeToString(int zenMode) {
+        switch (zenMode) {
+            case Global.ZEN_MODE_OFF: return "off";
+            case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return "important_interruptions";
+            case Global.ZEN_MODE_ALARMS: return "alarms";
+            case Global.ZEN_MODE_NO_INTERRUPTIONS: return "no_interruptions";
+            default: return "unknown";
+        }
+    }
+
+    public interface Callback {
+        void writeEvent(long time, int tag, Object[] list);
+        void writeState(long time, State state);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/MediaSessions.java b/packages/SystemUI/src/com/android/systemui/volume/MediaSessions.java
new file mode 100644
index 0000000..712ea27
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/MediaSessions.java
@@ -0,0 +1,378 @@
+/*
+ * 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.volume;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.media.IRemoteVolumeController;
+import android.media.MediaMetadata;
+import android.media.session.ISessionController;
+import android.media.session.MediaController;
+import android.media.session.MediaController.PlaybackInfo;
+import android.media.session.MediaSession.QueueItem;
+import android.media.session.MediaSession.Token;
+import android.media.session.MediaSessionManager;
+import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener;
+import android.media.session.PlaybackState;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Convenience client for all media session updates.  Provides a callback interface for events
+ * related to remote media sessions.
+ */
+public class MediaSessions {
+    private static final String TAG = Util.logTag(MediaSessions.class);
+
+    private static final boolean USE_SERVICE_LABEL = false;
+
+    private final Context mContext;
+    private final H mHandler;
+    private final MediaSessionManager mMgr;
+    private final Map<Token, MediaControllerRecord> mRecords = new HashMap<>();
+    private final Callbacks mCallbacks;
+
+    private boolean mInit;
+
+    public MediaSessions(Context context, Looper looper, Callbacks callbacks) {
+        mContext = context;
+        mHandler = new H(looper);
+        mMgr = (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
+        mCallbacks = callbacks;
+    }
+
+    public void dump(PrintWriter writer) {
+        writer.println(getClass().getSimpleName() + " state:");
+        writer.print("  mInit: "); writer.println(mInit);
+        writer.print("  mRecords.size: "); writer.println(mRecords.size());
+        int i = 0;
+        for (MediaControllerRecord r : mRecords.values()) {
+            dump(++i, writer, r.controller);
+        }
+    }
+
+    public void init() {
+        if (D.BUG) Log.d(TAG, "init");
+        // will throw if no permission
+        mMgr.addOnActiveSessionsChangedListener(mSessionsListener, null, mHandler);
+        mInit = true;
+        postUpdateSessions();
+        mMgr.setRemoteVolumeController(mRvc);
+    }
+
+    protected void postUpdateSessions() {
+        if (!mInit) return;
+        mHandler.sendEmptyMessage(H.UPDATE_SESSIONS);
+    }
+
+    public void destroy() {
+        if (D.BUG) Log.d(TAG, "destroy");
+        mInit = false;
+        mMgr.removeOnActiveSessionsChangedListener(mSessionsListener);
+    }
+
+    public void setVolume(Token token, int level) {
+        final MediaControllerRecord r = mRecords.get(token);
+        if (r == null) {
+            Log.w(TAG, "setVolume: No record found for token " + token);
+            return;
+        }
+        if (D.BUG) Log.d(TAG, "Setting level to " + level);
+        r.controller.setVolumeTo(level, 0);
+    }
+
+    private void onRemoteVolumeChangedH(ISessionController session, int flags) {
+        final MediaController controller = new MediaController(mContext, session);
+        if (D.BUG) Log.d(TAG, "remoteVolumeChangedH " + controller.getPackageName() + " "
+                + Util.audioManagerFlagsToString(flags));
+        final Token token = controller.getSessionToken();
+        mCallbacks.onRemoteVolumeChanged(token, flags);
+    }
+
+    private void onUpdateRemoteControllerH(ISessionController session) {
+        final MediaController controller = session != null ? new MediaController(mContext, session)
+                : null;
+        final String pkg = controller != null ? controller.getPackageName() : null;
+        if (D.BUG) Log.d(TAG, "updateRemoteControllerH " + pkg);
+        // this may be our only indication that a remote session is changed, refresh
+        postUpdateSessions();
+    }
+
+    protected void onActiveSessionsUpdatedH(List<MediaController> controllers) {
+        if (D.BUG) Log.d(TAG, "onActiveSessionsUpdatedH n=" + controllers.size());
+        final Set<Token> toRemove = new HashSet<Token>(mRecords.keySet());
+        for (MediaController controller : controllers) {
+            final Token token = controller.getSessionToken();
+            final PlaybackInfo pi = controller.getPlaybackInfo();
+            toRemove.remove(token);
+            if (!mRecords.containsKey(token)) {
+                final MediaControllerRecord r = new MediaControllerRecord(controller);
+                r.name = getControllerName(controller);
+                mRecords.put(token, r);
+                controller.registerCallback(r, mHandler);
+            }
+            final MediaControllerRecord r = mRecords.get(token);
+            final boolean remote = isRemote(pi);
+            if (remote) {
+                updateRemoteH(token, r.name, pi);
+                r.sentRemote = true;
+            }
+        }
+        for (Token t : toRemove) {
+            final MediaControllerRecord r = mRecords.get(t);
+            r.controller.unregisterCallback(r);
+            mRecords.remove(t);
+            if (D.BUG) Log.d(TAG, "Removing " + r.name + " sentRemote=" + r.sentRemote);
+            if (r.sentRemote) {
+                mCallbacks.onRemoteRemoved(t);
+                r.sentRemote = false;
+            }
+        }
+    }
+
+    private static boolean isRemote(PlaybackInfo pi) {
+        return pi != null && pi.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE;
+    }
+
+    protected String getControllerName(MediaController controller) {
+        final PackageManager pm = mContext.getPackageManager();
+        final String pkg = controller.getPackageName();
+        try {
+            if (USE_SERVICE_LABEL) {
+                final List<ResolveInfo> ris = pm.queryIntentServices(
+                        new Intent("android.media.MediaRouteProviderService").setPackage(pkg), 0);
+                if (ris != null) {
+                    for (ResolveInfo ri : ris) {
+                        if (ri.serviceInfo == null) continue;
+                        if (pkg.equals(ri.serviceInfo.packageName)) {
+                            final String serviceLabel =
+                                    Objects.toString(ri.serviceInfo.loadLabel(pm), "").trim();
+                            if (serviceLabel.length() > 0) {
+                                return serviceLabel;
+                            }
+                        }
+                    }
+                }
+            }
+            final ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
+            final String appLabel = Objects.toString(ai.loadLabel(pm), "").trim();
+            if (appLabel.length() > 0) {
+                return appLabel;
+            }
+        } catch (NameNotFoundException e) { }
+        return pkg;
+    }
+
+    private void updateRemoteH(Token token, String name, PlaybackInfo pi) {
+        if (mCallbacks != null) {
+            mCallbacks.onRemoteUpdate(token, name, pi);
+        }
+    }
+
+    private static void dump(int n, PrintWriter writer, MediaController c) {
+        writer.println("  Controller " + n + ": " + c.getPackageName());
+        final Bundle extras = c.getExtras();
+        final long flags = c.getFlags();
+        final MediaMetadata mm = c.getMetadata();
+        final PlaybackInfo pi = c.getPlaybackInfo();
+        final PlaybackState playbackState = c.getPlaybackState();
+        final List<QueueItem> queue = c.getQueue();
+        final CharSequence queueTitle = c.getQueueTitle();
+        final int ratingType = c.getRatingType();
+        final PendingIntent sessionActivity = c.getSessionActivity();
+
+        writer.println("    PlaybackState: " + Util.playbackStateToString(playbackState));
+        writer.println("    PlaybackInfo: " + Util.playbackInfoToString(pi));
+        if (mm != null) {
+            writer.println("  MediaMetadata.desc=" + mm.getDescription());
+        }
+        writer.println("    RatingType: " + ratingType);
+        writer.println("    Flags: " + flags);
+        if (extras != null) {
+            writer.println("    Extras:");
+            for (String key : extras.keySet()) {
+                writer.println("      " + key + "=" + extras.get(key));
+            }
+        }
+        if (queueTitle != null) {
+            writer.println("    QueueTitle: " + queueTitle);
+        }
+        if (queue != null && !queue.isEmpty()) {
+            writer.println("    Queue:");
+            for (QueueItem qi : queue) {
+                writer.println("      " + qi);
+            }
+        }
+        if (pi != null) {
+            writer.println("    sessionActivity: " + sessionActivity);
+        }
+    }
+
+    public static void dumpMediaSessions(Context context) {
+        final MediaSessionManager mgr = (MediaSessionManager) context
+                .getSystemService(Context.MEDIA_SESSION_SERVICE);
+        try {
+            final List<MediaController> controllers = mgr.getActiveSessions(null);
+            final int N = controllers.size();
+            if (D.BUG) Log.d(TAG, N + " controllers");
+            for (int i = 0; i < N; i++) {
+                final StringWriter sw = new StringWriter();
+                final PrintWriter pw = new PrintWriter(sw, true);
+                dump(i + 1, pw, controllers.get(i));
+                if (D.BUG) Log.d(TAG, sw.toString());
+            }
+        } catch (SecurityException e) {
+            Log.w(TAG, "Not allowed to get sessions", e);
+        }
+    }
+
+    private final class MediaControllerRecord extends MediaController.Callback {
+        private final MediaController controller;
+
+        private boolean sentRemote;
+        private String name;
+
+        private MediaControllerRecord(MediaController controller) {
+            this.controller = controller;
+        }
+
+        private String cb(String method) {
+            return method + " " + controller.getPackageName() + " ";
+        }
+
+        @Override
+        public void onAudioInfoChanged(PlaybackInfo info) {
+            if (D.BUG) Log.d(TAG, cb("onAudioInfoChanged") + Util.playbackInfoToString(info)
+                    + " sentRemote=" + sentRemote);
+            final boolean remote = isRemote(info);
+            if (!remote && sentRemote) {
+                mCallbacks.onRemoteRemoved(controller.getSessionToken());
+                sentRemote = false;
+            } else if (remote) {
+                updateRemoteH(controller.getSessionToken(), name, info);
+                sentRemote = true;
+            }
+        }
+
+        @Override
+        public void onExtrasChanged(Bundle extras) {
+            if (D.BUG) Log.d(TAG, cb("onExtrasChanged") + extras);
+        }
+
+        @Override
+        public void onMetadataChanged(MediaMetadata metadata) {
+            if (D.BUG) Log.d(TAG, cb("onMetadataChanged") + Util.mediaMetadataToString(metadata));
+        }
+
+        @Override
+        public void onPlaybackStateChanged(PlaybackState state) {
+            if (D.BUG) Log.d(TAG, cb("onPlaybackStateChanged") + Util.playbackStateToString(state));
+        }
+
+        @Override
+        public void onQueueChanged(List<QueueItem> queue) {
+            if (D.BUG) Log.d(TAG, cb("onQueueChanged") + queue);
+        }
+
+        @Override
+        public void onQueueTitleChanged(CharSequence title) {
+            if (D.BUG) Log.d(TAG, cb("onQueueTitleChanged") + title);
+        }
+
+        @Override
+        public void onSessionDestroyed() {
+            if (D.BUG) Log.d(TAG, cb("onSessionDestroyed"));
+        }
+
+        @Override
+        public void onSessionEvent(String event, Bundle extras) {
+            if (D.BUG) Log.d(TAG, cb("onSessionEvent") + "event=" + event + " extras=" + extras);
+        }
+    }
+
+    private final OnActiveSessionsChangedListener mSessionsListener =
+            new OnActiveSessionsChangedListener() {
+        @Override
+        public void onActiveSessionsChanged(List<MediaController> controllers) {
+            onActiveSessionsUpdatedH(controllers);
+        }
+    };
+
+    private final IRemoteVolumeController mRvc = new IRemoteVolumeController.Stub() {
+        @Override
+        public void remoteVolumeChanged(ISessionController session, int flags)
+                throws RemoteException {
+            mHandler.obtainMessage(H.REMOTE_VOLUME_CHANGED, flags, 0, session).sendToTarget();
+        }
+
+        @Override
+        public void updateRemoteController(final ISessionController session)
+                throws RemoteException {
+            mHandler.obtainMessage(H.UPDATE_REMOTE_CONTROLLER, session).sendToTarget();
+        }
+    };
+
+    private final class H extends Handler {
+        private static final int UPDATE_SESSIONS = 1;
+        private static final int REMOTE_VOLUME_CHANGED = 2;
+        private static final int UPDATE_REMOTE_CONTROLLER = 3;
+
+        private H(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case UPDATE_SESSIONS:
+                    onActiveSessionsUpdatedH(mMgr.getActiveSessions(null));
+                    break;
+                case REMOTE_VOLUME_CHANGED:
+                    onRemoteVolumeChangedH((ISessionController) msg.obj, msg.arg1);
+                    break;
+                case UPDATE_REMOTE_CONTROLLER:
+                    onUpdateRemoteControllerH((ISessionController) msg.obj);
+                    break;
+            }
+        }
+    }
+
+    public interface Callbacks {
+        void onRemoteUpdate(Token token, String name, PlaybackInfo pi);
+        void onRemoteRemoved(Token t);
+        void onRemoteVolumeChanged(Token token, int flags);
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Prefs.java b/packages/SystemUI/src/com/android/systemui/volume/Prefs.java
new file mode 100644
index 0000000..58bc9f4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/Prefs.java
@@ -0,0 +1,69 @@
+/*
+ * 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.volume;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.preference.PreferenceManager;
+
+/**
+ *  Configuration for the volume dialog + related policy.
+ */
+public class Prefs {
+
+    public static final String PREF_ENABLE_PROTOTYPE = "pref_enable_prototype";  // not persistent
+    public static final String PREF_SHOW_ALARMS = "pref_show_alarms";
+    public static final String PREF_SHOW_SYSTEM = "pref_show_system";
+    public static final String PREF_SHOW_HEADERS = "pref_show_headers";
+    public static final String PREF_SHOW_FAKE_REMOTE_1 = "pref_show_fake_remote_1";
+    public static final String PREF_SHOW_FAKE_REMOTE_2 = "pref_show_fake_remote_2";
+    public static final String PREF_SHOW_FOOTER = "pref_show_footer";
+    public static final String PREF_ZEN_FOOTER = "pref_zen_footer";
+    public static final String PREF_ENABLE_AUTOMUTE = "pref_enable_automute";
+    public static final String PREF_ENABLE_SILENT_MODE = "pref_enable_silent_mode";
+    public static final String PREF_DEBUG_LOGGING = "pref_debug_logging";
+    public static final String PREF_SEND_LOGS = "pref_send_logs";
+    public static final String PREF_ADJUST_SYSTEM = "pref_adjust_system";
+    public static final String PREF_ADJUST_VOICE_CALLS = "pref_adjust_voice_calls";
+    public static final String PREF_ADJUST_BLUETOOTH_SCO = "pref_adjust_bluetooth_sco";
+    public static final String PREF_ADJUST_MEDIA = "pref_adjust_media";
+    public static final String PREF_ADJUST_ALARMS = "pref_adjust_alarms";
+    public static final String PREF_ADJUST_NOTIFICATION = "pref_adjust_notification";
+
+    public static final boolean DEFAULT_SHOW_HEADERS = true;
+    public static final boolean DEFAULT_SHOW_FOOTER = true;
+    public static final boolean DEFAULT_ENABLE_AUTOMUTE = true;
+    public static final boolean DEFAULT_ENABLE_SILENT_MODE = true;
+    public static final boolean DEFAULT_ZEN_FOOTER = true;
+
+    public static void unregisterCallbacks(Context c, OnSharedPreferenceChangeListener listener) {
+        prefs(c).unregisterOnSharedPreferenceChangeListener(listener);
+    }
+
+    public static void registerCallbacks(Context c, OnSharedPreferenceChangeListener listener) {
+        prefs(c).registerOnSharedPreferenceChangeListener(listener);
+    }
+
+    private static SharedPreferences prefs(Context context) {
+        return PreferenceManager.getDefaultSharedPreferences(context);
+    }
+
+    public static boolean get(Context context, String key, boolean def) {
+        return prefs(context).getBoolean(key, def);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
new file mode 100644
index 0000000..04640a2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
@@ -0,0 +1,109 @@
+/*
+ * 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.volume;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.AudioManager;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+
+abstract public class SafetyWarningDialog extends SystemUIDialog
+        implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener {
+
+    private static final String TAG = Util.logTag(SafetyWarningDialog.class);
+
+    private static final int KEY_CONFIRM_ALLOWED_AFTER = 1000; // milliseconds
+
+    private final Context mContext;
+    private final AudioManager mAudioManager;
+
+    private long mShowTime;
+    private boolean mNewVolumeUp;
+
+    public SafetyWarningDialog(Context context, AudioManager audioManager) {
+        super(context);
+        mContext = context;
+        mAudioManager = audioManager;
+
+        getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+        setMessage(mContext.getString(com.android.internal.R.string.safe_media_volume_warning));
+        setButton(DialogInterface.BUTTON_POSITIVE,
+                mContext.getString(com.android.internal.R.string.yes), this);
+        setButton(DialogInterface.BUTTON_NEGATIVE,
+                mContext.getString(com.android.internal.R.string.no), (OnClickListener) null);
+        setOnDismissListener(this);
+
+        final IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+        context.registerReceiver(mReceiver, filter);
+    }
+
+    abstract protected void cleanUp();
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && event.getRepeatCount() == 0) {
+            mNewVolumeUp = true;
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mNewVolumeUp
+                && (System.currentTimeMillis() - mShowTime) > KEY_CONFIRM_ALLOWED_AFTER) {
+            if (D.BUG) Log.d(TAG, "Confirmed warning via VOLUME_UP");
+            mAudioManager.disableSafeMediaVolume();
+            dismiss();
+        }
+        return super.onKeyUp(keyCode, event);
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        mAudioManager.disableSafeMediaVolume();
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        mShowTime = System.currentTimeMillis();
+    }
+
+    @Override
+    public void onDismiss(DialogInterface unused) {
+        mContext.unregisterReceiver(mReceiver);
+        cleanUp();
+    }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+                if (D.BUG) Log.d(TAG, "Received ACTION_CLOSE_SYSTEM_DIALOGS");
+                cancel();
+                cleanUp();
+            }
+        }
+    };
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java b/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
index 5f5b881..4f20ac7 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
@@ -60,17 +60,14 @@
             final Object tag = c.getTag();
             final boolean selected = Objects.equals(mSelectedValue, tag);
             c.setSelected(selected);
-            c.getCompoundDrawables()[1].setTint(mContext.getColor(selected
-                    ? R.color.segmented_button_selected : R.color.segmented_button_unselected));
         }
         fireOnSelected();
     }
 
-    public void addButton(int labelResId, int iconResId, Object value) {
+    public void addButton(int labelResId, Object value) {
         final Button b = (Button) mInflater.inflate(R.layout.segmented_button, this, false);
         b.setTag(LABEL_RES_KEY, labelResId);
         b.setText(labelResId);
-        b.setCompoundDrawablesWithIntrinsicBounds(0, iconResId, 0, 0);
         final LayoutParams lp = (LayoutParams) b.getLayoutParams();
         if (getChildCount() == 0) {
             lp.leftMargin = lp.rightMargin = 0; // first button has no margin
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SpTexts.java b/packages/SystemUI/src/com/android/systemui/volume/SpTexts.java
new file mode 100644
index 0000000..d8e53db
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/SpTexts.java
@@ -0,0 +1,78 @@
+/*
+ * 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.volume;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.ArrayMap;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
+import android.widget.TextView;
+
+/**
+ * Capture initial sp values for registered textviews, and update properly when configuration
+ * changes.
+ */
+public class SpTexts {
+
+    private final Context mContext;
+    private final ArrayMap<TextView, Integer> mTexts = new ArrayMap<>();
+
+    public SpTexts(Context context) {
+        mContext = context;
+    }
+
+    public int add(final TextView text) {
+        if (text == null) return 0;
+        final Resources res = mContext.getResources();
+        final float fontScale = res.getConfiguration().fontScale;
+        final float density = res.getDisplayMetrics().density;
+        final float px = text.getTextSize();
+        final int sp = (int)(px / fontScale / density);
+        mTexts.put(text, sp);
+        text.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+            @Override
+            public void onViewDetachedFromWindow(View v) {
+            }
+
+            @Override
+            public void onViewAttachedToWindow(View v) {
+               setTextSizeH(text, sp);
+            }
+        });
+        return sp;
+    }
+
+    public void update() {
+        if (mTexts.isEmpty()) return;
+        mTexts.keyAt(0).post(mUpdateAll);
+    }
+
+    private void setTextSizeH(TextView text, int sp) {
+        text.setTextSize(TypedValue.COMPLEX_UNIT_SP, sp);
+    }
+
+    private final Runnable mUpdateAll = new Runnable() {
+        @Override
+        public void run() {
+            for (int i = 0; i < mTexts.size(); i++) {
+                setTextSizeH(mTexts.keyAt(i), mTexts.valueAt(i));
+            }
+        }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Util.java b/packages/SystemUI/src/com/android/systemui/volume/Util.java
new file mode 100644
index 0000000..78baf67
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/Util.java
@@ -0,0 +1,167 @@
+/*
+ * 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.volume;
+
+import android.media.AudioManager;
+import android.media.MediaMetadata;
+import android.media.VolumeProvider;
+import android.media.session.MediaController.PlaybackInfo;
+import android.media.session.PlaybackState;
+import android.service.notification.ZenModeConfig.DowntimeInfo;
+import android.view.View;
+import android.widget.TextView;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Objects;
+
+/**
+ * Static helpers for the volume dialog.
+ */
+class Util {
+
+    // Note: currently not shown (only used in the text footer)
+    private static final SimpleDateFormat HMMAA = new SimpleDateFormat("h:mm aa", Locale.US);
+
+    private static int[] AUDIO_MANAGER_FLAGS = new int[] {
+        AudioManager.FLAG_SHOW_UI,
+        AudioManager.FLAG_VIBRATE,
+        AudioManager.FLAG_PLAY_SOUND,
+        AudioManager.FLAG_ALLOW_RINGER_MODES,
+        AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE,
+        AudioManager.FLAG_SHOW_VIBRATE_HINT,
+        AudioManager.FLAG_SHOW_SILENT_HINT,
+        AudioManager.FLAG_FROM_KEY,
+        AudioManager.FLAG_SHOW_UI_WARNINGS,
+    };
+
+    private static String[] AUDIO_MANAGER_FLAG_NAMES = new String[] {
+        "SHOW_UI",
+        "VIBRATE",
+        "PLAY_SOUND",
+        "ALLOW_RINGER_MODES",
+        "REMOVE_SOUND_AND_VIBRATE",
+        "SHOW_VIBRATE_HINT",
+        "SHOW_SILENT_HINT",
+        "FROM_KEY",
+        "SHOW_UI_WARNINGS",
+    };
+
+    public static String logTag(Class<?> c) {
+        final String tag = "vol." + c.getSimpleName();
+        return tag.length() < 23 ? tag : tag.substring(0, 23);
+    }
+
+    public static String ringerModeToString(int ringerMode) {
+        switch (ringerMode) {
+            case AudioManager.RINGER_MODE_SILENT: return "RINGER_MODE_SILENT";
+            case AudioManager.RINGER_MODE_VIBRATE: return "RINGER_MODE_VIBRATE";
+            case AudioManager.RINGER_MODE_NORMAL: return "RINGER_MODE_NORMAL";
+            default: return "RINGER_MODE_UNKNOWN_" + ringerMode;
+        }
+    }
+
+    public static String mediaMetadataToString(MediaMetadata metadata) {
+        return metadata.getDescription().toString();
+    }
+
+    public static String playbackInfoToString(PlaybackInfo info) {
+        if (info == null) return null;
+        final String type = playbackInfoTypeToString(info.getPlaybackType());
+        final String vc = volumeProviderControlToString(info.getVolumeControl());
+        return String.format("PlaybackInfo[vol=%s,max=%s,type=%s,vc=%s],atts=%s",
+                info.getCurrentVolume(), info.getMaxVolume(), type, vc, info.getAudioAttributes());
+    }
+
+    public static String playbackInfoTypeToString(int type) {
+        switch (type) {
+            case PlaybackInfo.PLAYBACK_TYPE_LOCAL: return "LOCAL";
+            case PlaybackInfo.PLAYBACK_TYPE_REMOTE: return "REMOTE";
+            default: return "UNKNOWN_" + type;
+        }
+    }
+
+    public static String playbackStateStateToString(int state) {
+        switch (state) {
+            case PlaybackState.STATE_NONE: return "STATE_NONE";
+            case PlaybackState.STATE_STOPPED: return "STATE_STOPPED";
+            case PlaybackState.STATE_PAUSED: return "STATE_PAUSED";
+            case PlaybackState.STATE_PLAYING: return "STATE_PLAYING";
+            default: return "UNKNOWN_" + state;
+        }
+    }
+
+    public static String volumeProviderControlToString(int control) {
+        switch (control) {
+            case VolumeProvider.VOLUME_CONTROL_ABSOLUTE: return "VOLUME_CONTROL_ABSOLUTE";
+            case VolumeProvider.VOLUME_CONTROL_FIXED: return "VOLUME_CONTROL_FIXED";
+            case VolumeProvider.VOLUME_CONTROL_RELATIVE: return "VOLUME_CONTROL_RELATIVE";
+            default: return "VOLUME_CONTROL_UNKNOWN_" + control;
+        }
+    }
+
+    public static String playbackStateToString(PlaybackState playbackState) {
+        if (playbackState == null) return null;
+        return playbackStateStateToString(playbackState.getState()) + " " + playbackState;
+    }
+
+    public static String audioManagerFlagsToString(int value) {
+        return bitFieldToString(value, AUDIO_MANAGER_FLAGS, AUDIO_MANAGER_FLAG_NAMES);
+    }
+
+    private static String bitFieldToString(int value, int[] values, String[] names) {
+        if (value == 0) return "";
+        final StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < values.length; i++) {
+            if ((value & values[i]) != 0) {
+                if (sb.length() > 0) sb.append(',');
+                sb.append(names[i]);
+            }
+            value &= ~values[i];
+        }
+        if (value != 0) {
+            if (sb.length() > 0) sb.append(',');
+            sb.append("UNKNOWN_").append(value);
+        }
+        return sb.toString();
+    }
+
+    public static String getShortTime(long millis) {
+        return HMMAA.format(new Date(millis));
+    }
+
+    public static String getShortTime(DowntimeInfo info) {
+        return ((info.endHour + 1) % 12) + ":" + (info.endMinute < 10 ? " " : "") + info.endMinute;
+    }
+
+    public static void setText(TextView tv, CharSequence text) {
+        if (Objects.equals(tv.getText(), text)) return;
+        tv.setText(text);
+    }
+
+    public static final void setVisOrGone(View v, boolean vis) {
+        if (v == null || (v.getVisibility() == View.VISIBLE) == vis) return;
+        v.setVisibility(vis ? View.VISIBLE : View.GONE);
+    }
+
+    public static final void setVisOrInvis(View v, boolean vis) {
+        if (v == null || (v.getVisibility() == View.VISIBLE) == vis) return;
+        v.setVisibility(vis ? View.VISIBLE : View.INVISIBLE);
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
index e3f8f3d..1f0ee57 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
@@ -16,10 +16,18 @@
 
 package com.android.systemui.volume;
 
+import android.content.res.Configuration;
+
 import com.android.systemui.DemoMode;
 import com.android.systemui.statusbar.policy.ZenModeController;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 public interface VolumeComponent extends DemoMode {
     ZenModeController getZenController();
     void dismissNow();
+    void onConfigurationChanged(Configuration newConfig);
+    void dump(FileDescriptor fd, PrintWriter pw, String[] args);
+    void register();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
new file mode 100644
index 0000000..d8b3965
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -0,0 +1,1069 @@
+/*
+ * 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.volume;
+
+import android.animation.LayoutTransition;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.annotation.SuppressLint;
+import android.app.Dialog;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.provider.Settings.Global;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.DowntimeInfo;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.SparseBooleanArray;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLayoutChangeListener;
+import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
+import android.view.ViewGroup.MarginLayoutParams;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.volume.VolumeDialogController.State;
+import com.android.systemui.volume.VolumeDialogController.StreamState;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Visual presentation of the volume dialog.
+ *
+ * A client of VolumeDialogController and its state model.
+ *
+ * Methods ending in "H" must be called on the (ui) handler.
+ */
+public class VolumeDialog {
+    private static final String TAG = Util.logTag(VolumeDialog.class);
+
+    private static final long USER_ATTEMPT_GRACE_PERIOD = 1000;
+    private static final int WAIT_FOR_RIPPLE = 200;
+    private static final int UPDATE_ANIMATION_DURATION = 80;
+
+    private final Context mContext;
+    private final H mHandler = new H();
+    private final VolumeDialogController mController;
+
+    private final CustomDialog mDialog;
+    private final ViewGroup mDialogView;
+    private final ViewGroup mDialogContentView;
+    private final ImageButton mExpandButton;
+    private final TextView mFootlineText;
+    private final Button mFootlineAction;
+    private final View mSettingsButton;
+    private final View mFooter;
+    private final List<VolumeRow> mRows = new ArrayList<VolumeRow>();
+    private final SpTexts mSpTexts;
+    private final SparseBooleanArray mDynamic = new SparseBooleanArray();
+    private final KeyguardManager mKeyguard;
+    private final int mExpandButtonAnimationDuration;
+    private final View mTextFooter;
+    private final ZenFooter mZenFooter;
+    private final LayoutTransition mLayoutTransition;
+    private final Object mSafetyWarningLock = new Object();
+
+    private boolean mShowing;
+    private boolean mExpanded;
+    private int mActiveStream;
+    private boolean mShowHeaders = Prefs.DEFAULT_SHOW_HEADERS;
+    private boolean mShowFooter = Prefs.DEFAULT_SHOW_FOOTER;
+    private boolean mShowZenFooter = Prefs.DEFAULT_ZEN_FOOTER;
+    private boolean mAutomute = Prefs.DEFAULT_ENABLE_AUTOMUTE;
+    private boolean mSilentMode = Prefs.DEFAULT_ENABLE_SILENT_MODE;
+    private State mState;
+    private int mExpandButtonRes;
+    private boolean mExpanding;
+    private SafetyWarningDialog mSafetyWarning;
+
+    public VolumeDialog(Context context, VolumeDialogController controller,
+            ZenModeController zenModeController) {
+        mContext = context;
+        mController = controller;
+        mSpTexts = new SpTexts(mContext);
+        mKeyguard = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
+
+        mDialog = new CustomDialog(mContext);
+
+        final Window window = mDialog.getWindow();
+        window.requestFeature(Window.FEATURE_NO_TITLE);
+        window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+        window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        mDialog.setCanceledOnTouchOutside(true);
+        final Resources res = mContext.getResources();
+        final WindowManager.LayoutParams lp = window.getAttributes();
+        lp.type = WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
+        lp.format = PixelFormat.TRANSLUCENT;
+        lp.setTitle(VolumeDialog.class.getSimpleName());
+        lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
+        lp.windowAnimations = R.style.VolumeDialogAnimations;
+        lp.y = res.getDimensionPixelSize(R.dimen.volume_offset_top);
+        lp.gravity = Gravity.TOP;
+        window.setAttributes(lp);
+
+        mDialog.setContentView(R.layout.volume_dialog);
+        mDialogView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog);
+        mDialogContentView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog_content);
+        mExpandButton = (ImageButton) mDialogView.findViewById(R.id.volume_expand_button);
+        mExpandButton.setOnClickListener(mClickExpand);
+        updateWindowWidthH();
+        updateExpandButtonH();
+        mLayoutTransition = new LayoutTransition();
+        mLayoutTransition.setDuration(new ValueAnimator().getDuration() / 2);
+        mLayoutTransition.disableTransitionType(LayoutTransition.DISAPPEARING);
+        mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
+        mDialogContentView.setLayoutTransition(mLayoutTransition);
+
+        addRow(AudioManager.STREAM_RING,
+                R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true);
+        addRow(AudioManager.STREAM_MUSIC,
+                R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true);
+        addRow(AudioManager.STREAM_ALARM,
+                R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, false);
+        addRow(AudioManager.STREAM_VOICE_CALL,
+                R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false);
+        addRow(AudioManager.STREAM_BLUETOOTH_SCO,
+                R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false);
+        addRow(AudioManager.STREAM_SYSTEM,
+                R.drawable.ic_volume_system, R.drawable.ic_volume_system_mute, false);
+
+        mTextFooter = mDialog.findViewById(R.id.volume_text_footer);
+        mFootlineText = (TextView) mDialog.findViewById(R.id.volume_footline_text);
+        mSpTexts.add(mFootlineText);
+        mFootlineAction = (Button) mDialog.findViewById(R.id.volume_footline_action_button);
+        mSpTexts.add(mFootlineAction);
+        mFooter = mDialog.findViewById(R.id.volume_footer);
+        mSettingsButton = mDialog.findViewById(R.id.volume_settings_button);
+        mSettingsButton.setOnClickListener(mClickSettings);
+        mExpandButtonAnimationDuration = res.getInteger(R.integer.volume_expand_animation_duration);
+        mZenFooter = (ZenFooter) mDialog.findViewById(R.id.volume_zen_footer);
+        mZenFooter.init(zenModeController, mZenFooterCallback);
+
+        controller.addCallback(mControllerCallbackH, mHandler);
+        controller.getState();
+    }
+
+    private void updateWindowWidthH() {
+        final ViewGroup.LayoutParams lp = mDialogView.getLayoutParams();
+        final DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
+        if (D.BUG) Log.d(TAG, "updateWindowWidth dm.w=" + dm.widthPixels);
+        int w = dm.widthPixels;
+        final int max = mContext.getResources()
+                .getDimensionPixelSize(R.dimen.standard_notification_panel_width);
+        if (w > max) {
+            w = max;
+        }
+        w -= mContext.getResources().getDimensionPixelSize(R.dimen.notification_side_padding) * 2;
+        lp.width = w;
+        mDialogView.setLayoutParams(lp);
+    }
+
+    public void setStreamImportant(int stream, boolean important) {
+        mHandler.obtainMessage(H.SET_STREAM_IMPORTANT, stream, important ? 1 : 0).sendToTarget();
+    }
+
+    public void setShowHeaders(boolean showHeaders) {
+        if (showHeaders == mShowHeaders) return;
+        mShowHeaders = showHeaders;
+        mHandler.sendEmptyMessage(H.RECHECK_ALL);
+    }
+
+    public void setShowFooter(boolean show) {
+        if (mShowFooter == show) return;
+        mShowFooter = show;
+        mHandler.sendEmptyMessage(H.RECHECK_ALL);
+    }
+
+    public void setZenFooter(boolean zen) {
+        if (mShowZenFooter == zen) return;
+        mShowZenFooter = zen;
+        mHandler.sendEmptyMessage(H.RECHECK_ALL);
+    }
+
+    public void setAutomute(boolean automute) {
+        if (mAutomute == automute) return;
+        mAutomute = automute;
+        mHandler.sendEmptyMessage(H.RECHECK_ALL);
+    }
+
+    public void setSilentMode(boolean silentMode) {
+        if (mSilentMode == silentMode) return;
+        mSilentMode = silentMode;
+        mHandler.sendEmptyMessage(H.RECHECK_ALL);
+    }
+
+    private void addRow(int stream, int iconRes, int iconMuteRes, boolean important) {
+        final VolumeRow row = initRow(stream, iconRes, iconMuteRes, important);
+        if (!mRows.isEmpty()) {
+            final View v = new View(mContext);
+            final int h = mContext.getResources()
+                    .getDimensionPixelSize(R.dimen.volume_slider_interspacing);
+            final LinearLayout.LayoutParams lp =
+                    new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, h);
+            mDialogContentView.addView(v, mDialogContentView.getChildCount() - 1, lp);
+            row.space = v;
+        }
+        row.settingsButton.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                if (D.BUG) Log.d(TAG, "onLayoutChange"
+                        + " old=" + new Rect(oldLeft, oldTop, oldRight, oldBottom).toShortString()
+                        + " new=" + new Rect(left,top,right,bottom).toShortString());
+                if (oldLeft != left || oldTop != top) {
+                    for (int i = 0; i < mDialogContentView.getChildCount(); i++) {
+                        final View c = mDialogContentView.getChildAt(i);
+                        if (!c.isShown()) continue;
+                        if (c == row.view) {
+                            repositionExpandAnim(row);
+                        }
+                        return;
+                    }
+                }
+            }
+        });
+        // add new row just before the footer
+        mDialogContentView.addView(row.view, mDialogContentView.getChildCount() - 1);
+        mRows.add(row);
+    }
+
+    private boolean isAttached() {
+        return mDialogContentView != null && mDialogContentView.isAttachedToWindow();
+    }
+
+    private VolumeRow getActiveRow() {
+        for (VolumeRow row : mRows) {
+            if (row.stream == mActiveStream) {
+                return row;
+            }
+        }
+        return mRows.get(0);
+    }
+
+    private VolumeRow findRow(int stream) {
+        for (VolumeRow row : mRows) {
+            if (row.stream == stream) return row;
+        }
+        return null;
+    }
+
+    private void repositionExpandAnim(VolumeRow row) {
+        final int[] loc = new int[2];
+        row.settingsButton.getLocationInWindow(loc);
+        final MarginLayoutParams mlp = (MarginLayoutParams) mDialogView.getLayoutParams();
+        final int x = loc[0] - mlp.leftMargin;
+        final int y = loc[1] - mlp.topMargin;
+        if (D.BUG) Log.d(TAG, "repositionExpandAnim x=" + x + " y=" + y);
+        mExpandButton.setTranslationX(x);
+        mExpandButton.setTranslationY(y);
+    }
+
+    public void dump(PrintWriter writer) {
+        writer.println(VolumeDialog.class.getSimpleName() + " state:");
+        writer.print("  mShowing: "); writer.println(mShowing);
+        writer.print("  mExpanded: "); writer.println(mExpanded);
+        writer.print("  mExpanding: "); writer.println(mExpanding);
+        writer.print("  mActiveStream: "); writer.println(mActiveStream);
+        writer.print("  mDynamic: "); writer.println(mDynamic);
+        writer.print("  mShowHeaders: "); writer.println(mShowHeaders);
+        writer.print("  mShowFooter: "); writer.println(mShowFooter);
+        writer.print("  mAutomute: "); writer.println(mAutomute);
+        writer.print("  mSilentMode: "); writer.println(mSilentMode);
+    }
+
+    private static int getImpliedLevel(SeekBar seekBar, int progress) {
+        final int m = seekBar.getMax();
+        final int n = m / 100 - 1;
+        final int level = progress == 0 ? 0
+                : progress == m ? (m / 100) : (1 + (int)((progress / (float) m) * n));
+        return level;
+    }
+
+    @SuppressLint("InflateParams")
+    private VolumeRow initRow(final int stream, int iconRes, int iconMuteRes, boolean important) {
+        final VolumeRow row = new VolumeRow();
+        row.stream = stream;
+        row.iconRes = iconRes;
+        row.iconMuteRes = iconMuteRes;
+        row.important = important;
+        row.view = mDialog.getLayoutInflater().inflate(R.layout.volume_dialog_row, null);
+        row.view.setTag(row);
+        row.header = (TextView) row.view.findViewById(R.id.volume_row_header);
+        mSpTexts.add(row.header);
+        row.slider = (SeekBar) row.view.findViewById(R.id.volume_row_slider);
+        row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
+
+        // forward events above the slider into the slider
+        row.view.setOnTouchListener(new OnTouchListener() {
+            private final Rect mSliderHitRect = new Rect();
+            private boolean mDragging;
+
+            @SuppressLint("ClickableViewAccessibility")
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                row.slider.getHitRect(mSliderHitRect);
+                if (!mDragging && event.getActionMasked() == MotionEvent.ACTION_DOWN
+                        && event.getY() < mSliderHitRect.top) {
+                    mDragging = true;
+                }
+                if (mDragging) {
+                    event.offsetLocation(-mSliderHitRect.left, -mSliderHitRect.top);
+                    row.slider.dispatchTouchEvent(event);
+                    if (event.getActionMasked() == MotionEvent.ACTION_UP
+                            || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
+                        mDragging = false;
+                    }
+                    return true;
+                }
+                return false;
+            }
+        });
+        row.icon = (ImageButton) row.view.findViewById(R.id.volume_row_icon);
+        row.icon.setImageResource(iconRes);
+        row.icon.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Events.writeEvent(Events.EVENT_ICON_CLICK, row.stream, row.iconState);
+                mController.setActiveStream(row.stream);
+                if (row.stream == AudioManager.STREAM_RING) {
+                    final boolean hasVibrator = mController.hasVibrator();
+                    if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
+                        if (hasVibrator) {
+                            mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
+                        } else {
+                            final boolean wasZero = row.ss.level == 0;
+                            mController.setStreamVolume(stream, wasZero ? row.lastAudibleLevel : 0);
+                        }
+                    } else {
+                        mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
+                        if (row.ss.level == 0) {
+                            mController.setStreamVolume(stream, 1);
+                        }
+                    }
+                } else {
+                    if (mAutomute && !row.ss.muteSupported) {
+                        final boolean vmute = row.ss.level == 0;
+                        mController.setStreamVolume(stream, vmute ? row.lastAudibleLevel : 0);
+                    } else {
+                        final boolean mute = !row.ss.muted;
+                        mController.setStreamMute(stream, mute);
+                        if (mAutomute) {
+                            if (!mute && row.ss.level == 0) {
+                                mController.setStreamVolume(stream, 1);
+                            }
+                        }
+                    }
+                }
+                row.userAttempt = 0;  // reset the grace period, slider should update immediately
+            }
+        });
+        row.settingsButton = (ImageButton) row.view.findViewById(R.id.volume_settings_button);
+        row.settingsButton.setOnClickListener(mClickSettings);
+        return row;
+    }
+
+    public void destroy() {
+        mController.removeCallback(mControllerCallbackH);
+    }
+
+    public void show(int reason) {
+        mHandler.obtainMessage(H.SHOW, reason, 0).sendToTarget();
+    }
+
+    public void dismiss(int reason) {
+        mHandler.obtainMessage(H.DISMISS, reason, 0).sendToTarget();
+    }
+
+    protected void onSettingsClickedH() {
+        // hook for subclasses
+    }
+
+    protected void onZenSettingsClickedH() {
+        // hook for subclasses
+    }
+
+    private void showH(int reason) {
+        mHandler.removeMessages(H.SHOW);
+        mHandler.removeMessages(H.DISMISS);
+        rescheduleTimeoutH();
+        if (mShowing) return;
+        mShowing = true;
+        mDialog.show();
+        Events.writeEvent(Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
+        mController.notifyVisible(true);
+    }
+
+    protected void rescheduleTimeoutH() {
+        mHandler.removeMessages(H.DISMISS);
+        final int timeout = computeTimeoutH();
+        if (D.BUG) Log.d(TAG, "rescheduleTimeout " + timeout);
+        mHandler.sendMessageDelayed(mHandler
+                .obtainMessage(H.DISMISS, Events.DISMISS_REASON_TIMEOUT, 0), timeout);
+        mController.userActivity();
+    }
+
+    private int computeTimeoutH() {
+        if (mZenFooter != null && mZenFooter.isFooterExpanded()) return 10000;
+        if (mSafetyWarning != null) return 5000;
+        if (mExpanded || mExpanding) return 5000;
+        if (mActiveStream == AudioManager.STREAM_MUSIC) return 1500;
+        return 3000;
+    }
+
+    protected void dismissH(int reason) {
+        mHandler.removeMessages(H.DISMISS);
+        mHandler.removeMessages(H.SHOW);
+        if (!mShowing) return;
+        mShowing = false;
+        mDialog.dismiss();
+        Events.writeEvent(Events.EVENT_DISMISS_DIALOG, reason);
+        setExpandedH(false);
+        mController.notifyVisible(false);
+        synchronized (mSafetyWarningLock) {
+            if (mSafetyWarning != null) {
+                if (D.BUG) Log.d(TAG, "SafetyWarning dismissed");
+                mSafetyWarning.dismiss();
+            }
+        }
+    }
+
+    private void setExpandedH(boolean expanded) {
+        if (mExpanded == expanded) return;
+        mExpanded = expanded;
+        mExpanding = isAttached();
+        if (D.BUG) Log.d(TAG, "setExpandedH " + expanded);
+        updateRowsH();
+        if (mExpanding) {
+            final Drawable d = mExpandButton.getDrawable();
+            if (d instanceof AnimatedVectorDrawable) {
+                // workaround to reset drawable
+                final AnimatedVectorDrawable avd = (AnimatedVectorDrawable) d.getConstantState()
+                        .newDrawable();
+                mExpandButton.setImageDrawable(avd);
+                avd.start();
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        mExpanding = false;
+                        updateExpandButtonH();
+                        rescheduleTimeoutH();
+                    }
+                }, mExpandButtonAnimationDuration);
+            }
+        }
+        rescheduleTimeoutH();
+    }
+
+    private void updateExpandButtonH() {
+        mExpandButton.setClickable(!mExpanding);
+        if (mExpanding && isAttached()) return;
+        final int res = mExpanded ? R.drawable.ic_volume_collapse_animation
+                : R.drawable.ic_volume_expand_animation;
+        if (res == mExpandButtonRes) return;
+        mExpandButtonRes = res;
+        mExpandButton.setImageResource(res);
+    }
+
+    private boolean isVisibleH(VolumeRow row, boolean isActive) {
+        return mExpanded && row.view.getVisibility() == View.VISIBLE
+                || (mExpanded && (row.important || isActive))
+                || !mExpanded && isActive;
+    }
+
+    private void updateRowsH() {
+        final VolumeRow activeRow = getActiveRow();
+        updateFooterH();
+        updateExpandButtonH();
+        final boolean footerVisible = mFooter.getVisibility() == View.VISIBLE;
+        if (!mShowing) {
+            trimObsoleteH();
+        }
+        // first, find the last visible row
+        VolumeRow lastVisible = null;
+        for (VolumeRow row : mRows) {
+            final boolean isActive = row == activeRow;
+            if (isVisibleH(row, isActive)) {
+                lastVisible = row;
+            }
+        }
+        // apply changes to all rows
+        for (VolumeRow row : mRows) {
+            final boolean isActive = row == activeRow;
+            final boolean visible = isVisibleH(row, isActive);
+            Util.setVisOrGone(row.view, visible);
+            Util.setVisOrGone(row.space, visible && mExpanded);
+            final int expandButtonRes = mExpanded ? R.drawable.ic_volume_settings : 0;
+            if (expandButtonRes != row.cachedExpandButtonRes) {
+                row.cachedExpandButtonRes = expandButtonRes;
+                if (expandButtonRes == 0) {
+                    row.settingsButton.setImageDrawable(null);
+                } else {
+                    row.settingsButton.setImageResource(expandButtonRes);
+                }
+            }
+            Util.setVisOrInvis(row.settingsButton,
+                     mExpanded && (!footerVisible && row == lastVisible));
+            row.header.setAlpha(mExpanded && isActive ? 1 : 0.5f);
+        }
+    }
+
+    private void trimObsoleteH() {
+        for (int i = mRows.size() -1; i >= 0; i--) {
+            final VolumeRow row = mRows.get(i);
+            if (row.ss == null || !row.ss.dynamic) continue;
+            if (!mDynamic.get(row.stream)) {
+                mRows.remove(i);
+                mDialogContentView.removeView(row.view);
+                mDialogContentView.removeView(row.space);
+            }
+        }
+    }
+
+    private void onStateChangedH(State state) {
+        mState = state;
+        mDynamic.clear();
+        // add any new dynamic rows
+        for (int i = 0; i < state.states.size(); i++) {
+            final int stream = state.states.keyAt(i);
+            final StreamState ss = state.states.valueAt(i);
+            if (!ss.dynamic) continue;
+            mDynamic.put(stream, true);
+            if (findRow(stream) == null) {
+                addRow(stream, R.drawable.ic_volume_remote, R.drawable.ic_volume_remote_mute, true);
+            }
+        }
+
+        if (mActiveStream != state.activeStream) {
+            mActiveStream = state.activeStream;
+            updateRowsH();
+            rescheduleTimeoutH();
+        }
+        for (VolumeRow row : mRows) {
+            updateVolumeRowH(row);
+        }
+        updateFooterH();
+    }
+
+    private void updateTextFooterH() {
+        final boolean zen = mState.zenMode != Global.ZEN_MODE_OFF;
+        final boolean wasVisible = mFooter.getVisibility() == View.VISIBLE;
+        Util.setVisOrGone(mTextFooter, mExpanded && mShowFooter && (zen || mShowing && wasVisible));
+        if (mTextFooter.getVisibility() == View.VISIBLE) {
+            String text = null;
+            String action = null;
+            if (mState.exitCondition != null) {
+                final long countdown = ZenModeConfig.tryParseCountdownConditionId(mState
+                        .exitCondition.id);
+                if (countdown != 0) {
+                    text = mContext.getString(R.string.volume_dnd_ends_at,
+                            Util.getShortTime(countdown));
+                    action = mContext.getString(R.string.volume_end_now);
+                } else {
+                    final DowntimeInfo info = ZenModeConfig.tryParseDowntimeConditionId(mState.
+                            exitCondition.id);
+                    if (info != null) {
+                        text = mContext.getString(R.string.volume_dnd_ends_at,
+                                Util.getShortTime(info));
+                        action = mContext.getString(R.string.volume_end_now);
+                    }
+                }
+            }
+            if (text == null) {
+                text = mContext.getString(R.string.volume_dnd_is_on);
+            }
+            if (action == null) {
+                action = mContext.getString(R.string.volume_turn_off);
+            }
+            Util.setText(mFootlineText, text);
+            Util.setText(mFootlineAction, action);
+            mFootlineAction.setOnClickListener(mTurnOffDnd);
+        }
+        Util.setVisOrGone(mFootlineText, zen);
+        Util.setVisOrGone(mFootlineAction, zen);
+    }
+
+    private void updateFooterH() {
+        if (!mShowFooter) {
+            Util.setVisOrGone(mFooter, false);
+            return;
+        }
+        if (mShowZenFooter) {
+            Util.setVisOrGone(mTextFooter, false);
+            final boolean ringActive = mActiveStream == AudioManager.STREAM_RING;
+            Util.setVisOrGone(mZenFooter, mZenFooter.isZen() && ringActive
+                    || mShowing && (mExpanded || mZenFooter.getVisibility() == View.VISIBLE));
+            mZenFooter.update();
+        } else {
+            Util.setVisOrGone(mZenFooter, false);
+            updateTextFooterH();
+        }
+    }
+
+    private void updateVolumeRowH(VolumeRow row) {
+        if (mState == null) return;
+        final StreamState ss = mState.states.get(row.stream);
+        if (ss == null) return;
+        row.ss = ss;
+        if (ss.level > 0) {
+            row.lastAudibleLevel = ss.level;
+        }
+        final boolean isRingStream = row.stream == AudioManager.STREAM_RING;
+        final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM;
+        final boolean isRingVibrate = isRingStream
+                && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
+        final boolean isNoned = (isRingStream || isSystemStream)
+                && mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+        final boolean isLimited = isRingStream
+                && mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+
+        // update slider max
+        final int max = ss.levelMax * 100;
+        if (max != row.slider.getMax()) {
+            row.slider.setMax(max);
+        }
+
+        // update header visible
+        if (row.cachedShowHeaders != mShowHeaders) {
+            row.cachedShowHeaders = mShowHeaders;
+            Util.setVisOrGone(row.header, mShowHeaders);
+        }
+
+        // update header text
+        final String text;
+        if (isNoned) {
+            text = mContext.getString(R.string.volume_stream_muted_dnd, ss.name);
+        } else if (isRingVibrate && isLimited) {
+            text = mContext.getString(R.string.volume_stream_vibrate_dnd, ss.name);
+        } else if (isRingVibrate) {
+            text = mContext.getString(R.string.volume_stream_vibrate, ss.name);
+        } else if (ss.muted || mAutomute && ss.level == 0) {
+            text = mContext.getString(R.string.volume_stream_muted, ss.name);
+        } else if (isLimited) {
+            text = mContext.getString(R.string.volume_stream_limited_dnd, ss.name);
+        } else {
+            text = ss.name;
+        }
+        Util.setText(row.header, text);
+
+        // update icon
+        final boolean iconEnabled = mAutomute || ss.muteSupported;
+        row.icon.setEnabled(iconEnabled);
+        row.icon.setAlpha(iconEnabled ? 1 : 0.5f);
+        final int iconRes =
+                isRingVibrate ? R.drawable.ic_volume_ringer_vibrate
+                : ss.routedToBluetooth ?
+                        (ss.muted ? R.drawable.ic_volume_bt_mute : R.drawable.ic_volume_bt)
+                : mAutomute && ss.level == 0 ? row.iconMuteRes
+                : (ss.muted ? row.iconMuteRes : row.iconRes);
+        if (iconRes != row.cachedIconRes) {
+            if (row.cachedIconRes != 0 && isRingVibrate) {
+                mController.vibrate();
+            }
+            row.cachedIconRes = iconRes;
+            row.icon.setImageResource(iconRes);
+        }
+        row.iconState =
+                iconRes == R.drawable.ic_volume_ringer_vibrate ? Events.ICON_STATE_VIBRATE
+                : (iconRes == R.drawable.ic_volume_bt_mute || iconRes == row.iconMuteRes)
+                        ? Events.ICON_STATE_MUTE
+                : (iconRes == R.drawable.ic_volume_bt || iconRes == row.iconRes)
+                        ? Events.ICON_STATE_UNMUTE
+                : Events.ICON_STATE_UNKNOWN;
+
+        // update slider
+        updateVolumeRowSliderH(row);
+    }
+
+    private void updateVolumeRowSliderH(VolumeRow row) {
+        if (row.tracking) {
+            return;  // don't update if user is sliding
+        }
+        final int progress = row.slider.getProgress();
+        final int level = getImpliedLevel(row.slider, progress);
+        final boolean rowVisible = row.view.getVisibility() == View.VISIBLE;
+        final boolean inGracePeriod = (SystemClock.uptimeMillis() - row.userAttempt)
+                < USER_ATTEMPT_GRACE_PERIOD;
+        mHandler.removeMessages(H.RECHECK, row);
+        if (mShowing && rowVisible && inGracePeriod) {
+            if (D.BUG) Log.d(TAG, "inGracePeriod");
+            mHandler.sendMessageAtTime(mHandler.obtainMessage(H.RECHECK, row),
+                    row.userAttempt + USER_ATTEMPT_GRACE_PERIOD);
+            return;  // don't update if visible and in grace period
+        }
+        final int vlevel = row.ss.muted ? 0 : row.ss.level;
+        if (vlevel == level) {
+            if (mShowing && rowVisible) {
+                return;  // don't clamp if visible
+            }
+        }
+        final int newProgress = vlevel * 100;
+        if (progress != newProgress) {
+            if (mShowing && rowVisible) {
+                // animate!
+                if (row.anim != null && row.anim.isRunning()
+                        && row.animTargetProgress == newProgress) {
+                    return;  // already animating to the target progress
+                }
+                // start/update animation
+                if (row.anim == null) {
+                    row.anim = ObjectAnimator.ofInt(row.slider, "progress", progress, newProgress);
+                    row.anim.setInterpolator(new DecelerateInterpolator());
+                } else {
+                    row.anim.cancel();
+                    row.anim.setIntValues(progress, newProgress);
+                }
+                row.animTargetProgress = newProgress;
+                row.anim.setDuration(UPDATE_ANIMATION_DURATION);
+                row.anim.start();
+            } else {
+                // update slider directly to clamped value
+                if (row.anim != null) {
+                    row.anim.cancel();
+                }
+                row.slider.setProgress(newProgress);
+            }
+            if (mAutomute) {
+                if (vlevel == 0 && !row.ss.muted && row.stream == AudioManager.STREAM_MUSIC) {
+                    mController.setStreamMute(row.stream, true);
+                }
+            }
+        }
+    }
+
+    private void recheckH(VolumeRow row) {
+        if (row == null) {
+            if (D.BUG) Log.d(TAG, "recheckH ALL");
+            trimObsoleteH();
+            for (VolumeRow r : mRows) {
+                updateVolumeRowH(r);
+            }
+        } else {
+            if (D.BUG) Log.d(TAG, "recheckH " + row.stream);
+            updateVolumeRowH(row);
+        }
+    }
+
+    private void setStreamImportantH(int stream, boolean important) {
+        for (VolumeRow row : mRows) {
+            if (row.stream == stream) {
+                row.important = important;
+                return;
+            }
+        }
+    }
+
+    private void showSafetyWarningH(int flags) {
+        if ((flags & (AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_SHOW_UI_WARNINGS)) != 0
+                || mShowing) {
+            synchronized (mSafetyWarningLock) {
+                if (mSafetyWarning != null) {
+                    return;
+                }
+                mSafetyWarning = new SafetyWarningDialog(mContext, mController.getAudioManager()) {
+                    @Override
+                    protected void cleanUp() {
+                        synchronized (mSafetyWarningLock) {
+                            mSafetyWarning = null;
+                        }
+                        recheckH(null);
+                    }
+                };
+                mSafetyWarning.show();
+            }
+            recheckH(null);
+        }
+        rescheduleTimeoutH();
+    }
+
+    private final VolumeDialogController.Callbacks mControllerCallbackH
+            = new VolumeDialogController.Callbacks() {
+        @Override
+        public void onShowRequested(int reason) {
+            showH(reason);
+        }
+
+        @Override
+        public void onDismissRequested(int reason) {
+            dismissH(reason);
+        }
+
+        @Override
+        public void onScreenOff() {
+            dismissH(Events.DISMISS_REASON_SCREEN_OFF);
+        }
+
+        @Override
+        public void onStateChanged(State state) {
+            onStateChangedH(state);
+        }
+
+        @Override
+        public void onLayoutDirectionChanged(int layoutDirection) {
+            mDialogView.setLayoutDirection(layoutDirection);
+        }
+
+        @Override
+        public void onConfigurationChanged() {
+            updateWindowWidthH();
+            mSpTexts.update();
+        }
+
+        @Override
+        public void onShowVibrateHint() {
+            if (mSilentMode) {
+                mController.setRingerMode(AudioManager.RINGER_MODE_SILENT, false);
+            }
+        }
+
+        @Override
+        public void onShowSilentHint() {
+            if (mSilentMode) {
+                mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
+            }
+        }
+
+        @Override
+        public void onShowSafetyWarning(int flags) {
+            showSafetyWarningH(flags);
+        }
+    };
+
+    private final OnClickListener mClickExpand = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            if (mExpanding) return;
+            final boolean newExpand = !mExpanded;
+            Events.writeEvent(Events.EVENT_EXPAND, v);
+            setExpandedH(newExpand);
+        }
+    };
+
+    private final OnClickListener mClickSettings = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            mSettingsButton.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    Events.writeEvent(Events.EVENT_SETTINGS_CLICK);
+                    onSettingsClickedH();
+                }
+            }, WAIT_FOR_RIPPLE);
+        }
+    };
+
+    private final View.OnClickListener mTurnOffDnd = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            mSettingsButton.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    mController.setZenMode(Global.ZEN_MODE_OFF);
+                }
+            }, WAIT_FOR_RIPPLE);
+        }
+    };
+
+    private final ZenFooter.Callback mZenFooterCallback = new ZenFooter.Callback() {
+        @Override
+        public void onFooterExpanded() {
+            mHandler.sendEmptyMessage(H.RESCHEDULE_TIMEOUT);
+        }
+
+        @Override
+        public void onSettingsClicked() {
+            dismiss(Events.DISMISS_REASON_SETTINGS_CLICKED);
+            onZenSettingsClickedH();
+        }
+
+        @Override
+        public void onDoneClicked() {
+            dismiss(Events.DISMISS_REASON_DONE_CLICKED);
+        }
+    };
+
+    private final class H extends Handler {
+        private static final int SHOW = 1;
+        private static final int DISMISS = 2;
+        private static final int RECHECK = 3;
+        private static final int RECHECK_ALL = 4;
+        private static final int SET_STREAM_IMPORTANT = 5;
+        private static final int RESCHEDULE_TIMEOUT = 6;
+
+        public H() {
+            super(Looper.getMainLooper());
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case SHOW: showH(msg.arg1); break;
+                case DISMISS: dismissH(msg.arg1); break;
+                case RECHECK: recheckH((VolumeRow) msg.obj); break;
+                case RECHECK_ALL: recheckH(null); break;
+                case SET_STREAM_IMPORTANT: setStreamImportantH(msg.arg1, msg.arg2 != 0); break;
+                case RESCHEDULE_TIMEOUT: rescheduleTimeoutH(); break;
+            }
+        }
+    }
+
+    private final class CustomDialog extends Dialog {
+        public CustomDialog(Context context) {
+            super(context);
+        }
+
+        @Override
+        public boolean dispatchTouchEvent(MotionEvent ev) {
+            rescheduleTimeoutH();
+            return super.dispatchTouchEvent(ev);
+        }
+
+        @Override
+        protected void onStop() {
+            super.onStop();
+            mHandler.sendEmptyMessage(H.RECHECK_ALL);
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent event) {
+            if (isShowing()) {
+                if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+                    dismissH(Events.DISMISS_REASON_TOUCH_OUTSIDE);
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    private final class VolumeSeekBarChangeListener implements OnSeekBarChangeListener {
+        private final VolumeRow mRow;
+
+        private VolumeSeekBarChangeListener(VolumeRow row) {
+            mRow = row;
+        }
+
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+            if (mRow.ss == null) return;
+            if (D.BUG) Log.d(TAG, AudioSystem.streamToString(mRow.stream)
+                    + " onProgressChanged " + progress + " fromUser=" + fromUser);
+            if (!fromUser) return;
+            if (mRow.ss.levelMin > 0) {
+                final int minProgress = mRow.ss.levelMin * 100;
+                if (progress < minProgress) {
+                    seekBar.setProgress(minProgress);
+                }
+            }
+            final int userLevel = getImpliedLevel(seekBar, progress);
+            if (mRow.ss.level != userLevel || mRow.ss.muted && userLevel > 0) {
+                mRow.userAttempt = SystemClock.uptimeMillis();
+                if (mAutomute) {
+                    if (mRow.stream != AudioManager.STREAM_RING) {
+                        if (userLevel > 0 && mRow.ss.muted) {
+                            mController.setStreamMute(mRow.stream, false);
+                        }
+                        if (userLevel == 0 && mRow.ss.muteSupported && !mRow.ss.muted) {
+                            mController.setStreamMute(mRow.stream, true);
+                        }
+                    }
+                }
+                if (mRow.requestedLevel != userLevel) {
+                    mController.setStreamVolume(mRow.stream, userLevel);
+                    mRow.requestedLevel = userLevel;
+                    Events.writeEvent(Events.EVENT_TOUCH_LEVEL_CHANGED, mRow.stream, userLevel);
+                }
+            }
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+            if (D.BUG) Log.d(TAG, "onStartTrackingTouch"+ " " + mRow.stream);
+            mController.setActiveStream(mRow.stream);
+            mRow.tracking = true;
+        }
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+            if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream);
+            mRow.tracking = false;
+            mRow.userAttempt = SystemClock.uptimeMillis();
+            int userLevel = getImpliedLevel(seekBar, seekBar.getProgress());
+            if (mRow.ss.level != userLevel) {
+                mHandler.sendMessageDelayed(mHandler.obtainMessage(H.RECHECK, mRow),
+                        USER_ATTEMPT_GRACE_PERIOD);
+            }
+        }
+    }
+
+    private static class VolumeRow {
+        private View view;
+        private View space;
+        private TextView header;
+        private ImageButton icon;
+        private SeekBar slider;
+        private ImageButton settingsButton;
+        private int stream;
+        private StreamState ss;
+        private long userAttempt;  // last user-driven slider change
+        private boolean tracking;  // tracking slider touch
+        private int requestedLevel;
+        private int iconRes;
+        private int iconMuteRes;
+        private boolean important;
+        private int cachedIconRes;
+        private int iconState;  // from Events
+        private boolean cachedShowHeaders = Prefs.DEFAULT_SHOW_HEADERS;
+        private int cachedExpandButtonRes;
+        private ObjectAnimator anim;  // slider progress animation for non-touch-related updates
+        private int animTargetProgress;
+        private int lastAudibleLevel = 1;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
new file mode 100644
index 0000000..741e498
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -0,0 +1,120 @@
+/*
+ * 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.volume;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.media.AudioManager;
+import android.media.VolumePolicy;
+import android.os.Bundle;
+import android.os.Handler;
+
+import com.android.systemui.SystemUI;
+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 java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Implementation of VolumeComponent backed by the new volume dialog.
+ */
+public class VolumeDialogComponent implements VolumeComponent {
+    private final SystemUI mSysui;
+    private final Context mContext;
+    private final VolumeDialogController mController;
+    private final ZenModeController mZenModeController;
+    private final VolumeDialog mDialog;
+
+    public VolumeDialogComponent(SystemUI sysui, Context context, Handler handler,
+            ZenModeController zen) {
+        mSysui = sysui;
+        mContext = context;
+        mController = new VolumeDialogController(context, null) {
+            @Override
+            protected void onUserActivityW() {
+                sendUserActivity();
+            }
+        };
+        mZenModeController = zen;
+        mDialog = new VolumeDialog(context, mController, zen) {
+            @Override
+            protected void onZenSettingsClickedH() {
+                startZenSettings();
+            }
+        };
+        applyConfiguration();
+    }
+
+    private void sendUserActivity() {
+        final KeyguardViewMediator kvm = mSysui.getComponent(KeyguardViewMediator.class);
+        if (kvm != null) {
+            kvm.userActivity();
+        }
+    }
+
+    private void applyConfiguration() {
+        mDialog.setStreamImportant(AudioManager.STREAM_ALARM, true);
+        mDialog.setStreamImportant(AudioManager.STREAM_SYSTEM, false);
+        mDialog.setShowHeaders(false);
+        mDialog.setShowFooter(true);
+        mDialog.setZenFooter(true);
+        mDialog.setAutomute(true);
+        mDialog.setSilentMode(false);
+        mController.setVolumePolicy(VolumePolicy.DEFAULT);
+        mController.showDndTile(false);
+    }
+
+    @Override
+    public ZenModeController getZenController() {
+        return mZenModeController;
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        // noop
+    }
+
+    @Override
+    public void dismissNow() {
+        mController.dismiss();
+    }
+
+    @Override
+    public void dispatchDemoCommand(String command, Bundle args) {
+        // noop
+    }
+
+    @Override
+    public void register() {
+        mController.register();
+        DndTile.setCombinedIcon(mContext, true);
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mController.dump(fd, pw, args);
+        mDialog.dump(pw);
+    }
+
+    private void startZenSettings() {
+        mSysui.getComponent(PhoneStatusBar.class).startActivityDismissingKeyguard(
+                ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
new file mode 100644
index 0000000..265e2c6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
@@ -0,0 +1,988 @@
+/*
+ * 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.volume;
+
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.ContentObserver;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.media.IVolumeController;
+import android.media.VolumePolicy;
+import android.media.session.MediaController.PlaybackInfo;
+import android.media.session.MediaSession.Token;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.Vibrator;
+import android.provider.Settings;
+import android.service.notification.Condition;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.tiles.DndTile;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ *  Source of truth for all state / events related to the volume dialog.  No presentation.
+ *
+ *  All work done on a dedicated background worker thread & associated worker.
+ *
+ *  Methods ending in "W" must be called on the worker thread.
+ */
+public class VolumeDialogController {
+    private static final String TAG = Util.logTag(VolumeDialogController.class);
+
+    private static final int DYNAMIC_STREAM_START_INDEX = 100;
+    private static final int VIBRATE_HINT_DURATION = 50;
+
+    private static final int[] STREAMS = {
+        AudioSystem.STREAM_ALARM,
+        AudioSystem.STREAM_BLUETOOTH_SCO,
+        AudioSystem.STREAM_DTMF,
+        AudioSystem.STREAM_MUSIC,
+        AudioSystem.STREAM_NOTIFICATION,
+        AudioSystem.STREAM_RING,
+        AudioSystem.STREAM_SYSTEM,
+        AudioSystem.STREAM_SYSTEM_ENFORCED,
+        AudioSystem.STREAM_TTS,
+        AudioSystem.STREAM_VOICE_CALL,
+    };
+
+    private final HandlerThread mWorkerThread;
+    private final W mWorker;
+    private final Context mContext;
+    private final AudioManager mAudio;
+    private final NotificationManager mNoMan;
+    private final ComponentName mComponent;
+    private final SettingObserver mObserver;
+    private final Receiver mReceiver = new Receiver();
+    private final MediaSessions mMediaSessions;
+    private final VC mVolumeController = new VC();
+    private final C mCallbacks = new C();
+    private final State mState = new State();
+    private final String[] mStreamTitles;
+    private final MediaSessionsCallbacks mMediaSessionsCallbacksW = new MediaSessionsCallbacks();
+    private final Vibrator mVibrator;
+    private final boolean mHasVibrator;
+
+    private boolean mEnabled;
+    private boolean mDestroyed;
+    private VolumePolicy mVolumePolicy = new VolumePolicy(true, true, false, 400);
+    private boolean mShowDndTile = false;
+
+    public VolumeDialogController(Context context, ComponentName component) {
+        mContext = context.getApplicationContext();
+        Events.writeEvent(Events.EVENT_COLLECTION_STARTED);
+        mComponent = component;
+        mWorkerThread = new HandlerThread(VolumeDialogController.class.getSimpleName());
+        mWorkerThread.start();
+        mWorker = new W(mWorkerThread.getLooper());
+        mMediaSessions = createMediaSessions(mContext, mWorkerThread.getLooper(),
+                mMediaSessionsCallbacksW);
+        mAudio = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        mNoMan = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        mObserver = new SettingObserver(mWorker);
+        mObserver.init();
+        mReceiver.init();
+        mStreamTitles = mContext.getResources().getStringArray(R.array.volume_stream_titles);
+        mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
+        mHasVibrator = mVibrator != null && mVibrator.hasVibrator();
+    }
+
+    public AudioManager getAudioManager() {
+        return mAudio;
+    }
+
+    public void dismiss() {
+        mCallbacks.onDismissRequested(Events.DISMISS_REASON_VOLUME_CONTROLLER);
+    }
+
+    public void register() {
+        try {
+            mAudio.setVolumeController(mVolumeController);
+        } catch (SecurityException e) {
+            Log.w(TAG, "Unable to set the volume controller", e);
+            return;
+        }
+        setVolumePolicy(mVolumePolicy);
+        showDndTile(mShowDndTile);
+        try {
+            mMediaSessions.init();
+        } catch (SecurityException e) {
+            Log.w(TAG, "No access to media sessions", e);
+        }
+    }
+
+    public void setVolumePolicy(VolumePolicy policy) {
+        mVolumePolicy = policy;
+        try {
+            mAudio.setVolumePolicy(mVolumePolicy);
+        } catch (NoSuchMethodError e) {
+            Log.w(TAG, "No volume policy api");
+        }
+    }
+
+    protected MediaSessions createMediaSessions(Context context, Looper looper,
+            MediaSessions.Callbacks callbacks) {
+        return new MediaSessions(context, looper, callbacks);
+    }
+
+    public void destroy() {
+        if (D.BUG) Log.d(TAG, "destroy");
+        if (mDestroyed) return;
+        mDestroyed = true;
+        Events.writeEvent(Events.EVENT_COLLECTION_STOPPED);
+        mMediaSessions.destroy();
+        mObserver.destroy();
+        mReceiver.destroy();
+        mWorkerThread.quitSafely();
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println(VolumeDialogController.class.getSimpleName() + " state:");
+        pw.print("  mEnabled: "); pw.println(mEnabled);
+        pw.print("  mDestroyed: "); pw.println(mDestroyed);
+        pw.print("  mVolumePolicy: "); pw.println(mVolumePolicy);
+        pw.print("  mEnabled: "); pw.println(mEnabled);
+        pw.print("  mShowDndTile: "); pw.println(mShowDndTile);
+        pw.print("  mHasVibrator: "); pw.println(mHasVibrator);
+        pw.print("  mRemoteStreams: "); pw.println(mMediaSessionsCallbacksW.mRemoteStreams
+                .values());
+        pw.println();
+        mMediaSessions.dump(pw);
+    }
+
+    public void addCallback(Callbacks callback, Handler handler) {
+        mCallbacks.add(callback, handler);
+    }
+
+    public void removeCallback(Callbacks callback) {
+        mCallbacks.remove(callback);
+    }
+
+    public void getState() {
+        if (mDestroyed) return;
+        mWorker.sendEmptyMessage(W.GET_STATE);
+    }
+
+    public void notifyVisible(boolean visible) {
+        if (mDestroyed) return;
+        mWorker.obtainMessage(W.NOTIFY_VISIBLE, visible ? 1 : 0, 0).sendToTarget();
+    }
+
+    public void userActivity() {
+        if (mDestroyed) return;
+        mWorker.removeMessages(W.USER_ACTIVITY);
+        mWorker.sendEmptyMessage(W.USER_ACTIVITY);
+    }
+
+    public void setRingerMode(int value, boolean external) {
+        if (mDestroyed) return;
+        mWorker.obtainMessage(W.SET_RINGER_MODE, value, external ? 1 : 0).sendToTarget();
+    }
+
+    public void setZenMode(int value) {
+        if (mDestroyed) return;
+        mWorker.obtainMessage(W.SET_ZEN_MODE, value, 0).sendToTarget();
+    }
+
+    public void setExitCondition(Condition condition) {
+        if (mDestroyed) return;
+        mWorker.obtainMessage(W.SET_EXIT_CONDITION, condition).sendToTarget();
+    }
+
+    public void setStreamMute(int stream, boolean mute) {
+        if (mDestroyed) return;
+        mWorker.obtainMessage(W.SET_STREAM_MUTE, stream, mute ? 1 : 0).sendToTarget();
+    }
+
+    public void setStreamVolume(int stream, int level) {
+        if (mDestroyed) return;
+        mWorker.obtainMessage(W.SET_STREAM_VOLUME, stream, level).sendToTarget();
+    }
+
+    public void setActiveStream(int stream) {
+        if (mDestroyed) return;
+        mWorker.obtainMessage(W.SET_ACTIVE_STREAM, stream, 0).sendToTarget();
+    }
+
+    public void vibrate() {
+        if (mHasVibrator) {
+            mVibrator.vibrate(VIBRATE_HINT_DURATION);
+        }
+    }
+
+    public boolean hasVibrator() {
+        return mHasVibrator;
+    }
+
+    private void onNotifyVisibleW(boolean visible) {
+        if (mDestroyed) return;
+        mAudio.notifyVolumeControllerVisible(mVolumeController, visible);
+        if (!visible) {
+            if (updateActiveStreamW(-1)) {
+                mCallbacks.onStateChanged(mState);
+            }
+        }
+    }
+
+    protected void onUserActivityW() {
+        // hook for subclasses
+    }
+
+    private void onShowSafetyWarningW(int flags) {
+        mCallbacks.onShowSafetyWarning(flags);
+    }
+
+    private boolean checkRoutedToBluetoothW(int stream) {
+        boolean changed = false;
+        if (stream == AudioManager.STREAM_MUSIC) {
+            final boolean routedToBluetooth =
+                    (mAudio.getDevicesForStream(AudioManager.STREAM_MUSIC) &
+                            (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP |
+                            AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+                            AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0;
+            changed |= updateStreamRoutedToBluetoothW(stream, routedToBluetooth);
+        }
+        return changed;
+    }
+
+    private void onVolumeChangedW(int stream, int flags) {
+        final boolean showUI = (flags & AudioManager.FLAG_SHOW_UI) != 0;
+        final boolean fromKey = (flags & AudioManager.FLAG_FROM_KEY) != 0;
+        final boolean showVibrateHint = (flags & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0;
+        final boolean showSilentHint = (flags & AudioManager.FLAG_SHOW_SILENT_HINT) != 0;
+        boolean changed = false;
+        if (showUI) {
+            changed |= updateActiveStreamW(stream);
+        }
+        changed |= updateStreamLevelW(stream, mAudio.getLastAudibleStreamVolume(stream));
+        changed |= checkRoutedToBluetoothW(showUI ? AudioManager.STREAM_MUSIC : stream);
+        if (changed) {
+            mCallbacks.onStateChanged(mState);
+        }
+        if (showUI) {
+            mCallbacks.onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
+        }
+        if (showVibrateHint) {
+            mCallbacks.onShowVibrateHint();
+        }
+        if (showSilentHint) {
+            mCallbacks.onShowSilentHint();
+        }
+        if (changed && fromKey) {
+            Events.writeEvent(Events.EVENT_KEY);
+        }
+    }
+
+    private boolean updateActiveStreamW(int activeStream) {
+        if (activeStream == mState.activeStream) return false;
+        mState.activeStream = activeStream;
+        Events.writeEvent(Events.EVENT_ACTIVE_STREAM_CHANGED, activeStream);
+        if (D.BUG) Log.d(TAG, "updateActiveStreamW " + activeStream);
+        final int s = activeStream < DYNAMIC_STREAM_START_INDEX ? activeStream : -1;
+        if (D.BUG) Log.d(TAG, "forceVolumeControlStream " + s);
+        mAudio.forceVolumeControlStream(s);
+        return true;
+    }
+
+    private StreamState streamStateW(int stream) {
+        StreamState ss = mState.states.get(stream);
+        if (ss == null) {
+            ss = new StreamState();
+            mState.states.put(stream, ss);
+        }
+        return ss;
+    }
+
+    private void onGetStateW() {
+        for (int stream : STREAMS) {
+            updateStreamLevelW(stream, mAudio.getLastAudibleStreamVolume(stream));
+            streamStateW(stream).levelMin = mAudio.getStreamMinVolume(stream);
+            streamStateW(stream).levelMax = mAudio.getStreamMaxVolume(stream);
+            updateStreamMuteW(stream, mAudio.isStreamMute(stream));
+            final StreamState ss = streamStateW(stream);
+            ss.muteSupported = mAudio.isStreamAffectedByMute(stream);
+            ss.name = mStreamTitles[stream];
+            checkRoutedToBluetoothW(stream);
+        }
+        updateRingerModeExternalW(mAudio.getRingerMode());
+        updateZenModeW();
+        updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
+        updateExitConditionW();
+        mCallbacks.onStateChanged(mState);
+    }
+
+    private boolean updateStreamRoutedToBluetoothW(int stream, boolean routedToBluetooth) {
+        final StreamState ss = streamStateW(stream);
+        if (ss.routedToBluetooth == routedToBluetooth) return false;
+        ss.routedToBluetooth = routedToBluetooth;
+        if (D.BUG) Log.d(TAG, "updateStreamRoutedToBluetoothW stream=" + stream
+                + " routedToBluetooth=" + routedToBluetooth);
+        return true;
+    }
+
+    private boolean updateStreamLevelW(int stream, int level) {
+        final StreamState ss = streamStateW(stream);
+        if (ss.level == level) return false;
+        ss.level = level;
+        if (isLogWorthy(stream)) {
+            Events.writeEvent(Events.EVENT_LEVEL_CHANGED, stream, level);
+        }
+        return true;
+    }
+
+    private static boolean isLogWorthy(int stream) {
+        switch (stream) {
+            case AudioSystem.STREAM_ALARM:
+            case AudioSystem.STREAM_BLUETOOTH_SCO:
+            case AudioSystem.STREAM_MUSIC:
+            case AudioSystem.STREAM_RING:
+            case AudioSystem.STREAM_SYSTEM:
+            case AudioSystem.STREAM_VOICE_CALL:
+                return true;
+        }
+        return false;
+    }
+
+    private boolean updateStreamMuteW(int stream, boolean muted) {
+        final StreamState ss = streamStateW(stream);
+        if (ss.muted == muted) return false;
+        ss.muted = muted;
+        if (isLogWorthy(stream)) {
+            Events.writeEvent(Events.EVENT_MUTE_CHANGED, stream, muted);
+        }
+        if (muted && isRinger(stream)) {
+            updateRingerModeInternalW(mAudio.getRingerModeInternal());
+        }
+        return true;
+    }
+
+    private static boolean isRinger(int stream) {
+        return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION;
+    }
+
+    private boolean updateExitConditionW() {
+        final Condition exitCondition = mNoMan.getZenModeCondition();
+        if (Objects.equals(mState.exitCondition, exitCondition)) return false;
+        mState.exitCondition = exitCondition;
+        return true;
+    }
+
+    private boolean updateEffectsSuppressorW(ComponentName effectsSuppressor) {
+        if (Objects.equals(mState.effectsSuppressor, effectsSuppressor)) return false;
+        mState.effectsSuppressor = effectsSuppressor;
+        mState.effectsSuppressorName = getApplicationName(mContext, mState.effectsSuppressor);
+        Events.writeEvent(Events.EVENT_SUPPRESSOR_CHANGED, mState.effectsSuppressor,
+                mState.effectsSuppressorName);
+        return true;
+    }
+
+    private static String getApplicationName(Context context, ComponentName component) {
+        if (component == null) return null;
+        final PackageManager pm = context.getPackageManager();
+        final String pkg = component.getPackageName();
+        try {
+            final ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
+            final String rt = Objects.toString(ai.loadLabel(pm), "").trim();
+            if (rt.length() > 0) {
+                return rt;
+            }
+        } catch (NameNotFoundException e) {}
+        return pkg;
+    }
+
+    private boolean updateZenModeW() {
+        final int zen = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+        if (mState.zenMode == zen) return false;
+        mState.zenMode = zen;
+        Events.writeEvent(Events.EVENT_ZEN_MODE_CHANGED, zen);
+        return true;
+    }
+
+    private boolean updateRingerModeExternalW(int rm) {
+        if (rm == mState.ringerModeExternal) return false;
+        mState.ringerModeExternal = rm;
+        Events.writeEvent(Events.EVENT_EXTERNAL_RINGER_MODE_CHANGED, rm);
+        return true;
+    }
+
+    private boolean updateRingerModeInternalW(int rm) {
+        if (rm == mState.ringerModeInternal) return false;
+        mState.ringerModeInternal = rm;
+        Events.writeEvent(Events.EVENT_INTERNAL_RINGER_MODE_CHANGED, rm);
+        return true;
+    }
+
+    private void onSetRingerModeW(int mode, boolean external) {
+        if (external) {
+            mAudio.setRingerMode(mode);
+        } else {
+            mAudio.setRingerModeInternal(mode);
+        }
+    }
+
+    private void onSetStreamMuteW(int stream, boolean mute) {
+        mAudio.adjustStreamVolume(stream, mute ? AudioManager.ADJUST_MUTE
+                : AudioManager.ADJUST_UNMUTE, 0);
+    }
+
+    private void onSetStreamVolumeW(int stream, int level) {
+        if (D.BUG) Log.d(TAG, "onSetStreamVolume " + stream + " level=" + level);
+        if (stream >= DYNAMIC_STREAM_START_INDEX) {
+            mMediaSessionsCallbacksW.setStreamVolume(stream, level);
+            return;
+        }
+        mAudio.setStreamVolume(stream, level, 0);
+    }
+
+    private void onSetActiveStreamW(int stream) {
+        boolean changed = updateActiveStreamW(stream);
+        if (changed) {
+            mCallbacks.onStateChanged(mState);
+        }
+    }
+
+    private void onSetExitConditionW(Condition condition) {
+        mNoMan.setZenModeCondition(condition);
+    }
+
+    private void onSetZenModeW(int mode) {
+        if (D.BUG) Log.d(TAG, "onSetZenModeW " + mode);
+        mNoMan.setZenMode(mode);
+    }
+
+    private void onDismissRequestedW(int reason) {
+        mCallbacks.onDismissRequested(reason);
+    }
+
+    public void showDndTile(boolean visible) {
+        if (D.BUG) Log.d(TAG, "showDndTile");
+        DndTile.setVisible(mContext, visible);
+    }
+
+    private final class VC extends IVolumeController.Stub {
+        private final String TAG = VolumeDialogController.TAG + ".VC";
+
+        @Override
+        public void displaySafeVolumeWarning(int flags) throws RemoteException {
+            if (D.BUG) Log.d(TAG, "displaySafeVolumeWarning "
+                    + Util.audioManagerFlagsToString(flags));
+            if (mDestroyed) return;
+            mWorker.obtainMessage(W.SHOW_SAFETY_WARNING, flags, 0).sendToTarget();
+        }
+
+        @Override
+        public void volumeChanged(int streamType, int flags) throws RemoteException {
+            if (D.BUG) Log.d(TAG, "volumeChanged " + AudioSystem.streamToString(streamType)
+                    + " " + Util.audioManagerFlagsToString(flags));
+            if (mDestroyed) return;
+            mWorker.obtainMessage(W.VOLUME_CHANGED, streamType, flags).sendToTarget();
+        }
+
+        @Override
+        public void masterMuteChanged(int flags) throws RemoteException {
+            if (D.BUG) Log.d(TAG, "masterMuteChanged");
+        }
+
+        @Override
+        public void setLayoutDirection(int layoutDirection) throws RemoteException {
+            if (D.BUG) Log.d(TAG, "setLayoutDirection");
+            if (mDestroyed) return;
+            mWorker.obtainMessage(W.LAYOUT_DIRECTION_CHANGED, layoutDirection, 0).sendToTarget();
+        }
+
+        @Override
+        public void dismiss() throws RemoteException {
+            if (D.BUG) Log.d(TAG, "dismiss requested");
+            if (mDestroyed) return;
+            mWorker.obtainMessage(W.DISMISS_REQUESTED, Events.DISMISS_REASON_VOLUME_CONTROLLER, 0)
+                    .sendToTarget();
+            mWorker.sendEmptyMessage(W.DISMISS_REQUESTED);
+        }
+    }
+
+    private final class W extends Handler {
+        private static final int VOLUME_CHANGED = 1;
+        private static final int DISMISS_REQUESTED = 2;
+        private static final int GET_STATE = 3;
+        private static final int SET_RINGER_MODE = 4;
+        private static final int SET_ZEN_MODE = 5;
+        private static final int SET_EXIT_CONDITION = 6;
+        private static final int SET_STREAM_MUTE = 7;
+        private static final int LAYOUT_DIRECTION_CHANGED = 8;
+        private static final int CONFIGURATION_CHANGED = 9;
+        private static final int SET_STREAM_VOLUME = 10;
+        private static final int SET_ACTIVE_STREAM = 11;
+        private static final int NOTIFY_VISIBLE = 12;
+        private static final int USER_ACTIVITY = 13;
+        private static final int SHOW_SAFETY_WARNING = 14;
+
+        W(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case VOLUME_CHANGED: onVolumeChangedW(msg.arg1, msg.arg2); break;
+                case DISMISS_REQUESTED: onDismissRequestedW(msg.arg1); break;
+                case GET_STATE: onGetStateW(); break;
+                case SET_RINGER_MODE: onSetRingerModeW(msg.arg1, msg.arg2 != 0); break;
+                case SET_ZEN_MODE: onSetZenModeW(msg.arg1); break;
+                case SET_EXIT_CONDITION: onSetExitConditionW((Condition) msg.obj); break;
+                case SET_STREAM_MUTE: onSetStreamMuteW(msg.arg1, msg.arg2 != 0); break;
+                case LAYOUT_DIRECTION_CHANGED: mCallbacks.onLayoutDirectionChanged(msg.arg1); break;
+                case CONFIGURATION_CHANGED: mCallbacks.onConfigurationChanged(); break;
+                case SET_STREAM_VOLUME: onSetStreamVolumeW(msg.arg1, msg.arg2); break;
+                case SET_ACTIVE_STREAM: onSetActiveStreamW(msg.arg1); break;
+                case NOTIFY_VISIBLE: onNotifyVisibleW(msg.arg1 != 0); break;
+                case USER_ACTIVITY: onUserActivityW(); break;
+                case SHOW_SAFETY_WARNING: onShowSafetyWarningW(msg.arg1); break;
+            }
+        }
+    }
+
+    private final class C implements Callbacks {
+        private final HashMap<Callbacks, Handler> mCallbackMap = new HashMap<>();
+
+        public void add(Callbacks callback, Handler handler) {
+            if (callback == null || handler == null) throw new IllegalArgumentException();
+            mCallbackMap.put(callback, handler);
+        }
+
+        public void remove(Callbacks callback) {
+            mCallbackMap.remove(callback);
+        }
+
+        @Override
+        public void onShowRequested(final int reason) {
+            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
+                entry.getValue().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        entry.getKey().onShowRequested(reason);
+                    }
+                });
+            }
+        }
+
+        @Override
+        public void onDismissRequested(final int reason) {
+            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
+                entry.getValue().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        entry.getKey().onDismissRequested(reason);
+                    }
+                });
+            }
+        }
+
+        @Override
+        public void onStateChanged(final State state) {
+            final long time = System.currentTimeMillis();
+            final State copy = state.copy();
+            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
+                entry.getValue().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        entry.getKey().onStateChanged(copy);
+                    }
+                });
+            }
+            Events.writeState(time, copy);
+        }
+
+        @Override
+        public void onLayoutDirectionChanged(final int layoutDirection) {
+            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
+                entry.getValue().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        entry.getKey().onLayoutDirectionChanged(layoutDirection);
+                    }
+                });
+            }
+        }
+
+        @Override
+        public void onConfigurationChanged() {
+            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
+                entry.getValue().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        entry.getKey().onConfigurationChanged();
+                    }
+                });
+            }
+        }
+
+        @Override
+        public void onShowVibrateHint() {
+            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
+                entry.getValue().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        entry.getKey().onShowVibrateHint();
+                    }
+                });
+            }
+        }
+
+        @Override
+        public void onShowSilentHint() {
+            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
+                entry.getValue().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        entry.getKey().onShowSilentHint();
+                    }
+                });
+            }
+        }
+
+        @Override
+        public void onScreenOff() {
+            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
+                entry.getValue().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        entry.getKey().onScreenOff();
+                    }
+                });
+            }
+        }
+
+        @Override
+        public void onShowSafetyWarning(final int flags) {
+            for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
+                entry.getValue().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        entry.getKey().onShowSafetyWarning(flags);
+                    }
+                });
+            }
+        }
+    }
+
+
+    private final class SettingObserver extends ContentObserver {
+        private final Uri SERVICE_URI = Settings.Secure.getUriFor(
+                Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT);
+        private final Uri ZEN_MODE_URI =
+                Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
+        private final Uri ZEN_MODE_CONFIG_URI =
+                Settings.Global.getUriFor(Settings.Global.ZEN_MODE_CONFIG_ETAG);
+
+        public SettingObserver(Handler handler) {
+            super(handler);
+        }
+
+        public void init() {
+            mContext.getContentResolver().registerContentObserver(SERVICE_URI, false, this);
+            mContext.getContentResolver().registerContentObserver(ZEN_MODE_URI, false, this);
+            mContext.getContentResolver().registerContentObserver(ZEN_MODE_CONFIG_URI, false, this);
+            onChange(true, SERVICE_URI);
+        }
+
+        public void destroy() {
+            mContext.getContentResolver().unregisterContentObserver(this);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            boolean changed = false;
+            if (SERVICE_URI.equals(uri)) {
+                final String setting = Settings.Secure.getString(mContext.getContentResolver(),
+                        Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT);
+                final boolean enabled = setting != null && mComponent != null
+                        && mComponent.equals(ComponentName.unflattenFromString(setting));
+                if (enabled == mEnabled) return;
+                if (enabled) {
+                    register();
+                }
+                mEnabled = enabled;
+            }
+            if (ZEN_MODE_URI.equals(uri)) {
+                changed = updateZenModeW();
+            }
+            if (ZEN_MODE_CONFIG_URI.equals(uri)) {
+                changed = updateExitConditionW();
+            }
+            if (changed) {
+                mCallbacks.onStateChanged(mState);
+            }
+        }
+    }
+
+    private final class Receiver extends BroadcastReceiver {
+
+        public void init() {
+            final IntentFilter filter = new IntentFilter();
+            filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
+            filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
+            filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
+            filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
+            filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION);
+            filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
+            filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+            filter.addAction(Intent.ACTION_SCREEN_OFF);
+            mContext.registerReceiver(this, filter, null, mWorker);
+        }
+
+        public void destroy() {
+            mContext.unregisterReceiver(this);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            boolean changed = false;
+            if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
+                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+                final int level = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
+                final int oldLevel = intent
+                        .getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);
+                if (D.BUG) Log.d(TAG, "onReceive VOLUME_CHANGED_ACTION stream=" + stream
+                        + " level=" + level + " oldLevel=" + oldLevel);
+                changed = updateStreamLevelW(stream, level);
+            } else if (action.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) {
+                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+                final int devices = intent
+                        .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, -1);
+                final int oldDevices = intent
+                        .getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, -1);
+                if (D.BUG) Log.d(TAG, "onReceive STREAM_DEVICES_CHANGED_ACTION stream="
+                        + stream + " devices=" + devices + " oldDevices=" + oldDevices);
+                changed = checkRoutedToBluetoothW(stream);
+            } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
+                final int rm = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
+                if (D.BUG) Log.d(TAG, "onReceive RINGER_MODE_CHANGED_ACTION rm="
+                        + Util.ringerModeToString(rm));
+                changed = updateRingerModeExternalW(rm);
+            } else if (action.equals(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)) {
+                final int rm = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
+                if (D.BUG) Log.d(TAG, "onReceive INTERNAL_RINGER_MODE_CHANGED_ACTION rm="
+                        + Util.ringerModeToString(rm));
+                changed = updateRingerModeInternalW(rm);
+            } else if (action.equals(AudioManager.STREAM_MUTE_CHANGED_ACTION)) {
+                final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+                final boolean muted = intent
+                        .getBooleanExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, false);
+                if (D.BUG) Log.d(TAG, "onReceive STREAM_MUTE_CHANGED_ACTION stream=" + stream
+                        + " muted=" + muted);
+                changed = updateStreamMuteW(stream, muted);
+            } else if (action.equals(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED)) {
+                if (D.BUG) Log.d(TAG, "onReceive ACTION_EFFECTS_SUPPRESSOR_CHANGED");
+                changed = updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
+            } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
+                if (D.BUG) Log.d(TAG, "onReceive ACTION_CONFIGURATION_CHANGED");
+                mCallbacks.onConfigurationChanged();
+            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+                if (D.BUG) Log.d(TAG, "onReceive ACTION_SCREEN_OFF");
+                mCallbacks.onScreenOff();
+            }
+            if (changed) {
+                mCallbacks.onStateChanged(mState);
+            }
+        }
+    }
+
+    private final class MediaSessionsCallbacks implements MediaSessions.Callbacks {
+        private final HashMap<Token, Integer> mRemoteStreams = new HashMap<>();
+
+        private int mNextStream = DYNAMIC_STREAM_START_INDEX;
+
+        @Override
+        public void onRemoteUpdate(Token token, String name, PlaybackInfo pi) {
+            if (!mRemoteStreams.containsKey(token)) {
+                mRemoteStreams.put(token, mNextStream);
+                if (D.BUG) Log.d(TAG, "onRemoteUpdate: " + name + " is stream " + mNextStream);
+                mNextStream++;
+            }
+            final int stream = mRemoteStreams.get(token);
+            boolean changed = mState.states.indexOfKey(stream) < 0;
+            final StreamState ss = streamStateW(stream);
+            ss.dynamic = true;
+            ss.levelMin = 0;
+            ss.levelMax = pi.getMaxVolume();
+            if (ss.level != pi.getCurrentVolume()) {
+                ss.level = pi.getCurrentVolume();
+                changed = true;
+            }
+            if (!Objects.equals(ss.name, name)) {
+                ss.name = name;
+                changed = true;
+            }
+            if (changed) {
+                if (D.BUG) Log.d(TAG, "onRemoteUpdate: " + name + ": " + ss.level
+                        + " of " + ss.levelMax);
+                mCallbacks.onStateChanged(mState);
+            }
+        }
+
+        @Override
+        public void onRemoteVolumeChanged(Token token, int flags) {
+            final int stream = mRemoteStreams.get(token);
+            final boolean showUI = (flags & AudioManager.FLAG_SHOW_UI) != 0;
+            boolean changed = updateActiveStreamW(stream);
+            if (showUI) {
+                changed |= checkRoutedToBluetoothW(AudioManager.STREAM_MUSIC);
+            }
+            if (changed) {
+                mCallbacks.onStateChanged(mState);
+            }
+            if (showUI) {
+                mCallbacks.onShowRequested(Events.SHOW_REASON_REMOTE_VOLUME_CHANGED);
+            }
+        }
+
+        @Override
+        public void onRemoteRemoved(Token token) {
+            final int stream = mRemoteStreams.get(token);
+            mState.states.remove(stream);
+            if (mState.activeStream == stream) {
+                updateActiveStreamW(-1);
+            }
+            mCallbacks.onStateChanged(mState);
+        }
+
+        public void setStreamVolume(int stream, int level) {
+            final Token t = findToken(stream);
+            if (t == null) {
+                Log.w(TAG, "setStreamVolume: No token found for stream: " + stream);
+                return;
+            }
+            mMediaSessions.setVolume(t, level);
+        }
+
+        private Token findToken(int stream) {
+            for (Map.Entry<Token, Integer> entry : mRemoteStreams.entrySet()) {
+                if (entry.getValue().equals(stream)) {
+                    return entry.getKey();
+                }
+            }
+            return null;
+        }
+    }
+
+    public static final class StreamState {
+        public boolean dynamic;
+        public int level;
+        public int levelMin;
+        public int levelMax;
+        public boolean muted;
+        public boolean muteSupported;
+        public String name;
+        public boolean routedToBluetooth;
+
+        public StreamState copy() {
+            final StreamState rt = new StreamState();
+            rt.dynamic = dynamic;
+            rt.level = level;
+            rt.levelMin = levelMin;
+            rt.levelMax = levelMax;
+            rt.muted = muted;
+            rt.muteSupported = muteSupported;
+            rt.name = name;
+            rt.routedToBluetooth = routedToBluetooth;
+            return rt;
+        }
+    }
+
+    public static final class State {
+        public static int NO_ACTIVE_STREAM = -1;
+
+        public final SparseArray<StreamState> states = new SparseArray<StreamState>();
+
+        public int ringerModeInternal;
+        public int ringerModeExternal;
+        public int zenMode;
+        public ComponentName effectsSuppressor;
+        public String effectsSuppressorName;
+        public Condition exitCondition;
+        public int activeStream = NO_ACTIVE_STREAM;
+
+        public State copy() {
+            final State rt = new State();
+            for (int i = 0; i < states.size(); i++) {
+                rt.states.put(states.keyAt(i), states.valueAt(i).copy());
+            }
+            rt.ringerModeExternal = ringerModeExternal;
+            rt.ringerModeInternal = ringerModeInternal;
+            rt.zenMode = zenMode;
+            if (effectsSuppressor != null) rt.effectsSuppressor = effectsSuppressor.clone();
+            rt.effectsSuppressorName = effectsSuppressorName;
+            if (exitCondition != null) rt.exitCondition = exitCondition.copy();
+            rt.activeStream = activeStream;
+            return rt;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder("{");
+            for (int i = 0; i < states.size(); i++) {
+                if (i > 0) sb.append(',');
+                final int stream = states.keyAt(i);
+                final StreamState ss = states.valueAt(i);
+                sb.append(AudioSystem.streamToString(stream)).append(":").append(ss.level)
+                        .append("[").append(ss.levelMin).append("..").append(ss.levelMax);
+                if (ss.muted) sb.append(" [MUTED]");
+            }
+            sb.append(",ringerModeExternal:").append(ringerModeExternal);
+            sb.append(",ringerModeInternal:").append(ringerModeInternal);
+            sb.append(",zenMode:").append(zenMode);
+            sb.append(",effectsSuppressor:").append(effectsSuppressor);
+            sb.append(",effectsSuppressorName:").append(effectsSuppressorName);
+            sb.append(",exitCondition:").append(exitCondition);
+            sb.append(",activeStream:").append(activeStream);
+            return sb.append('}').toString();
+        }
+    }
+
+    public interface Callbacks {
+        void onShowRequested(int reason);
+        void onDismissRequested(int reason);
+        void onStateChanged(State state);
+        void onLayoutDirectionChanged(int layoutDirection);
+        void onConfigurationChanged();
+        void onShowVibrateHint();
+        void onShowSilentHint();
+        void onScreenOff();
+        void onShowSafetyWarning(int flags);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index d16b818..f16e9d2 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -52,7 +52,6 @@
 import android.os.Vibrator;
 import android.util.Log;
 import android.util.SparseArray;
-import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -72,7 +71,6 @@
 
 import com.android.internal.R;
 import com.android.systemui.DemoMode;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.ZenModeController;
 
 import java.io.FileDescriptor;
@@ -264,80 +262,6 @@
     private static AlertDialog sSafetyWarning;
     private static Object sSafetyWarningLock = new Object();
 
-    private static class SafetyWarning extends SystemUIDialog
-            implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener {
-        private final Context mContext;
-        private final VolumePanel mVolumePanel;
-        private final AudioManager mAudioManager;
-
-        private boolean mNewVolumeUp;
-
-        SafetyWarning(Context context, VolumePanel volumePanel, AudioManager audioManager) {
-            super(context);
-            mContext = context;
-            mVolumePanel = volumePanel;
-            mAudioManager = audioManager;
-
-            setMessage(mContext.getString(com.android.internal.R.string.safe_media_volume_warning));
-            setButton(DialogInterface.BUTTON_POSITIVE,
-                    mContext.getString(com.android.internal.R.string.yes), this);
-            setButton(DialogInterface.BUTTON_NEGATIVE,
-                    mContext.getString(com.android.internal.R.string.no), (OnClickListener) null);
-            setOnDismissListener(this);
-
-            IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
-            context.registerReceiver(mReceiver, filter);
-        }
-
-        @Override
-        public boolean onKeyDown(int keyCode, KeyEvent event) {
-            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && event.getRepeatCount() == 0) {
-                mNewVolumeUp = true;
-            }
-            return super.onKeyDown(keyCode, event);
-        }
-
-        @Override
-        public boolean onKeyUp(int keyCode, KeyEvent event) {
-            if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mNewVolumeUp) {
-                if (LOGD) Log.d(TAG, "Confirmed warning via VOLUME_UP");
-                mAudioManager.disableSafeMediaVolume();
-                dismiss();
-            }
-            return super.onKeyUp(keyCode, event);
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            mAudioManager.disableSafeMediaVolume();
-        }
-
-        @Override
-        public void onDismiss(DialogInterface unused) {
-            mContext.unregisterReceiver(mReceiver);
-            cleanUp();
-        }
-
-        private void cleanUp() {
-            synchronized (sSafetyWarningLock) {
-                sSafetyWarning = null;
-            }
-            mVolumePanel.forceTimeout(0);
-            mVolumePanel.updateStates();
-        }
-
-        private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
-                    if (LOGD) Log.d(TAG, "Received ACTION_CLOSE_SYSTEM_DIALOGS");
-                    cancel();
-                    cleanUp();
-                }
-            }
-        };
-    }
-
     protected LayoutParams getDialogLayoutParams(Window window, Resources res) {
         final LayoutParams lp = window.getAttributes();
         lp.token = null;
@@ -384,7 +308,7 @@
         final Window window = mDialog.getWindow();
         window.requestFeature(Window.FEATURE_NO_TITLE);
         mDialog.setCanceledOnTouchOutside(true);
-        mDialog.setContentView(com.android.systemui.R.layout.volume_dialog);
+        mDialog.setContentView(com.android.systemui.R.layout.volume_panel_dialog);
         mDialog.setOnDismissListener(new OnDismissListener() {
             @Override
             public void onDismiss(DialogInterface dialog) {
@@ -1283,7 +1207,16 @@
                 if (sSafetyWarning != null) {
                     return;
                 }
-                sSafetyWarning = new SafetyWarning(mContext, this, mAudioManager);
+                sSafetyWarning = new SafetyWarningDialog(mContext, mAudioManager) {
+                    @Override
+                    protected void cleanUp() {
+                        synchronized (sSafetyWarningLock) {
+                            sSafetyWarning = null;
+                        }
+                        forceTimeout(0);
+                        updateStates();
+                    }
+                };
                 sSafetyWarning.show();
             }
             updateStates();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelComponent.java
new file mode 100644
index 0000000..fa6ea9e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelComponent.java
@@ -0,0 +1,184 @@
+/*
+ * 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.volume;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.media.AudioManager;
+import android.media.IRemoteVolumeController;
+import android.media.IVolumeController;
+import android.media.VolumePolicy;
+import android.media.session.ISessionController;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+
+import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+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 java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Implementation of VolumeComponent backed by the old volume panel.
+ */
+public class VolumePanelComponent implements VolumeComponent {
+
+    private final SystemUI mSysui;
+    private final Context mContext;
+    private final Handler mHandler;
+    private final VolumeController mVolumeController;
+    private final RemoteVolumeController mRemoteVolumeController;
+    private final AudioManager mAudioManager;
+    private final MediaSessionManager mMediaSessionManager;
+
+    private VolumePanel mPanel;
+    private int mDismissDelay;
+
+    public VolumePanelComponent(SystemUI sysui, Context context, Handler handler,
+            ZenModeController controller) {
+        mSysui = sysui;
+        mContext = context;
+        mHandler = handler;
+        mAudioManager = context.getSystemService(AudioManager.class);
+        mMediaSessionManager = context.getSystemService(MediaSessionManager.class);
+        mVolumeController = new VolumeController();
+        mRemoteVolumeController = new RemoteVolumeController();
+        mDismissDelay = mContext.getResources().getInteger(R.integer.volume_panel_dismiss_delay);
+        mPanel = new VolumePanel(mContext, controller);
+        mPanel.setCallback(new VolumePanel.Callback() {
+            @Override
+            public void onZenSettings() {
+                mHandler.removeCallbacks(mStartZenSettings);
+                mHandler.post(mStartZenSettings);
+            }
+
+            @Override
+            public void onInteraction() {
+                final KeyguardViewMediator kvm = mSysui.getComponent(KeyguardViewMediator.class);
+                if (kvm != null) {
+                    kvm.userActivity();
+                }
+            }
+
+            @Override
+            public void onVisible(boolean visible) {
+                if (mAudioManager != null && mVolumeController != null) {
+                    mAudioManager.notifyVolumeControllerVisible(mVolumeController, visible);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mPanel != null) {
+            mPanel.dump(fd, pw, args);
+        }
+    }
+
+    public void register() {
+        mAudioManager.setVolumeController(mVolumeController);
+        mAudioManager.setVolumePolicy(VolumePolicy.DEFAULT);
+        mMediaSessionManager.setRemoteVolumeController(mRemoteVolumeController);
+        DndTile.setVisible(mContext, false);
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        if (mPanel != null) {
+            mPanel.onConfigurationChanged(newConfig);
+        }
+    }
+
+    @Override
+    public ZenModeController getZenController() {
+        return mPanel.getZenController();
+    }
+
+    @Override
+    public void dispatchDemoCommand(String command, Bundle args) {
+        mPanel.dispatchDemoCommand(command, args);
+    }
+
+    @Override
+    public void dismissNow() {
+        mPanel.postDismiss(0);
+    }
+
+    private final Runnable mStartZenSettings = new Runnable() {
+        @Override
+        public void run() {
+            mSysui.getComponent(PhoneStatusBar.class).startActivityDismissingKeyguard(
+                    ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */);
+            mPanel.postDismiss(mDismissDelay);
+        }
+    };
+
+    private final class RemoteVolumeController extends IRemoteVolumeController.Stub {
+        @Override
+        public void remoteVolumeChanged(ISessionController binder, int flags)
+                throws RemoteException {
+            MediaController controller = new MediaController(mContext, binder);
+            mPanel.postRemoteVolumeChanged(controller, flags);
+        }
+
+        @Override
+        public void updateRemoteController(ISessionController session) throws RemoteException {
+            mPanel.postRemoteSliderVisibility(session != null);
+            // TODO stash default session in case the slider can be opened other
+            // than by remoteVolumeChanged.
+        }
+    }
+
+    /** For now, simply host an unmodified base volume panel in this process. */
+    private final class VolumeController extends IVolumeController.Stub {
+
+        @Override
+        public void displaySafeVolumeWarning(int flags) throws RemoteException {
+            mPanel.postDisplaySafeVolumeWarning(flags);
+        }
+
+        @Override
+        public void volumeChanged(int streamType, int flags)
+                throws RemoteException {
+            mPanel.postVolumeChanged(streamType, flags);
+        }
+
+        @Override
+        public void masterMuteChanged(int flags) throws RemoteException {
+            // no-op
+        }
+
+        @Override
+        public void setLayoutDirection(int layoutDirection)
+                throws RemoteException {
+            mPanel.postLayoutDirection(layoutDirection);
+        }
+
+        @Override
+        public void dismiss() throws RemoteException {
+            dismissNow();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index ac08904..387aed0 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -29,25 +29,17 @@
 import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
 import android.media.AudioManager;
-import android.media.IRemoteVolumeController;
-import android.media.IVolumeController;
-import android.media.VolumePolicy;
-import android.media.session.ISessionController;
-import android.media.session.MediaController;
 import android.media.session.MediaSessionManager;
-import android.os.Bundle;
 import android.os.Handler;
-import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
-import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.statusbar.ServiceMonitor;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
@@ -59,6 +51,8 @@
     private static final String TAG = "VolumeUI";
     private static boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
 
+    private static final boolean USE_OLD_VOLUME = SystemProperties.getBoolean("volume.old", false);
+
     private final Handler mHandler = new Handler();
     private final Receiver mReceiver = new Receiver();
     private final RestorationNotification mRestorationNotification = new RestorationNotification();
@@ -67,12 +61,10 @@
     private AudioManager mAudioManager;
     private NotificationManager mNotificationManager;
     private MediaSessionManager mMediaSessionManager;
-    private VolumeController mVolumeController;
-    private RemoteVolumeController mRemoteVolumeController;
     private ServiceMonitor mVolumeControllerService;
 
-    private VolumePanel mPanel;
-    private int mDismissDelay;
+    private VolumePanelComponent mOldVolume;
+    private VolumeDialogComponent mNewVolume;
 
     @Override
     public void start() {
@@ -83,10 +75,10 @@
                 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
         mMediaSessionManager = (MediaSessionManager) mContext
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
-        initPanel();
-        mVolumeController = new VolumeController();
-        mRemoteVolumeController = new RemoteVolumeController();
-        putComponent(VolumeComponent.class, mVolumeController);
+        final ZenModeController zenController = new ZenModeControllerImpl(mContext, mHandler);
+        mOldVolume = new VolumePanelComponent(this, mContext, mHandler, zenController);
+        mNewVolume = new VolumeDialogComponent(this, mContext, null, zenController);
+        putComponent(VolumeComponent.class, getVolumeComponent());
         mReceiver.start();
         mVolumeControllerService = new ServiceMonitor(TAG, LOGD,
                 mContext, Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT,
@@ -94,30 +86,30 @@
         mVolumeControllerService.start();
     }
 
+    private VolumeComponent getVolumeComponent() {
+        return USE_OLD_VOLUME ? mOldVolume : mNewVolume;
+    }
+
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        if (mPanel != null) {
-            mPanel.onConfigurationChanged(newConfig);
-        }
+        if (!mEnabled) return;
+        getVolumeComponent().onConfigurationChanged(newConfig);
     }
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.print("mEnabled="); pw.println(mEnabled);
+        if (!mEnabled) return;
         pw.print("mVolumeControllerService="); pw.println(mVolumeControllerService.getComponent());
-        if (mPanel != null) {
-            mPanel.dump(fd, pw, args);
-        }
+        getVolumeComponent().dump(fd, pw, args);
     }
 
-    private void setVolumeController(boolean register) {
+    private void setDefaultVolumeController(boolean register) {
         if (register) {
-            if (LOGD) Log.d(TAG, "Registering default volume controller");
-            mAudioManager.setVolumeController(mVolumeController);
-            mAudioManager.setVolumePolicy(VolumePolicy.DEFAULT);
-            mMediaSessionManager.setRemoteVolumeController(mRemoteVolumeController);
             DndTile.setVisible(mContext, false);
+            if (LOGD) Log.d(TAG, "Registering default volume controller");
+            getVolumeComponent().register();
         } else {
             if (LOGD) Log.d(TAG, "Unregistering default volume controller");
             mAudioManager.setVolumeController(null);
@@ -125,33 +117,6 @@
         }
     }
 
-    private void initPanel() {
-        mDismissDelay = mContext.getResources().getInteger(R.integer.volume_panel_dismiss_delay);
-        mPanel = new VolumePanel(mContext, new ZenModeControllerImpl(mContext, mHandler));
-        mPanel.setCallback(new VolumePanel.Callback() {
-            @Override
-            public void onZenSettings() {
-                mHandler.removeCallbacks(mStartZenSettings);
-                mHandler.post(mStartZenSettings);
-            }
-
-            @Override
-            public void onInteraction() {
-                final KeyguardViewMediator kvm = getComponent(KeyguardViewMediator.class);
-                if (kvm != null) {
-                    kvm.userActivity();
-                }
-            }
-
-            @Override
-            public void onVisible(boolean visible) {
-                if (mAudioManager != null && mVolumeController != null) {
-                    mAudioManager.notifyVolumeControllerVisible(mVolumeController, visible);
-                }
-            }
-        });
-    }
-
     private String getAppLabel(ComponentName component) {
         final String pkg = component.getPackageName();
         try {
@@ -179,83 +144,11 @@
         d.show();
     }
 
-    private final Runnable mStartZenSettings = new Runnable() {
-        @Override
-        public void run() {
-            getComponent(PhoneStatusBar.class).startActivityDismissingKeyguard(
-                    ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */);
-            mPanel.postDismiss(mDismissDelay);
-        }
-    };
-
-    /** For now, simply host an unmodified base volume panel in this process. */
-    private final class VolumeController extends IVolumeController.Stub implements VolumeComponent {
-
-        @Override
-        public void displaySafeVolumeWarning(int flags) throws RemoteException {
-            mPanel.postDisplaySafeVolumeWarning(flags);
-        }
-
-        @Override
-        public void volumeChanged(int streamType, int flags)
-                throws RemoteException {
-            mPanel.postVolumeChanged(streamType, flags);
-        }
-
-        @Override
-        public void masterMuteChanged(int flags) throws RemoteException {
-            // no-op
-        }
-
-        @Override
-        public void setLayoutDirection(int layoutDirection)
-                throws RemoteException {
-            mPanel.postLayoutDirection(layoutDirection);
-        }
-
-        @Override
-        public void dismiss() throws RemoteException {
-            dismissNow();
-        }
-
-        @Override
-        public ZenModeController getZenController() {
-            return mPanel.getZenController();
-        }
-
-        @Override
-        public void dispatchDemoCommand(String command, Bundle args) {
-            mPanel.dispatchDemoCommand(command, args);
-        }
-
-        @Override
-        public void dismissNow() {
-            mPanel.postDismiss(0);
-        }
-    }
-
-    private final class RemoteVolumeController extends IRemoteVolumeController.Stub {
-
-        @Override
-        public void remoteVolumeChanged(ISessionController binder, int flags)
-                throws RemoteException {
-            MediaController controller = new MediaController(mContext, binder);
-            mPanel.postRemoteVolumeChanged(controller, flags);
-        }
-
-        @Override
-        public void updateRemoteController(ISessionController session) throws RemoteException {
-            mPanel.postRemoteSliderVisibility(session != null);
-            // TODO stash default session in case the slider can be opened other
-            // than by remoteVolumeChanged.
-        }
-    }
-
     private final class ServiceMonitorCallbacks implements ServiceMonitor.Callbacks {
         @Override
         public void onNoService() {
             if (LOGD) Log.d(TAG, "onNoService");
-            setVolumeController(true);
+            setDefaultVolumeController(true);
             mRestorationNotification.hide();
             if (!mVolumeControllerService.isPackageAvailable()) {
                 mVolumeControllerService.setComponent(null);
@@ -267,8 +160,8 @@
             if (LOGD) Log.d(TAG, "onServiceStartAttempt");
             // poke the setting to update the uid
             mVolumeControllerService.setComponent(mVolumeControllerService.getComponent());
-            setVolumeController(false);
-            mVolumeController.dismissNow();
+            setDefaultVolumeController(false);
+            getVolumeComponent().dismissNow();
             mRestorationNotification.show();
             return 0;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
new file mode 100644
index 0000000..f99eb6d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -0,0 +1,221 @@
+/*
+ * 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.volume;
+
+import android.animation.LayoutTransition;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings.Global;
+import android.service.notification.Condition;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.LinearLayout;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.ZenModeController;
+
+/**
+ * Switch bar + zen mode panel (conditions) attached to the bottom of the volume dialog.
+ */
+public class ZenFooter extends LinearLayout {
+    private static final String TAG = Util.logTag(ZenFooter.class);
+
+    private final Context mContext;
+    private final float mSecondaryAlpha;
+    private final LayoutTransition mLayoutTransition;
+
+    private ZenModeController mController;
+    private Switch mSwitch;
+    private ZenModePanel mZenModePanel;
+    private View mZenModePanelButtons;
+    private View mZenModePanelMoreButton;
+    private View mZenModePanelDoneButton;
+    private View mSwitchBar;
+    private View mSwitchBarIcon;
+    private View mSummary;
+    private TextView mSummaryLine1;
+    private TextView mSummaryLine2;
+    private boolean mFooterExpanded;
+    private int mZen = -1;
+    private Callback mCallback;
+
+    public ZenFooter(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+        mSecondaryAlpha = getFloat(context.getResources(), R.dimen.volume_secondary_alpha);
+        mLayoutTransition = new LayoutTransition();
+        mLayoutTransition.setDuration(new ValueAnimator().getDuration() / 2);
+        mLayoutTransition.disableTransitionType(LayoutTransition.DISAPPEARING);
+        mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
+    }
+
+    private static float getFloat(Resources r, int resId) {
+        final TypedValue tv = new TypedValue();
+        r.getValue(resId, tv, true);
+        return tv.getFloat();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mSwitchBar = findViewById(R.id.volume_zen_switch_bar);
+        mSwitchBarIcon = findViewById(R.id.volume_zen_switch_bar_icon);
+        mSwitch = (Switch) findViewById(R.id.volume_zen_switch);
+        mZenModePanel = (ZenModePanel) findViewById(R.id.zen_mode_panel);
+        mZenModePanelButtons = findViewById(R.id.volume_zen_mode_panel_buttons);
+        mZenModePanelMoreButton = findViewById(R.id.volume_zen_mode_panel_more);
+        mZenModePanelDoneButton = findViewById(R.id.volume_zen_mode_panel_done);
+        mSummary = findViewById(R.id.volume_zen_panel_summary);
+        mSummaryLine1 = (TextView) findViewById(R.id.volume_zen_panel_summary_line_1);
+        mSummaryLine2 = (TextView) findViewById(R.id.volume_zen_panel_summary_line_2);
+    }
+
+    public void init(ZenModeController controller, Callback callback) {
+        mCallback = callback;
+        mController = controller;
+        mZenModePanel.init(controller);
+        mZenModePanel.setEmbedded(true);
+        mSwitch.setOnCheckedChangeListener(mCheckedListener);
+        mController.addCallback(new ZenModeController.Callback() {
+            @Override
+            public void onZenChanged(int zen) {
+                setZen(zen);
+            }
+            @Override
+            public void onExitConditionChanged(Condition exitCondition) {
+                update();
+            }
+        });
+        mSwitchBar.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mSwitch.setChecked(!mSwitch.isChecked());
+            }
+        });
+        mZenModePanelMoreButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mCallback != null) {
+                    mCallback.onSettingsClicked();
+                }
+            }
+        });
+        mZenModePanelDoneButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mCallback != null) {
+                    mCallback.onDoneClicked();
+                }
+            }
+        });
+        mZen = mController.getZen();
+        update();
+    }
+
+    private void setZen(int zen) {
+        if (mZen == zen) return;
+        mZen = zen;
+        update();
+    }
+
+    public boolean isZen() {
+        return isZenPriority() || isZenAlarms() || isZenNone();
+    }
+
+    private boolean isZenPriority() {
+        return mZen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+    }
+
+    private boolean isZenAlarms() {
+        return mZen == Global.ZEN_MODE_ALARMS;
+    }
+
+    private boolean isZenNone() {
+        return mZen == Global.ZEN_MODE_NO_INTERRUPTIONS;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        setLayoutTransition(null);
+        setFooterExpanded(false);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        setLayoutTransition(mLayoutTransition);
+    }
+
+    private boolean setFooterExpanded(boolean expanded) {
+        if (mFooterExpanded == expanded) return false;
+        mFooterExpanded = expanded;
+        update();
+        if (mCallback != null) {
+            mCallback.onFooterExpanded();
+        }
+        return true;
+    }
+
+    public boolean isFooterExpanded() {
+        return mFooterExpanded;
+    }
+
+    public void update() {
+        final boolean isZen = isZen();
+        mSwitch.setOnCheckedChangeListener(null);
+        mSwitch.setChecked(isZen);
+        mSwitch.setOnCheckedChangeListener(mCheckedListener);
+        Util.setVisOrGone(mZenModePanel, isZen && mFooterExpanded);
+        Util.setVisOrGone(mZenModePanelButtons, isZen && mFooterExpanded);
+        Util.setVisOrGone(mSummary, isZen && !mFooterExpanded);
+        mSwitchBarIcon.setAlpha(isZen ? 1 : mSecondaryAlpha);
+        final String line1 =
+                isZenPriority() ? mContext.getString(R.string.interruption_level_priority)
+                : isZenAlarms() ? mContext.getString(R.string.interruption_level_alarms)
+                : isZenNone() ? mContext.getString(R.string.interruption_level_none)
+                : null;
+        Util.setText(mSummaryLine1, line1);
+        Util.setText(mSummaryLine2, mZenModePanel.getExitConditionText());
+    }
+
+    private final OnCheckedChangeListener mCheckedListener = new OnCheckedChangeListener() {
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            if (D.BUG) Log.d(TAG, "onCheckedChanged " + isChecked);
+            if (isChecked != isZen()) {
+                final int newZen = isChecked ? Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+                        : Global.ZEN_MODE_OFF;
+                mZen = newZen;  // this one's optimistic
+                setFooterExpanded(isChecked);
+                mController.setZen(newZen);
+            }
+        }
+    };
+
+    public interface Callback {
+        void onFooterExpanded();
+        void onSettingsClicked();
+        void onDoneClicked();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 878ab712..cb6c29f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -23,7 +23,6 @@
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.content.res.Resources;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Handler;
@@ -150,12 +149,13 @@
         if (mEmbedded == embedded) return;
         mEmbedded = embedded;
         mZenButtonsContainer.setLayoutTransition(mEmbedded ? null : newLayoutTransition(null));
+        setLayoutTransition(mEmbedded ? null : newLayoutTransition(null));
         if (mEmbedded) {
             mZenButtonsContainer.setBackground(null);
         } else {
             mZenButtonsContainer.setBackgroundResource(R.drawable.qs_background_secondary);
         }
-        mZenButtons.getChildAt(2).setVisibility(mEmbedded ? GONE : VISIBLE);
+        mZenButtons.getChildAt(3).setVisibility(mEmbedded ? GONE : VISIBLE);
         mZenEmbeddedDivider.setVisibility(mEmbedded ? VISIBLE : GONE);
         setExpanded(mEmbedded);
         updateWidgets();
@@ -166,12 +166,13 @@
         super.onFinishInflate();
 
         mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons);
-        mZenButtons.addButton(R.string.interruption_level_none, R.drawable.ic_zen_none,
+        mZenButtons.addButton(R.string.interruption_level_none_twoline,
                 Global.ZEN_MODE_NO_INTERRUPTIONS);
-        mZenButtons.addButton(R.string.interruption_level_priority, R.drawable.ic_zen_important,
+        mZenButtons.addButton(R.string.interruption_level_alarms_twoline,
+                Global.ZEN_MODE_ALARMS);
+        mZenButtons.addButton(R.string.interruption_level_priority_twoline,
                 Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
-        mZenButtons.addButton(R.string.interruption_level_all, R.drawable.ic_zen_all,
-                Global.ZEN_MODE_OFF);
+        mZenButtons.addButton(R.string.interruption_level_all, Global.ZEN_MODE_OFF);
         mZenButtons.setCallback(mZenButtonsCallback);
 
         mZenButtonsContainer = (ViewGroup) findViewById(R.id.zen_buttons_container);
@@ -275,6 +276,7 @@
 
     private void setExpanded(boolean expanded) {
         if (expanded == mExpanded) return;
+        if (DEBUG) Log.d(mTag, "setExpanded " + expanded);
         mExpanded = expanded;
         if (mExpanded) {
             ensureSelection();
@@ -358,6 +360,10 @@
         return condition == null ? null : condition.copy();
     }
 
+    public String getExitConditionText() {
+        return mExitConditionText;
+    }
+
     private void refreshExitConditionText() {
         if (mExitCondition == null) {
             mExitConditionText = foreverSummary();
@@ -428,7 +434,7 @@
         mZenSubheadExpanded.setVisibility(expanded ? VISIBLE : GONE);
         mZenSubheadCollapsed.setVisibility(!expanded ? VISIBLE : GONE);
         mMoreSettings.setVisibility(zenImportant && expanded ? VISIBLE : GONE);
-        mZenConditions.setVisibility(!zenOff && expanded ? VISIBLE : GONE);
+        mZenConditions.setVisibility(mEmbedded || !zenOff && expanded ? VISIBLE : GONE);
 
         if (zenNone) {
             mZenSubheadExpanded.setText(R.string.zen_no_interruptions_with_warning);
@@ -715,7 +721,10 @@
             case Global.ZEN_MODE_NO_INTERRUPTIONS:
                 modeText = mContext.getString(R.string.zen_no_interruptions);
                 break;
-             default:
+            case Global.ZEN_MODE_ALARMS:
+                modeText = mContext.getString(R.string.zen_alarms);
+                break;
+            default:
                 return;
         }
         announceForAccessibility(mContext.getString(R.string.zen_mode_and_condition, modeText,
diff --git a/preloaded-classes b/preloaded-classes
index c8d8c5d..151766f 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -1146,8 +1146,6 @@
 android.provider.Settings$System
 android.provider.Telephony$Mms
 android.renderscript.RenderScript
-android.security.AndroidKeyPairGenerator
-android.security.AndroidKeyStore
 android.security.AndroidKeyStoreProvider
 android.speech.tts.TextToSpeechService
 android.speech.tts.TextToSpeechService$SpeechItemV1
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 523c8fb..2203850 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -273,8 +273,8 @@
     }
 
     /**
-     * @hide
      * Enable/Disable AutoPadding for Vec3 elements.
+     * By default: Diabled.
      *
      * @param useAutoPadding True: enable AutoPadding; flase: disable AutoPadding
      *
@@ -802,7 +802,7 @@
 
     /**
      * This is only intended to be used by auto-generated code reflected from
-     * the RenderScript script files.
+     * the RenderScript script files and should not be used by developers.
      *
      * @param xoff
      * @param component_number
@@ -813,9 +813,8 @@
     }
 
     /**
-     * @hide
      * This is only intended to be used by auto-generated code reflected from
-     * the RenderScript script files.
+     * the RenderScript script files and should not be used by developers.
      *
      * @param xoff
      * @param yoff
@@ -1247,8 +1246,11 @@
     }
 
     /**
-     * @hide
+     * Copy a rectangular region from the array into the allocation.
+     * The array is assumed to be tightly packed.
      *
+     * The data type of the array is not required to be the same as
+     * the element data type.
      */
     private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
                                           Object array, Element.DataType dt, int arrayLen) {
@@ -1277,7 +1279,6 @@
     }
 
     /**
-     * @hide
      * Copy a rectangular region from the array into the allocation.
      * The array is assumed to be tightly packed.
      *
@@ -1298,7 +1299,6 @@
     }
 
     /**
-     * @hide
      * Copy a rectangular region into the allocation from another
      * allocation.
      *
@@ -1340,15 +1340,22 @@
 
     private void copyTo(Object array, Element.DataType dt, int arrayLen) {
         Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
-        if (dt.mSize * arrayLen < mSize) {
-            throw new RSIllegalArgumentException(
-                "Size of output array cannot be smaller than size of allocation.");
-        }
         mRS.validate();
         boolean usePadding = false;
         if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
             usePadding = true;
         }
+        if (usePadding) {
+            if (dt.mSize * arrayLen < mSize / 4 * 3) {
+                throw new RSIllegalArgumentException(
+                    "Size of output array cannot be smaller than size of allocation.");
+            }
+        } else {
+            if (dt.mSize * arrayLen < mSize) {
+                throw new RSIllegalArgumentException(
+                    "Size of output array cannot be smaller than size of allocation.");
+            }
+        }
         mRS.nAllocationRead(getID(mRS), array, dt, mType.mElement.mType.mSize, usePadding);
         Trace.traceEnd(RenderScript.TRACE_TAG);
     }
@@ -1415,7 +1422,6 @@
     }
 
     /**
-     * @hide
      * This is only intended to be used by auto-generated code reflected from
      * the RenderScript script files and should not be used by developers.
      *
@@ -1423,7 +1429,7 @@
      * @param yoff
      * @param zoff
      * @param component_number
-     * @param array
+     * @param fp
      */
     public void copyToFieldPacker(int xoff, int yoff, int zoff, int component_number, FieldPacker fp) {
         mRS.validate();
@@ -1501,7 +1507,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
      *
@@ -1516,7 +1521,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
      *
@@ -1529,7 +1533,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
      *
@@ -1542,7 +1545,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
      *
@@ -1555,7 +1557,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
      *
@@ -1569,7 +1570,6 @@
 
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * and will generate exceptions if the Allocation type does not
      * match the component type of the array passed in.
@@ -1585,7 +1585,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * and will generate exceptions if the Allocation type is not a 32 bit
      * integer type.
@@ -1600,7 +1599,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * and will generate exceptions if the Allocation type is not a 16 bit
      * integer type.
@@ -1615,7 +1613,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * and will generate exceptions if the Allocation type is not an 8 bit
      * integer type.
@@ -1630,7 +1627,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * and will generate exceptions if the Allocation type is not a 32 bit float
      * type.
@@ -1671,7 +1667,6 @@
     }
 
     /**
-     * @hide
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
@@ -1687,7 +1682,6 @@
     }
 
     /**
-     * @hide
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
@@ -1703,7 +1697,6 @@
     }
 
     /**
-     * @hide
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
@@ -1719,7 +1712,6 @@
     }
 
     /**
-     * @hide
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
@@ -1735,7 +1727,6 @@
     }
 
     /**
-     * @hide
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
@@ -1752,8 +1743,11 @@
 
 
     /**
-     * @hide
+     * Copy from a rectangular region in this Allocation into an array.
+     * The array is assumed to be tightly packed.
      *
+     * The data type of the array is not required to be the same as
+     * the element data type.
      */
     private void copy3DRangeToUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
                                         Object array, Element.DataType dt, int arrayLen) {
@@ -1780,8 +1774,7 @@
         Trace.traceEnd(RenderScript.TRACE_TAG);
     }
 
-    /**
-     * @hide
+    /*
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index 287b3f1..4b3e30f 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -114,13 +114,11 @@
      * MATRIX the three matrix types contain FLOAT_32 elements and are treated
      * as 32 bits for alignment purposes.
      *
-     * RS_* objects.  32 bit opaque handles.
+     * RS_* objects:  opaque handles with implementation dependent
+     * sizes.
      */
     public enum DataType {
         NONE (0, 0),
-        /**
-         *     @hide
-         */
         FLOAT_16 (1, 2),
         FLOAT_32 (2, 4),
         FLOAT_64 (3, 8),
@@ -389,9 +387,6 @@
         return rs.mElement_I64;
     }
 
-    /**
-     *     @hide
-     */
     public static Element F16(RenderScript rs) {
         if(rs.mElement_F16 == null) {
             rs.mElement_F16 = createUser(rs, DataType.FLOAT_16);
@@ -533,9 +528,6 @@
         return rs.mElement_RGBA_8888;
     }
 
-    /**
-     *     @hide
-     */
     public static Element F16_2(RenderScript rs) {
         if(rs.mElement_HALF_2 == null) {
             rs.mElement_HALF_2 = createVector(rs, DataType.FLOAT_16, 2);
@@ -543,9 +535,6 @@
         return rs.mElement_HALF_2;
     }
 
-    /**
-     *     @hide
-     */
     public static Element F16_3(RenderScript rs) {
         if(rs.mElement_FLOAT_3 == null) {
             rs.mElement_FLOAT_3 = createVector(rs, DataType.FLOAT_16, 3);
@@ -553,9 +542,6 @@
         return rs.mElement_HALF_3;
     }
 
-    /**
-     *     @hide
-     */
     public static Element F16_4(RenderScript rs) {
         if(rs.mElement_HALF_4 == null) {
             rs.mElement_HALF_4 = createVector(rs, DataType.FLOAT_16, 4);
diff --git a/rs/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java
index 0f967fc..de1c497 100644
--- a/rs/java/android/renderscript/FieldPacker.java
+++ b/rs/java/android/renderscript/FieldPacker.java
@@ -47,6 +47,15 @@
         // subAlign() can never work correctly for copied FieldPacker objects.
     }
 
+    static FieldPacker createFromArray(Object[] args) {
+        FieldPacker fp = new FieldPacker(RenderScript.sPointerSize * 8);
+        for (Object arg : args) {
+            fp.addSafely(arg);
+        }
+        fp.resize(fp.mPos);
+        return fp;
+    }
+
     public void align(int v) {
         if ((v <= 0) || ((v & (v - 1)) != 0)) {
             throw new RSIllegalArgumentException("argument must be a non-negative non-zero power of 2: " + v);
@@ -618,294 +627,182 @@
         return mPos;
     }
 
-    private static void addToPack(FieldPacker fp, Object obj) {
+    private void add(Object obj) {
         if (obj instanceof Boolean) {
-            fp.addBoolean(((Boolean)obj).booleanValue());
+            addBoolean((Boolean)obj);
             return;
         }
 
         if (obj instanceof Byte) {
-            fp.addI8(((Byte)obj).byteValue());
+            addI8((Byte)obj);
             return;
         }
 
         if (obj instanceof Short) {
-            fp.addI16(((Short)obj).shortValue());
+            addI16((Short)obj);
             return;
         }
 
         if (obj instanceof Integer) {
-            fp.addI32(((Integer)obj).intValue());
+            addI32((Integer)obj);
             return;
         }
 
         if (obj instanceof Long) {
-            fp.addI64(((Long)obj).longValue());
+            addI64((Long)obj);
             return;
         }
 
         if (obj instanceof Float) {
-            fp.addF32(((Float)obj).floatValue());
+            addF32((Float)obj);
             return;
         }
 
         if (obj instanceof Double) {
-            fp.addF64(((Double)obj).doubleValue());
+            addF64((Double)obj);
             return;
         }
 
         if (obj instanceof Byte2) {
-            fp.addI8((Byte2)obj);
+            addI8((Byte2)obj);
             return;
         }
 
         if (obj instanceof Byte3) {
-            fp.addI8((Byte3)obj);
+            addI8((Byte3)obj);
             return;
         }
 
         if (obj instanceof Byte4) {
-            fp.addI8((Byte4)obj);
+            addI8((Byte4)obj);
             return;
         }
 
         if (obj instanceof Short2) {
-            fp.addI16((Short2)obj);
+            addI16((Short2)obj);
             return;
         }
 
         if (obj instanceof Short3) {
-            fp.addI16((Short3)obj);
+            addI16((Short3)obj);
             return;
         }
 
         if (obj instanceof Short4) {
-            fp.addI16((Short4)obj);
+            addI16((Short4)obj);
             return;
         }
 
         if (obj instanceof Int2) {
-            fp.addI32((Int2)obj);
+            addI32((Int2)obj);
             return;
         }
 
         if (obj instanceof Int3) {
-            fp.addI32((Int3)obj);
+            addI32((Int3)obj);
             return;
         }
 
         if (obj instanceof Int4) {
-            fp.addI32((Int4)obj);
+            addI32((Int4)obj);
             return;
         }
 
         if (obj instanceof Long2) {
-            fp.addI64((Long2)obj);
+            addI64((Long2)obj);
             return;
         }
 
         if (obj instanceof Long3) {
-            fp.addI64((Long3)obj);
+            addI64((Long3)obj);
             return;
         }
 
         if (obj instanceof Long4) {
-            fp.addI64((Long4)obj);
+            addI64((Long4)obj);
             return;
         }
 
         if (obj instanceof Float2) {
-            fp.addF32((Float2)obj);
+            addF32((Float2)obj);
             return;
         }
 
         if (obj instanceof Float3) {
-            fp.addF32((Float3)obj);
+            addF32((Float3)obj);
             return;
         }
 
         if (obj instanceof Float4) {
-            fp.addF32((Float4)obj);
+            addF32((Float4)obj);
             return;
         }
 
         if (obj instanceof Double2) {
-            fp.addF64((Double2)obj);
+            addF64((Double2)obj);
             return;
         }
 
         if (obj instanceof Double3) {
-            fp.addF64((Double3)obj);
+            addF64((Double3)obj);
             return;
         }
 
         if (obj instanceof Double4) {
-            fp.addF64((Double4)obj);
+            addF64((Double4)obj);
             return;
         }
 
         if (obj instanceof Matrix2f) {
-            fp.addMatrix((Matrix2f)obj);
+            addMatrix((Matrix2f)obj);
             return;
         }
 
         if (obj instanceof Matrix3f) {
-            fp.addMatrix((Matrix3f)obj);
+            addMatrix((Matrix3f)obj);
             return;
         }
 
         if (obj instanceof Matrix4f) {
-            fp.addMatrix((Matrix4f)obj);
+            addMatrix((Matrix4f)obj);
             return;
         }
 
         if (obj instanceof BaseObj) {
-            fp.addObj((BaseObj)obj);
+            addObj((BaseObj)obj);
             return;
         }
     }
 
-    private static int getPackedSize(Object obj) {
-        if (obj instanceof Boolean) {
-            return 1;
+    private boolean resize(int newSize) {
+        if (newSize == mLen) {
+            return false;
         }
 
-        if (obj instanceof Byte) {
-            return 1;
-        }
+        byte[] newData = new byte[newSize];
+        System.arraycopy(mData, 0, newData, 0, mPos);
+        mData = newData;
+        mLen = newSize;
+        return true;
+    }
 
-        if (obj instanceof Short) {
-            return 2;
-        }
-
-        if (obj instanceof Integer) {
-            return 4;
-        }
-
-        if (obj instanceof Long) {
-            return 8;
-        }
-
-        if (obj instanceof Float) {
-            return 4;
-        }
-
-        if (obj instanceof Double) {
-            return 8;
-        }
-
-        if (obj instanceof Byte2) {
-            return 2;
-        }
-
-        if (obj instanceof Byte3) {
-            return 3;
-        }
-
-        if (obj instanceof Byte4) {
-            return 4;
-        }
-
-        if (obj instanceof Short2) {
-            return 4;
-        }
-
-        if (obj instanceof Short3) {
-            return 6;
-        }
-
-        if (obj instanceof Short4) {
-            return 8;
-        }
-
-        if (obj instanceof Int2) {
-            return 8;
-        }
-
-        if (obj instanceof Int3) {
-            return 12;
-        }
-
-        if (obj instanceof Int4) {
-            return 16;
-        }
-
-        if (obj instanceof Long2) {
-            return 16;
-        }
-
-        if (obj instanceof Long3) {
-            return 24;
-        }
-
-        if (obj instanceof Long4) {
-            return 32;
-        }
-
-        if (obj instanceof Float2) {
-            return 8;
-        }
-
-        if (obj instanceof Float3) {
-            return 12;
-        }
-
-        if (obj instanceof Float4) {
-            return 16;
-        }
-
-        if (obj instanceof Double2) {
-            return 16;
-        }
-
-        if (obj instanceof Double3) {
-            return 24;
-        }
-
-        if (obj instanceof Double4) {
-            return 32;
-        }
-
-        if (obj instanceof Matrix2f) {
-            return 16;
-        }
-
-        if (obj instanceof Matrix3f) {
-            return 36;
-        }
-
-        if (obj instanceof Matrix4f) {
-            return 64;
-        }
-
-        if (obj instanceof BaseObj) {
-            if (RenderScript.sPointerSize == 8) {
-                return 32;
-            } else {
-                return 4;
+    private void addSafely(Object obj) {
+        boolean retry;
+        final int oldPos = mPos;
+        do {
+            retry = false;
+            try {
+                add(obj);
+            } catch (ArrayIndexOutOfBoundsException e) {
+                mPos = oldPos;
+                resize(mLen * 2);
+                retry = true;
             }
-        }
-
-        return 0;
+        } while (retry);
     }
 
-    static FieldPacker createFieldPack(Object[] args) {
-        int len = 0;
-        for (Object arg : args) {
-            len += getPackedSize(arg);
-        }
-        FieldPacker fp = new FieldPacker(len);
-        for (Object arg : args) {
-            addToPack(fp, arg);
-        }
-        return fp;
-    }
-
-    private final byte mData[];
+    private byte mData[];
     private int mPos;
     private int mLen;
     private BitSet mAlignment;
-
 }
-
-
diff --git a/rs/java/android/renderscript/FileA3D.java b/rs/java/android/renderscript/FileA3D.java
index 4164810..9d8f162 100644
--- a/rs/java/android/renderscript/FileA3D.java
+++ b/rs/java/android/renderscript/FileA3D.java
@@ -145,6 +145,9 @@
             case MESH:
                 entry.mLoadedObj = new Mesh(objectID, rs);
                 break;
+
+            default:
+                throw new RSRuntimeException("Unrecognized object type in file.");
             }
 
             entry.mLoadedObj.updateFromNative();
diff --git a/rs/java/android/renderscript/Mesh.java b/rs/java/android/renderscript/Mesh.java
index 5b4cadb..13c8e1c 100644
--- a/rs/java/android/renderscript/Mesh.java
+++ b/rs/java/android/renderscript/Mesh.java
@@ -363,6 +363,9 @@
                     alloc = Allocation.createTyped(mRS, entry.t, mUsage);
                 } else if(entry.e != null) {
                     alloc = Allocation.createSized(mRS, entry.e, entry.size, mUsage);
+                } else {
+                    // Should never happen because the builder will always set one
+                    throw new IllegalStateException("Builder corrupt, no valid element in entry.");
                 }
                 vertexBuffers[ct] = alloc;
                 vtx[ct] = alloc.getID(mRS);
@@ -375,6 +378,9 @@
                     alloc = Allocation.createTyped(mRS, entry.t, mUsage);
                 } else if(entry.e != null) {
                     alloc = Allocation.createSized(mRS, entry.e, entry.size, mUsage);
+                } else {
+                    // Should never happen because the builder will always set one
+                    throw new IllegalStateException("Builder corrupt, no valid element in entry.");
                 }
                 long allocID = (alloc == null) ? 0 : alloc.getID(mRS);
                 indexBuffers[ct] = alloc;
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index e8e942c..7ef17a7 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -139,7 +139,8 @@
      * Returns an identifier that can be used to identify a particular
      * minor version of RS.
      *
-     * @hide
+     * @return The minor RenderScript version number
+     *
      */
     public static long getMinorID() {
         return sMinorID;
@@ -1321,7 +1322,6 @@
     /**
      * Create a RenderScript context.
      *
-     * @hide
      * @param ctx The context.
      * @return RenderScript
      */
@@ -1418,14 +1418,13 @@
      /**
      * Gets or creates a RenderScript context of the specified type.
      *
-     * @hide
      * @param ctx The context.
      * @param ct The type of context to be created.
      * @param sdkVersion The target SDK Version.
      * @param flags The OR of the CREATE_FLAG_* options desired
      * @return RenderScript
      */
-    public static RenderScript create(Context ctx, int sdkVersion, ContextType ct, int flags) {
+    private static RenderScript create(Context ctx, int sdkVersion, ContextType ct, int flags) {
         if (sdkVersion < 23) {
             return internalCreate(ctx, sdkVersion, ct, flags);
         }
@@ -1448,8 +1447,6 @@
     }
 
     /**
-     * @hide
-     *
      * Releases all the process contexts.  This is the same as
      * calling .destroy() on each unique context retreived with
      * create(...). If no contexts have been created this
@@ -1486,7 +1483,6 @@
      *
      * If you need a single context please use create()
      *
-     * @hide
      * @param ctx The context.
      * @return RenderScript
      */
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index 65056ac..6a1efee 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -66,7 +66,6 @@
     }
 
     /**
-     * @hide Pending API review
      * InvokeID is an identifier for an invoke function. It is used
      * as an identifier for ScriptGroup creation.
      *
@@ -86,7 +85,6 @@
 
     private final SparseArray<InvokeID> mIIDs = new SparseArray<InvokeID>();
     /**
-     * @hide Pending API review
      * Only to be used by generated reflected classes.
      */
     protected InvokeID createInvokeID(int slot) {
@@ -222,22 +220,21 @@
 
     /**
      * Only intended for use by generated reflected code.
-     *
-     * @hide
      */
     protected void forEach(int slot, Allocation[] ains, Allocation aout,
                            FieldPacker v) {
+
+        // FieldPacker is kept here to support regular params in the future.
         forEach(slot, ains, aout, v, null);
     }
 
     /**
      * Only intended for use by generated reflected code.
-     *
-     * @hide
      */
     protected void forEach(int slot, Allocation[] ains, Allocation aout,
                            FieldPacker v, LaunchOptions sc) {
         // TODO: Is this necessary if nScriptForEach calls validate as well?
+        // FieldPacker is kept here to support regular params in the future.
         mRS.validate();
         if (ains != null) {
             for (Allocation ain : ains) {
@@ -476,7 +473,23 @@
 
 
     /**
-     * Class used to specify clipping for a kernel launch.
+     * Class for specifying the specifics about how a kernel will be
+     * launched
+     *
+     * This class can specify a potential range of cells on which to
+     * run a kernel.  If no set is called for a dimension then this
+     * class will have no impact on that dimension when the kernel
+     * is executed.
+     *
+     * The forEach launch will operate over the intersection of the
+     * dimensions.
+     *
+     * Example:
+     * LaunchOptions with setX(5, 15)
+     * Allocation with dimension X=10, Y=10
+     * The resulting forEach run would execute over x = 5 to 10 and
+     * y = 0 to 10.
+     *
      *
      */
     public static final class LaunchOptions {
diff --git a/rs/java/android/renderscript/ScriptGroup2.java b/rs/java/android/renderscript/ScriptGroup2.java
index 4a56572..8b9f73e 100644
--- a/rs/java/android/renderscript/ScriptGroup2.java
+++ b/rs/java/android/renderscript/ScriptGroup2.java
@@ -24,26 +24,41 @@
 import java.util.Map;
 
 /**
+ * ScriptGroup2 is a new, enhanced API for script groups.
+ * A script group is a collection of kernels or invocable functions, with
+ * data dependencies defined among them. A script group is launched for
+ * execution as a whole, rather than launching each kernel or invocable function
+ * separately. Once created, a script group can be repeatedly used with
+ * different inputs.
+ * <p>
+ * In the new ScriptGroup2 API, a script group is modeled using closures.
+ * A closure, in this context, is defined as a function call to a kernel or
+ * invocable function. Each function argument or global variable accessed inside
+ * the function is bound to 1) a known value, 2) a script group input, or 3) a
+ * future. A future is the output of a closure, i.e., the return value of the
+ * function or a global variable written by that function.
+ * <p>
+ * A script group is a directed acyclic graph (DAG), in which closures are the
+ * vertices and the dependencies among them are the edges.
+ * The way the ScriptGroup2 API is designed makes cycles impossible in a script
+ * group. For example, it is impossible to make forward references to futures,
+ * i.e., it is impossible to set as input to a closure the future from itself or
+ * a future from another closure that directly or indirectly depends on it.
+ * <p>
+ * Grouping kernels and invocable functions together allows to execute them more
+ * efficiently. Runtime and compiler optimizations are applied to script
+ * groups, to reduce computation or communication overhead, and to make more
+ * efficient use of the CPU and the GPU.
+ */
 
-******************************
-You have tried to change the API from what has been previously approved.
-
-To make these errors go away, you have two choices:
-1) You can add "@hide" javadoc comments to the methods, etc. listed in the
-errors above.
-
-2) You can update current.txt by executing the following command:
-make update-api
-
-To submit the revised current.txt to the main Android repository,
-you will need approval.
-******************************
-
-@hide Pending Android public API approval.
-*/
 public class ScriptGroup2 extends BaseObj {
 
+    /**
+     * An opaque class for closures
+     */
+
     public static class Closure extends BaseObj {
+        private Object[] mArgs;
         private Allocation mReturnValue;
         private Map<Script.FieldID, Object> mBindings;
 
@@ -62,8 +77,9 @@
                        Object[] args, Map<Script.FieldID, Object> globals) {
             super(0, rs);
 
+            mArgs = args;
             mReturnValue = Allocation.createTyped(rs, returnType);
-            mBindings = new HashMap<Script.FieldID, Object>();
+            mBindings = globals;
             mGlobalFuture = new HashMap<Script.FieldID, Future>();
 
             int numValues = args.length + globals.size();
@@ -110,9 +126,10 @@
         public Closure(RenderScript rs, Script.InvokeID invokeID,
                        Object[] args, Map<Script.FieldID, Object> globals) {
             super(0, rs);
-            mFP = FieldPacker.createFieldPack(args);
+            mFP = FieldPacker.createFromArray(args);
 
-            mBindings = new HashMap<Script.FieldID, Object>();
+            mArgs = args;
+            mBindings = globals;
             mGlobalFuture = new HashMap<Script.FieldID, Future>();
 
             int numValues = globals.size();
@@ -132,7 +149,6 @@
                     UnboundValue unbound = (UnboundValue)obj;
                     unbound.addReference(this, fieldID);
                 } else {
-                    // TODO(yangni): Verify obj not a future.
                     retrieveValueAndDependenceInfo(rs, i, obj, values,
                                                    sizes, depClosures, depFieldIDs);
                 }
@@ -174,6 +190,12 @@
             sizes[index] = vs.size;
         }
 
+        /**
+         * Returns the future for the return value
+         *
+         * @return a future
+         */
+
         public Future getReturn() {
             if (mReturnFuture == null) {
                 mReturnFuture = new Future(this, null, mReturnValue);
@@ -182,6 +204,13 @@
             return mReturnFuture;
         }
 
+        /**
+         * Returns the future for a global variable
+         *
+         * @param field the field ID for the global variable
+         * @return a future
+         */
+
         public Future getGlobal(Script.FieldID field) {
             Future f = mGlobalFuture.get(field);
 
@@ -198,11 +227,13 @@
         }
 
         void setArg(int index, Object obj) {
+            mArgs[index] = obj;
             ValueAndSize vs = new ValueAndSize(mRS, obj);
             mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
         }
 
         void setGlobal(Script.FieldID fieldID, Object obj) {
+            mBindings.put(fieldID, obj);
             ValueAndSize vs = new ValueAndSize(mRS, obj);
             mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size);
         }
@@ -234,6 +265,10 @@
         }
     }
 
+    /**
+     * An opaque class for futures
+     */
+
     public static class Future {
         Closure mClosure;
         Script.FieldID mFieldID;
@@ -250,6 +285,10 @@
         Object getValue() { return mValue; }
     }
 
+    /**
+     * An opaque class for unbound values (a.k.a. script group inputs)
+     */
+
     public static class UnboundValue {
         // Either mFieldID or mArgIndex should be set but not both.
         List<Pair<Closure, Script.FieldID>> mFieldID;
@@ -309,6 +348,13 @@
         setID(id);
     }
 
+    /**
+     * Executes a script group
+     *
+     * @param inputs inputs to the script group
+     * @return outputs of the script group as an array of objects
+     */
+
     public Object[] execute(Object... inputs) {
         if (inputs.length < mInputs.size()) {
             Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " +
@@ -343,32 +389,95 @@
     }
 
     /**
-       @hide Pending Android public API approval.
-    */
+     * A class representing a binding of a value to a global variable in a
+     * kernel or invocable function. Such a binding can be used to create a
+     * closure.
+     */
+
     public static final class Binding {
-        public Script.FieldID mField;
-        public Object mValue;
+        private Script.FieldID mField;
+        private Object mValue;
+
+        /**
+         * Returns a Binding object that binds value to field
+         *
+         * @param field the Script.FieldID of the global variable
+         * @param value the value
+         */
+
         public Binding(Script.FieldID field, Object value) {
             mField = field;
             mValue = value;
         }
+
+        /**
+         * Returns the field ID
+         */
+
+        public Script.FieldID getField() { return mField; }
+
+        /**
+         * Returns the value
+         */
+
+        public Object getValue() { return mValue; }
     }
 
     /**
-       @hide Pending Android public API approval.
-    */
+     * The builder class to create a script group.
+     * <p>
+     * Closures are created using the {@link #addKernel} or {@link #addInvoke}
+     * methods.
+     * When a closure is created, futures from previously created closures
+     * can be used as inputs.
+     * Unbound values can be used as inputs to create closures as well.
+     * An unbound value is created using the {@link #addInput} method.
+     * Unbound values become inputs to the script group to be created,
+     * in the order that they are added.
+     * A script group is created by a call to the {@link #create} method, which
+     * accepts an array of futures as the outputs for the script group.
+     * <p>
+     * Closures in a script group can be evaluated in any order as long as the
+     * following conditions are met.
+     * First, a closure must be evaluated before any other closures that take its
+     * futures as inputs.
+     * Second, all closures added before an invoke closure must be evaluated
+     * before it.
+     * Third, all closures added after an invoke closure must be evaluated after
+     * it.
+     * <p>
+     * As a special case, the order that the closures are added is a legal
+     * evaluation order. However, other evaluation orders are allowed, including
+     * concurrently evaluating independent closures.
+     */
+
     public static final class Builder {
         RenderScript mRS;
         List<Closure> mClosures;
         List<UnboundValue> mInputs;
         private static final String TAG = "ScriptGroup2.Builder";
 
+        /**
+         * Returns a Builder object
+         *
+         * @param rs the RenderScript context
+         */
         public Builder(RenderScript rs) {
             mRS = rs;
             mClosures = new ArrayList<Closure>();
             mInputs = new ArrayList<UnboundValue>();
         }
 
+        /**
+         * Adds a closure for a kernel
+         *
+         * @param k Kernel ID for the kernel function
+         * @param returnType Allocation type for the return value
+         * @param args arguments to the kernel function
+         * @param globalBindings bindings for global variables
+         * @return a closure
+         */
+
         public Closure addKernel(Script.KernelID k, Type returnType, Object[] args,
                                  Map<Script.FieldID, Object> globalBindings) {
             Closure c = new Closure(mRS, k, returnType, args, globalBindings);
@@ -376,6 +485,15 @@
             return c;
         }
 
+        /**
+         * Adds a closure for an invocable function
+         *
+         * @param invoke Invoke ID for the invocable function
+         * @param args arguments to the invocable function
+         * @param globalBindings bindings for global variables
+         * @return a closure
+         */
+
         public Closure addInvoke(Script.InvokeID invoke, Object[] args,
                                  Map<Script.FieldID, Object> globalBindings) {
             Closure c = new Closure(mRS, invoke, args, globalBindings);
@@ -383,12 +501,25 @@
             return c;
         }
 
+        /**
+         * Adds a script group input
+         *
+         * @return a unbound value that can be used to create a closure
+         */
         public UnboundValue addInput() {
             UnboundValue unbound = new UnboundValue();
             mInputs.add(unbound);
             return unbound;
         }
 
+        /**
+         * Adds a closure for a kernel
+         *
+         * @param k Kernel ID for the kernel function
+         * @param argsAndBindings arguments followed by bindings for global variables
+         * @return a closure
+         */
+
         public Closure addKernel(Script.KernelID k, Type returnType, Object... argsAndBindings) {
             ArrayList<Object> args = new ArrayList<Object>();
             Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
@@ -398,6 +529,14 @@
             return addKernel(k, returnType, args.toArray(), bindingMap);
         }
 
+        /**
+         * Adds a closure for an invocable function
+         *
+         * @param invoke Invoke ID for the invocable function
+         * @param argsAndBindings arguments followed by bindings for global variables
+         * @return a closure
+         */
+
         public Closure addInvoke(Script.InvokeID invoke, Object... argsAndBindings) {
             ArrayList<Object> args = new ArrayList<Object>();
             Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>();
@@ -407,6 +546,13 @@
             return addInvoke(invoke, args.toArray(), bindingMap);
         }
 
+        /**
+         * Creates a script group
+         *
+         * @param outputs futures intended as outputs of the script group
+         * @return a script group
+         */
+
         public ScriptGroup2 create(Future... outputs) {
             ScriptGroup2 ret = new ScriptGroup2(mRS, mClosures, mInputs, outputs);
             return ret;
@@ -428,7 +574,7 @@
                     return false;
                 }
                 Binding b = (Binding)argsAndBindings[i];
-                bindingMap.put(b.mField, b.mValue);
+                bindingMap.put(b.getField(), b.getValue());
             }
 
             return true;
diff --git a/rs/java/android/renderscript/ScriptIntrinsicBlur.java b/rs/java/android/renderscript/ScriptIntrinsicBlur.java
index 5c4edd3..60e2b6d 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicBlur.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicBlur.java
@@ -34,7 +34,7 @@
      * Create an intrinsic for applying a blur to an allocation. The
      * default radius is 5.0.
      *
-     * Supported elements types are {@link Element#U8_4}
+     * Supported elements types are {@link Element#U8_4 Element#U8}
      *
      * @param rs The RenderScript context
      * @param e Element type for inputs and outputs
diff --git a/rs/java/android/renderscript/Type.java b/rs/java/android/renderscript/Type.java
index a58e42c..cc9b58b 100644
--- a/rs/java/android/renderscript/Type.java
+++ b/rs/java/android/renderscript/Type.java
@@ -150,24 +150,29 @@
     }
 
     /**
-     * @hide
-     */
-    public int getArray(int dim) {
-        if ((dim < 0) || (dim >= mMaxArrays)) {
+      * Return the dimension of the specified array.
+      *
+      * @param arrayNum  The array dimension to query
+      * @return int
+      */
+    public int getArray(int arrayNum) {
+        if ((arrayNum < 0) || (arrayNum >= mMaxArrays)) {
             throw new RSIllegalArgumentException("Array dimension out of range.");
         }
 
-        if (mArrays == null || dim >= mArrays.length) {
+        if (mArrays == null || arrayNum >= mArrays.length) {
             // Dimension in range but no array for that dimension allocated
             return 0;
         }
 
-        return mArrays[dim];
+        return mArrays[arrayNum];
     }
 
     /**
-     * @hide
-     */
+      * Return the number of array dimensions.
+      *
+      * @return int
+      */
     public int getArrayCount() {
         if (mArrays != null) return mArrays.length;
         return 0;
@@ -377,7 +382,7 @@
         }
 
         /**
-         * @hide
+         * Adds an array dimension to the builder
          *
          * @param dim
          * @param value
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 886845c..40fad38 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -367,7 +367,7 @@
   return (jlong)(uintptr_t)rsClosureCreate(
       (RsContext)con, (RsScriptKernelID)kernelID, (RsAllocation)returnValue,
       fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
-      (size_t*)sizes, (size_t)sizes_length,
+      (int*)sizes, (size_t)sizes_length,
       depClosures, (size_t)depClosures_length,
       depFieldIDs, (size_t)depFieldIDs_length);
 }
@@ -400,7 +400,7 @@
   return (jlong)(uintptr_t)rsInvokeClosureCreate(
       (RsContext)con, (RsScriptInvokeID)invokeID, jParams, jParamLength,
       fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
-      (size_t*)sizes, (size_t)sizes_length);
+      (int*)sizes, (size_t)sizes_length);
 }
 
 static void
diff --git a/services/Android.mk b/services/Android.mk
index 8777085..1918db5 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -24,6 +24,7 @@
     appwidget \
     backup \
     devicepolicy \
+    midi \
     net \
     print \
     restrictions \
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 31f9e22..96840a2 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -29,6 +29,7 @@
 import android.app.backup.BackupDataOutput;
 import android.app.backup.BackupTransport;
 import android.app.backup.FullBackup;
+import android.app.backup.FullBackupDataOutput;
 import android.app.backup.RestoreDescription;
 import android.app.backup.RestoreSet;
 import android.app.backup.IBackupManager;
@@ -93,6 +94,7 @@
 import com.android.server.EventLogTags;
 import com.android.server.SystemService;
 import com.android.server.backup.PackageManagerBackupAgent.Metadata;
+import com.android.server.pm.PackageManagerService;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
@@ -134,6 +136,7 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.zip.Deflater;
@@ -369,7 +372,7 @@
                     // we're now good to go, so start the backup alarms
                     if (MORE_DEBUG) Slog.d(TAG, "Now provisioned, so starting backups");
                     KeyValueBackupJob.schedule(mContext);
-                    scheduleNextFullBackupJob();
+                    scheduleNextFullBackupJob(0);
                 }
             }
         }
@@ -726,7 +729,7 @@
             {
                 try {
                     BackupRestoreTask task = (BackupRestoreTask) msg.obj;
-                    task.operationComplete();
+                    task.operationComplete(msg.arg1);
                 } catch (ClassCastException e) {
                     Slog.e(TAG, "Invalid completion in flight, obj=" + msg.obj);
                 }
@@ -1784,7 +1787,7 @@
                         PackageInfo app = mPackageManager.getPackageInfo(packageName, 0);
                         if (appGetsFullBackup(app) && appIsEligibleForBackup(app.applicationInfo)) {
                             enqueueFullBackup(packageName, now);
-                            scheduleNextFullBackupJob();
+                            scheduleNextFullBackupJob(0);
                         }
 
                         // Transport maintenance: rebind to known existing transports that have
@@ -2224,7 +2227,7 @@
         void execute();
 
         // An operation that wanted a callback has completed
-        void operationComplete();
+        void operationComplete(int result);
 
         // An operation that wanted a callback has timed out
         void handleTimeout();
@@ -2792,7 +2795,7 @@
         }
 
         @Override
-        public void operationComplete() {
+        public void operationComplete(int unusedResult) {
             // The agent reported back to us!
 
             if (mBackupData == null) {
@@ -3128,8 +3131,23 @@
 
     // Core logic for performing one package's full backup, gathering the tarball from the
     // application and emitting it to the designated OutputStream.
+
+    // Callout from the engine to an interested participant that might need to communicate
+    // with the agent prior to asking it to move data
+    interface FullBackupPreflight {
+        /**
+         * Perform the preflight operation necessary for the given package.
+         * @param pkg The name of the package being proposed for full-data backup
+         * @param agent Live BackupAgent binding to the target app's agent
+         * @return BackupTransport.TRANSPORT_OK to proceed with the backup operation,
+         *         or one of the other BackupTransport.* error codes as appropriate
+         */
+        int preflightFullBackup(PackageInfo pkg, IBackupAgent agent);
+    };
+
     class FullBackupEngine {
         OutputStream mOutput;
+        FullBackupPreflight mPreflightHook;
         IFullBackupRestoreObserver mObserver;
         File mFilesDir;
         File mManifestFile;
@@ -3160,8 +3178,7 @@
             @Override
             public void run() {
                 try {
-                    BackupDataOutput output = new BackupDataOutput(
-                            mPipe.getFileDescriptor());
+                    FullBackupDataOutput output = new FullBackupDataOutput(mPipe);
 
                     if (mWriteManifest) {
                         final boolean writeWidgetData = mWidgetData != null;
@@ -3204,15 +3221,16 @@
             }
         }
 
-        FullBackupEngine(OutputStream output, String packageName, boolean alsoApks) {
+        FullBackupEngine(OutputStream output, String packageName, FullBackupPreflight preflightHook,
+                boolean alsoApks) {
             mOutput = output;
+            mPreflightHook = preflightHook;
             mIncludeApks = alsoApks;
             mFilesDir = new File("/data/system");
             mManifestFile = new File(mFilesDir, BACKUP_MANIFEST_FILENAME);
             mMetadataFile = new File(mFilesDir, BACKUP_METADATA_FILENAME);
         }
 
-
         public int backupOnePackage(PackageInfo pkg) throws RemoteException {
             int result = BackupTransport.TRANSPORT_OK;
             Slog.d(TAG, "Binding to full backup agent : " + pkg.packageName);
@@ -3222,42 +3240,52 @@
             if (agent != null) {
                 ParcelFileDescriptor[] pipes = null;
                 try {
-                    pipes = ParcelFileDescriptor.createPipe();
+                    // Call the preflight hook, if any
+                    if (mPreflightHook != null) {
+                        result = mPreflightHook.preflightFullBackup(pkg, agent);
+                        if (MORE_DEBUG) {
+                            Slog.v(TAG, "preflight returned " + result);
+                        }
+                    }
 
-                    ApplicationInfo app = pkg.applicationInfo;
-                    final boolean isSharedStorage = pkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
-                    final boolean sendApk = mIncludeApks
-                            && !isSharedStorage
-                            && ((app.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) == 0)
-                            && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
+                    // If we're still good to go after preflighting, start moving data
+                    if (result == BackupTransport.TRANSPORT_OK) {
+                        pipes = ParcelFileDescriptor.createPipe();
+
+                        ApplicationInfo app = pkg.applicationInfo;
+                        final boolean isSharedStorage = pkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
+                        final boolean sendApk = mIncludeApks
+                                && !isSharedStorage
+                                && ((app.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) == 0)
+                                && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
                                 (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
 
-                    byte[] widgetBlob = AppWidgetBackupBridge.getWidgetState(pkg.packageName,
-                            UserHandle.USER_OWNER);
+                        byte[] widgetBlob = AppWidgetBackupBridge.getWidgetState(pkg.packageName,
+                                UserHandle.USER_OWNER);
 
-                    final int token = generateToken();
-                    FullBackupRunner runner = new FullBackupRunner(pkg, agent, pipes[1],
-                            token, sendApk, !isSharedStorage, widgetBlob);
-                    pipes[1].close();   // the runner has dup'd it
-                    pipes[1] = null;
-                    Thread t = new Thread(runner, "app-data-runner");
-                    t.start();
+                        final int token = generateToken();
+                        FullBackupRunner runner = new FullBackupRunner(pkg, agent, pipes[1],
+                                token, sendApk, !isSharedStorage, widgetBlob);
+                        pipes[1].close();   // the runner has dup'd it
+                        pipes[1] = null;
+                        Thread t = new Thread(runner, "app-data-runner");
+                        t.start();
 
-                    // Now pull data from the app and stuff it into the output
-                    try {
-                        routeSocketDataToOutput(pipes[0], mOutput);
-                    } catch (IOException e) {
-                        Slog.i(TAG, "Caught exception reading from agent", e);
-                        result = BackupTransport.AGENT_ERROR;
+                        // Now pull data from the app and stuff it into the output
+                        try {
+                            routeSocketDataToOutput(pipes[0], mOutput);
+                        } catch (IOException e) {
+                            Slog.i(TAG, "Caught exception reading from agent", e);
+                            result = BackupTransport.AGENT_ERROR;
+                        }
+
+                        if (!waitUntilOperationComplete(token)) {
+                            Slog.e(TAG, "Full backup failed on package " + pkg.packageName);
+                            result = BackupTransport.AGENT_ERROR;
+                        } else {
+                            if (DEBUG) Slog.d(TAG, "Full package backup success: " + pkg.packageName);
+                        }
                     }
-
-                    if (!waitUntilOperationComplete(token)) {
-                        Slog.e(TAG, "Full backup failed on package " + pkg.packageName);
-                        result = BackupTransport.AGENT_ERROR;
-                    } else {
-                        if (DEBUG) Slog.d(TAG, "Full package backup success: " + pkg.packageName);
-                    }
-
                 } catch (IOException e) {
                     Slog.e(TAG, "Error backing up " + pkg.packageName, e);
                     result = BackupTransport.AGENT_ERROR;
@@ -3282,7 +3310,7 @@
             return result;
         }
 
-        private void writeApkToBackup(PackageInfo pkg, BackupDataOutput output) {
+        private void writeApkToBackup(PackageInfo pkg, FullBackupDataOutput output) {
             // Forward-locked apps, system-bundled .apks, etc are filtered out before we get here
             // TODO: handle backing up split APKs
             final String appSourceDir = pkg.applicationInfo.getBaseCodePath();
@@ -3781,7 +3809,7 @@
                     final boolean isSharedStorage =
                             pkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
 
-                    mBackupEngine = new FullBackupEngine(out, pkg.packageName, mIncludeApks);
+                    mBackupEngine = new FullBackupEngine(out, pkg.packageName, null, mIncludeApks);
                     sendOnBackupPackage(isSharedStorage ? "Shared storage" : pkg.packageName);
                     mBackupEngine.backupOnePackage(pkg);
 
@@ -3828,13 +3856,13 @@
         static final String TAG = "PFTBT";
         ArrayList<PackageInfo> mPackages;
         boolean mUpdateSchedule;
-        AtomicBoolean mLatch;
+        CountDownLatch mLatch;
         AtomicBoolean mKeepRunning;     // signal from job scheduler
         FullBackupJob mJob;             // if a scheduled job needs to be finished afterwards
 
         PerformFullTransportBackupTask(IFullBackupRestoreObserver observer, 
                 String[] whichPackages, boolean updateSchedule,
-                FullBackupJob runningJob, AtomicBoolean latch) {
+                FullBackupJob runningJob, CountDownLatch latch) {
             super(observer);
             mUpdateSchedule = updateSchedule;
             mLatch = latch;
@@ -3892,6 +3920,7 @@
             ParcelFileDescriptor[] transportPipes = null;
 
             PackageInfo currentPackage;
+            long backoff = 0;
 
             try {
                 if (!mEnabled || !mProvisioned) {
@@ -3910,16 +3939,6 @@
                     return;
                 }
 
-                // Don't proceed unless we have already established package metadata
-                // for the current dataset via a key/value backup pass.
-                File stateDir = new File(mBaseStateDir, transport.transportDirName());
-                File pmState = new File(stateDir, PACKAGE_MANAGER_SENTINEL);
-                if (pmState.length() <= 0) {
-                    Slog.i(TAG, "Full backup requested but dataset not yet initialized "
-                            + "via k/v backup pass; ignoring");
-                    return;
-                }
-
                 // Set up to send data to the transport
                 final int N = mPackages.size();
                 for (int i = 0; i < N; i++) {
@@ -3944,10 +3963,10 @@
 
                         // Now set up the backup engine / data source end of things
                         enginePipes = ParcelFileDescriptor.createPipe();
-                        AtomicBoolean runnerLatch = new AtomicBoolean(false);
+                        CountDownLatch runnerLatch = new CountDownLatch(1);
                         SinglePackageBackupRunner backupRunner =
                                 new SinglePackageBackupRunner(enginePipes[1], currentPackage,
-                                        runnerLatch);
+                                        transport, runnerLatch);
                         // The runner dup'd the pipe half, so we close it here
                         enginePipes[1].close();
                         enginePipes[1] = null;
@@ -3972,6 +3991,9 @@
                                 break;
                             }
                             nRead = in.read(buffer);
+                            if (MORE_DEBUG) {
+                                Slog.v(TAG, "in.read(buffer) from app: " + nRead);
+                            }
                             if (nRead > 0) {
                                 out.write(buffer, 0, nRead);
                                 result = transport.sendBackupData(nRead);
@@ -4003,6 +4025,14 @@
                             Slog.e(TAG, "Error " + result
                                     + " backing up " + currentPackage.packageName);
                         }
+
+                        // Also ask the transport how long it wants us to wait before
+                        // moving on to the next package, if any.
+                        backoff = transport.requestFullBackupTime();
+                        if (DEBUG_SCHEDULING) {
+                            Slog.i(TAG, "Transport suggested backoff=" + backoff);
+                        }
+
                     }
 
                     // Roll this package to the end of the backup queue if we're
@@ -4055,15 +4085,12 @@
                     mRunningFullBackupTask = null;
                 }
 
-                synchronized (mLatch) {
-                    mLatch.set(true);
-                    mLatch.notifyAll();
-                }
+                mLatch.countDown();
 
                 // Now that we're actually done with schedule-driven work, reschedule
                 // the next pass based on the new queue state.
                 if (mUpdateSchedule) {
-                    scheduleNextFullBackupJob();
+                    scheduleNextFullBackupJob(backoff);
                 }
             }
         }
@@ -4094,15 +4121,79 @@
         // Run the backup and pipe it back to the given socket -- expects to run on
         // a standalone thread.  The  runner owns this half of the pipe, and closes
         // it to indicate EOD to the other end.
+        class SinglePackageBackupPreflight implements BackupRestoreTask, FullBackupPreflight {
+            final AtomicInteger mResult = new AtomicInteger();
+            final CountDownLatch mLatch = new CountDownLatch(1);
+            final IBackupTransport mTransport;
+
+            public SinglePackageBackupPreflight(IBackupTransport transport) {
+                mTransport = transport;
+            }
+
+            @Override
+            public int preflightFullBackup(PackageInfo pkg, IBackupAgent agent) {
+                int result;
+                try {
+                    final int token = generateToken();
+                    prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL, this);
+                    addBackupTrace("preflighting");
+                    if (MORE_DEBUG) {
+                        Slog.d(TAG, "Preflighting full payload of " + pkg.packageName);
+                    }
+                    agent.doMeasureFullBackup(token, mBackupManagerBinder);
+
+                    // now wait to get our result back
+                    mLatch.await();
+                    int totalSize = mResult.get();
+                    if (MORE_DEBUG) {
+                        Slog.v(TAG, "Got preflight response; size=" + totalSize);
+                    }
+
+                    result = mTransport.checkFullBackupSize(totalSize);
+                } catch (Exception e) {
+                    Slog.w(TAG, "Exception preflighting " + pkg.packageName + ": " + e.getMessage());
+                    result = BackupTransport.AGENT_ERROR;
+                }
+                return result;
+            }
+
+            @Override
+            public void execute() {
+                // Unused in this case
+            }
+
+            @Override
+            public void operationComplete(int result) {
+                // got the callback, and our preflightFullBackup() method is waiting for the result
+                if (MORE_DEBUG) {
+                    Slog.i(TAG, "Preflight op complete, result=" + result);
+                }
+                mResult.set(result);
+                mLatch.countDown();
+            }
+
+            @Override
+            public void handleTimeout() {
+                if (MORE_DEBUG) {
+                    Slog.i(TAG, "Preflight timeout; failing");
+                }
+                mResult.set(BackupTransport.AGENT_ERROR);
+                mLatch.countDown();
+            }
+            
+        }
+
         class SinglePackageBackupRunner implements Runnable {
             final ParcelFileDescriptor mOutput;
             final PackageInfo mTarget;
-            final AtomicBoolean mLatch;
+            final FullBackupPreflight mPreflight;
+            final CountDownLatch mLatch;
 
             SinglePackageBackupRunner(ParcelFileDescriptor output, PackageInfo target,
-                    AtomicBoolean latch) throws IOException {
+                    IBackupTransport transport, CountDownLatch latch) throws IOException {
                 mOutput = ParcelFileDescriptor.dup(output.getFileDescriptor());
                 mTarget = target;
+                mPreflight = new SinglePackageBackupPreflight(transport);
                 mLatch = latch;
             }
 
@@ -4110,15 +4201,13 @@
             public void run() {
                 try {
                     FileOutputStream out = new FileOutputStream(mOutput.getFileDescriptor());
-                    FullBackupEngine engine = new FullBackupEngine(out, mTarget.packageName, false);
+                    FullBackupEngine engine = new FullBackupEngine(out, mTarget.packageName,
+                            mPreflight, false);
                     engine.backupOnePackage(mTarget);
                 } catch (Exception e) {
                     Slog.e(TAG, "Exception during full package backup of " + mTarget);
                 } finally {
-                    synchronized (mLatch) {
-                        mLatch.set(true);
-                        mLatch.notifyAll();
-                    }
+                    mLatch.countDown();
                     try {
                         mOutput.close();
                     } catch (IOException e) {
@@ -4126,7 +4215,6 @@
                     }
                 }
             }
-            
         }
     }
 
@@ -4135,16 +4223,17 @@
     /**
      * Schedule a job to tell us when it's a good time to run a full backup
      */
-    void scheduleNextFullBackupJob() {
+    void scheduleNextFullBackupJob(long transportMinLatency) {
         synchronized (mQueueLock) {
             if (mFullBackupQueue.size() > 0) {
                 // schedule the next job at the point in the future when the least-recently
                 // backed up app comes due for backup again; or immediately if it's already
                 // due.
-                long upcomingLastBackup = mFullBackupQueue.get(0).lastBackup;
-                long timeSinceLast = System.currentTimeMillis() - upcomingLastBackup;
-                final long latency = (timeSinceLast < MIN_FULL_BACKUP_INTERVAL)
+                final long upcomingLastBackup = mFullBackupQueue.get(0).lastBackup;
+                final long timeSinceLast = System.currentTimeMillis() - upcomingLastBackup;
+                final long appLatency = (timeSinceLast < MIN_FULL_BACKUP_INTERVAL)
                         ? (MIN_FULL_BACKUP_INTERVAL - timeSinceLast) : 0;
+                final long latency = Math.min(transportMinLatency, appLatency);
                 Runnable r = new Runnable() {
                     @Override public void run() {
                         FullBackupJob.schedule(mContext, latency);
@@ -4198,6 +4287,31 @@
         writeFullBackupScheduleAsync();
     }
 
+    private boolean fullBackupAllowable(IBackupTransport transport) {
+        if (transport == null) {
+            Slog.w(TAG, "Transport not present; full data backup not performed");
+            return false;
+        }
+
+        // Don't proceed unless we have already established package metadata
+        // for the current dataset via a key/value backup pass.
+        try {
+            File stateDir = new File(mBaseStateDir, transport.transportDirName());
+            File pmState = new File(stateDir, PACKAGE_MANAGER_SENTINEL);
+            if (pmState.length() <= 0) {
+                if (DEBUG) {
+                    Slog.i(TAG, "Full backup requested but dataset not yet initialized");
+                }
+                return false;
+            }
+        } catch (Exception e) {
+            Slog.w(TAG, "Unable to contact transport");
+            return false;
+        }
+
+        return true;
+    }
+
     /**
      * Conditions are right for a full backup operation, so run one.  The model we use is
      * to perform one app backup per scheduled job execution, and to reschedule the job
@@ -4209,6 +4323,7 @@
     boolean beginFullBackup(FullBackupJob scheduledJob) {
         long now = System.currentTimeMillis();
         FullBackupEntry entry = null;
+        long latency = MIN_FULL_BACKUP_INTERVAL;
 
         if (!mEnabled || !mProvisioned) {
             // Backups are globally disabled, so don't proceed.  We also don't reschedule
@@ -4240,17 +4355,41 @@
                 return false;
             }
 
-            entry = mFullBackupQueue.get(0);
-            long timeSinceRun = now - entry.lastBackup;
-            if (timeSinceRun < MIN_FULL_BACKUP_INTERVAL) {
-                // It's too early to back up the next thing in the queue, so bow out
+            // At this point we know that we have work to do, just not right now.  Any
+            // exit without actually running backups will also require that we
+            // reschedule the job.
+            boolean runBackup = true;
+
+            if (!fullBackupAllowable(getTransport(mCurrentTransport))) {
                 if (MORE_DEBUG) {
-                    Slog.i(TAG, "Device ready but too early to back up next app");
+                    Slog.i(TAG, "Preconditions not met; not running full backup");
                 }
-                final long latency = MIN_FULL_BACKUP_INTERVAL - timeSinceRun;
+                runBackup = false;
+                // Typically this means we haven't run a key/value backup yet.  Back off
+                // full-backup operations by the key/value job's run interval so that
+                // next time we run, we are likely to be able to make progress.
+                latency = KeyValueBackupJob.BATCH_INTERVAL;
+            }
+
+            if (runBackup) {
+                entry = mFullBackupQueue.get(0);
+                long timeSinceRun = now - entry.lastBackup;
+                runBackup = (timeSinceRun >= MIN_FULL_BACKUP_INTERVAL);
+                if (!runBackup) {
+                    // It's too early to back up the next thing in the queue, so bow out
+                    if (MORE_DEBUG) {
+                        Slog.i(TAG, "Device ready but too early to back up next app");
+                    }
+                    // Wait until the next app in the queue falls due for a full data backup
+                    latency = MIN_FULL_BACKUP_INTERVAL - timeSinceRun;
+                }
+            }
+
+            if (!runBackup) {
+                final long deferTime = latency;     // pin for the closure
                 mBackupHandler.post(new Runnable() {
                     @Override public void run() {
-                        FullBackupJob.schedule(mContext, latency);
+                        FullBackupJob.schedule(mContext, deferTime);
                     }
                 });
                 return false;
@@ -4258,7 +4397,7 @@
 
             // Okay, the top thing is runnable now.  Pop it off and get going.
             mFullBackupQueue.remove(0);
-            AtomicBoolean latch = new AtomicBoolean(false);
+            CountDownLatch latch = new CountDownLatch(1);
             String[] pkg = new String[] {entry.packageName};
             mRunningFullBackupTask = new PerformFullTransportBackupTask(null, pkg, true,
                     scheduledJob, latch);
@@ -7895,7 +8034,7 @@
         }
 
         @Override
-        public void operationComplete() {
+        public void operationComplete(int unusedResult) {
             if (MORE_DEBUG) {
                 Slog.i(TAG, "operationComplete() during restore: target="
                         + mCurrentPackage.packageName
@@ -8391,21 +8530,33 @@
             throw new IllegalStateException("Restore supported only for the device owner");
         }
 
-        if (DEBUG) {
-            Slog.d(TAG, "fullTransportBackup()");
+        if (!fullBackupAllowable(getTransport(mCurrentTransport))) {
+            Slog.i(TAG, "Full backup not currently possible -- key/value backup not yet run?");
+        } else {
+            if (DEBUG) {
+                Slog.d(TAG, "fullTransportBackup()");
+            }
+
+            CountDownLatch latch = new CountDownLatch(1);
+            PerformFullTransportBackupTask task =
+                    new PerformFullTransportBackupTask(null, pkgNames, false, null, latch);
+            (new Thread(task, "full-transport-master")).start();
+            do {
+                try {
+                    latch.await();
+                    break;
+                } catch (InterruptedException e) {
+                    // Just go back to waiting for the latch to indicate completion
+                }
+            } while (true);
+
+            // We just ran a backup on these packages, so kick them to the end of the queue
+            final long now = System.currentTimeMillis();
+            for (String pkg : pkgNames) {
+                enqueueFullBackup(pkg, now);
+            }
         }
 
-        AtomicBoolean latch = new AtomicBoolean(false);
-        PerformFullTransportBackupTask task =
-                new PerformFullTransportBackupTask(null, pkgNames, false, null, latch);
-        (new Thread(task, "full-transport-master")).start();
-        synchronized (latch) {
-            try {
-                while (latch.get() == false) {
-                    latch.wait();
-                }
-            } catch (InterruptedException e) {}
-        }
         if (DEBUG) {
             Slog.d(TAG, "Done with full transport backup.");
         }
@@ -8575,7 +8726,7 @@
                 if (enable && !wasEnabled && mProvisioned) {
                     // if we've just been enabled, start scheduling backup passes
                     KeyValueBackupJob.schedule(mContext);
-                    scheduleNextFullBackupJob();
+                    scheduleNextFullBackupJob(0);
                 } else if (!enable) {
                     // No longer enabled, so stop running backups
                     if (DEBUG) Slog.i(TAG, "Opting out of backup");
@@ -8948,8 +9099,10 @@
 
     // Note that a currently-active backup agent has notified us that it has
     // completed the given outstanding asynchronous backup/restore operation.
-    public void opComplete(int token) {
-        if (MORE_DEBUG) Slog.v(TAG, "opComplete: " + Integer.toHexString(token));
+    public void opComplete(int token, long result) {
+        if (MORE_DEBUG) {
+            Slog.v(TAG, "opComplete: " + Integer.toHexString(token) + " result=" + result);
+        }
         Operation op = null;
         synchronized (mCurrentOpLock) {
             op = mCurrentOperations.get(token);
@@ -8962,6 +9115,8 @@
         // The completion callback, if any, is invoked on the handler
         if (op != null && op.callback != null) {
             Message msg = mBackupHandler.obtainMessage(MSG_OP_COMPLETE, op.callback);
+            // NB: this cannot distinguish between results > 2 gig
+            msg.arg1 = (result > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) result;
             mBackupHandler.sendMessage(msg);
         }
     }
diff --git a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
index dc1c9d5..a4489c1 100644
--- a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
+++ b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
@@ -41,7 +41,7 @@
     // Once someone asks for a backup, this is how long we hold off, batching
     // up additional requests, before running the actual backup pass.  Privileged
     // callers can always trigger an immediate pass via BackupManager.backupNow().
-    private static final long BATCH_INTERVAL = 4 * AlarmManager.INTERVAL_HOUR;
+    static final long BATCH_INTERVAL = 4 * AlarmManager.INTERVAL_HOUR;
 
     // Random variation in next-backup scheduling time to avoid server load spikes
     private static final int FUZZ_MILLIS = 10 * 60 * 1000;
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 2e84fbe..99bbdae 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -309,10 +309,10 @@
     }
 
     @Override
-    public void opComplete(int token) throws RemoteException {
+    public void opComplete(int token, long result) throws RemoteException {
         BackupManagerService svc = mService;
         if (svc != null) {
-            svc.opComplete(token);
+            svc.opComplete(token, result);
         }
     }
 
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 1a0fa34..64b6134 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -10,5 +10,6 @@
     java/com/android/server/am/EventLogTags.logtags
 
 LOCAL_JAVA_LIBRARIES := telephony-common
+LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
index e6dc1c7..f106667 100644
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ b/services/core/java/com/android/server/AssetAtlasService.java
@@ -403,13 +403,13 @@
         if (cpuCount == 1) {
             new ComputeWorker(MIN_SIZE, MAX_SIZE, STEP, bitmaps, pixelCount, results, null).run();
         } else {
-            int start = MIN_SIZE;
-            int end = MAX_SIZE - (cpuCount - 1) * STEP;
+            int start = MIN_SIZE + (cpuCount - 1) * STEP;
+            int end = MAX_SIZE;
             int step = STEP * cpuCount;
 
             final CountDownLatch signal = new CountDownLatch(cpuCount);
 
-            for (int i = 0; i < cpuCount; i++, start += STEP, end += STEP) {
+            for (int i = 0; i < cpuCount; i++, start -= STEP, end -= STEP) {
                 ComputeWorker worker = new ComputeWorker(start, end, step,
                         bitmaps, pixelCount, results, signal);
                 new Thread(worker, "Atlas Worker #" + (i + 1)).start();
@@ -435,7 +435,8 @@
 
         if (DEBUG_ATLAS) {
             float delay = (System.nanoTime() - begin) / 1000.0f / 1000.0f / 1000.0f;
-            Log.d(LOG_TAG, String.format("Found best atlas configuration in %.2fs", delay));
+            Log.d(LOG_TAG, String.format("Found best atlas configuration (out of %d) in %.2fs",
+                    results.size(), delay));
         }
 
         WorkerResult result = results.get(0);
@@ -696,8 +697,8 @@
 
             Atlas.Entry entry = new Atlas.Entry();
             for (Atlas.Type type : Atlas.Type.values()) {
-                for (int width = mStart; width < mEnd; width += mStep) {
-                    for (int height = MIN_SIZE; height < MAX_SIZE; height += STEP) {
+                for (int width = mEnd; width > mStart; width -= mStep) {
+                    for (int height = MAX_SIZE; height > MIN_SIZE; height -= STEP) {
                         // If the atlas is not big enough, skip it
                         if (width * height <= mThreshold) continue;
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 201c755..eb394c3 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2023,6 +2023,8 @@
                         ReapUnvalidatedNetworks.DONT_REAP);
             }
         }
+        NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
+        if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name);
     }
 
     // If this method proves to be too slow then we can maintain a separate
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 983d83a..694e851 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -221,3 +221,4 @@
 # AudioService.java
 # ---------------------------
 40000 volume_changed (stream|1), (prev_level|1), (level|1), (max_level|1), (caller|3)
+40001 stream_devices_changed (stream|1), (prev_devices|1), (devices|1)
diff --git a/services/core/java/com/android/server/GraphicsStatsService.java b/services/core/java/com/android/server/GraphicsStatsService.java
new file mode 100644
index 0000000..c79fdfc
--- /dev/null
+++ b/services/core/java/com/android/server/GraphicsStatsService.java
@@ -0,0 +1,256 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.MemoryFile;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.IGraphicsStats;
+import android.view.ThreadedRenderer;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * This service's job is to collect aggregate rendering profile data. It
+ * does this by allowing rendering processes to request an ashmem buffer
+ * to place their stats into. This buffer will be pre-initialized with historical
+ * data for that process if it exists (if the userId & packageName match a buffer
+ * in the historical log)
+ *
+ * This service does not itself attempt to understand the data in the buffer,
+ * its primary job is merely to manage distributing these buffers. However,
+ * it is assumed that this buffer is for ThreadedRenderer and delegates
+ * directly to ThreadedRenderer for dumping buffers.
+ *
+ * MEMORY USAGE:
+ *
+ * This class consumes UP TO:
+ * 1) [active rendering processes] * (ASHMEM_SIZE * 2)
+ * 2) ASHMEM_SIZE (for scratch space used during dumping)
+ * 3) ASHMEM_SIZE * HISTORY_SIZE
+ *
+ * Currently ASHMEM_SIZE is 256 bytes and HISTORY_SIZE is 10. Assuming
+ * the system then also has 10 active rendering processes in the worst case
+ * this would end up using under 10KiB (8KiB for the buffers, plus some overhead
+ * for userId, pid, package name, and a couple other objects)
+ *
+ *  @hide */
+public class GraphicsStatsService extends IGraphicsStats.Stub {
+    public static final String GRAPHICS_STATS_SERVICE = "graphicsstats";
+
+    private static final String TAG = "GraphicsStatsService";
+    private static final int ASHMEM_SIZE = 256;
+    private static final int HISTORY_SIZE = 10;
+
+    private final Context mContext;
+    private final Object mLock = new Object();
+    private ArrayList<ActiveBuffer> mActive = new ArrayList<>();
+    private HistoricalData[] mHistoricalLog = new HistoricalData[HISTORY_SIZE];
+    private int mNextHistoricalSlot = 0;
+    private byte[] mTempBuffer = new byte[ASHMEM_SIZE];
+
+    public GraphicsStatsService(Context context) {
+        mContext = context;
+    }
+
+    private boolean isValid(int uid, String packageName) {
+        try {
+            PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0);
+            return info.applicationInfo.uid == uid;
+        } catch (NameNotFoundException e) {
+        }
+        return false;
+    }
+
+    @Override
+    public ParcelFileDescriptor requestBufferForProcess(String packageName, IBinder token)
+            throws RemoteException {
+        int uid = Binder.getCallingUid();
+        int pid = Binder.getCallingPid();
+        ParcelFileDescriptor pfd = null;
+        long callingIdentity = Binder.clearCallingIdentity();
+        try {
+            if (!isValid(uid, packageName)) {
+                throw new RemoteException("Invalid package name");
+            }
+            synchronized (mLock) {
+                pfd = requestBufferForProcessLocked(token, uid, pid, packageName);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingIdentity);
+        }
+        return pfd;
+    }
+
+    private ParcelFileDescriptor getPfd(MemoryFile file) {
+        try {
+            return new ParcelFileDescriptor(file.getFileDescriptor());
+        } catch (IOException ex) {
+            throw new IllegalStateException("Failed to get PFD from memory file", ex);
+        }
+    }
+
+    private ParcelFileDescriptor requestBufferForProcessLocked(IBinder token,
+            int uid, int pid, String packageName) throws RemoteException {
+        ActiveBuffer buffer = fetchActiveBuffersLocked(token, uid, pid, packageName);
+        return getPfd(buffer.mProcessBuffer);
+    }
+
+    private void processDied(ActiveBuffer buffer) {
+        synchronized (mLock) {
+            mActive.remove(buffer);
+            Log.d("GraphicsStats", "Buffer count: " + mActive.size());
+        }
+        HistoricalData data = buffer.mPreviousData;
+        buffer.mPreviousData = null;
+        if (data == null) {
+            data = mHistoricalLog[mNextHistoricalSlot];
+            if (data == null) {
+                data = new HistoricalData();
+            }
+        }
+        data.update(buffer.mPackageName, buffer.mUid, buffer.mProcessBuffer);
+        buffer.closeAllBuffers();
+
+        mHistoricalLog[mNextHistoricalSlot] = data;
+        mNextHistoricalSlot = (mNextHistoricalSlot + 1) % mHistoricalLog.length;
+    }
+
+    private ActiveBuffer fetchActiveBuffersLocked(IBinder token, int uid, int pid,
+            String packageName) throws RemoteException {
+        int size = mActive.size();
+        for (int i = 0; i < size; i++) {
+            ActiveBuffer buffers = mActive.get(i);
+            if (buffers.mPid == pid
+                    && buffers.mUid == uid) {
+                return buffers;
+            }
+        }
+        // Didn't find one, need to create it
+        try {
+            ActiveBuffer buffers = new ActiveBuffer(token, uid, pid, packageName);
+            mActive.add(buffers);
+            return buffers;
+        } catch (IOException ex) {
+            throw new RemoteException("Failed to allocate space");
+        }
+    }
+
+    private HistoricalData removeHistoricalDataLocked(int uid, String packageName) {
+        for (int i = 0; i < mHistoricalLog.length; i++) {
+            final HistoricalData data = mHistoricalLog[i];
+            if (data != null && data.mUid == uid
+                    && data.mPackageName.equals(packageName)) {
+                if (i == mNextHistoricalSlot) {
+                    mHistoricalLog[i] = null;
+                } else {
+                    mHistoricalLog[i] = mHistoricalLog[mNextHistoricalSlot];
+                    mHistoricalLog[mNextHistoricalSlot] = null;
+                }
+                return data;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+        synchronized (mLock) {
+            for (int i = 0; i < mActive.size(); i++) {
+                final ActiveBuffer buffer = mActive.get(i);
+                fout.print("Package: ");
+                fout.print(buffer.mPackageName);
+                fout.flush();
+                try {
+                    buffer.mProcessBuffer.readBytes(mTempBuffer, 0, 0, ASHMEM_SIZE);
+                    ThreadedRenderer.dumpProfileData(mTempBuffer, fd);
+                } catch (IOException e) {
+                    fout.println("Failed to dump");
+                }
+                fout.println();
+            }
+            for (HistoricalData buffer : mHistoricalLog) {
+                if (buffer == null) continue;
+                fout.print("Package: ");
+                fout.print(buffer.mPackageName);
+                fout.flush();
+                ThreadedRenderer.dumpProfileData(buffer.mBuffer, fd);
+                fout.println();
+            }
+        }
+    }
+
+    private final class ActiveBuffer implements DeathRecipient {
+        final int mUid;
+        final int mPid;
+        final String mPackageName;
+        final IBinder mToken;
+        MemoryFile mProcessBuffer;
+        HistoricalData mPreviousData;
+
+        ActiveBuffer(IBinder token, int uid, int pid, String packageName)
+                throws RemoteException, IOException {
+            mUid = uid;
+            mPid = pid;
+            mPackageName = packageName;
+            mToken = token;
+            mToken.linkToDeath(this, 0);
+            mProcessBuffer = new MemoryFile("GFXStats-" + uid, ASHMEM_SIZE);
+            mPreviousData = removeHistoricalDataLocked(mUid, mPackageName);
+            if (mPreviousData != null) {
+                mProcessBuffer.writeBytes(mPreviousData.mBuffer, 0, 0, ASHMEM_SIZE);
+            }
+        }
+
+        @Override
+        public void binderDied() {
+            mToken.unlinkToDeath(this, 0);
+            processDied(this);
+        }
+
+        void closeAllBuffers() {
+            if (mProcessBuffer != null) {
+                mProcessBuffer.close();
+                mProcessBuffer = null;
+            }
+        }
+    }
+
+    private final static class HistoricalData {
+        final byte[] mBuffer = new byte[ASHMEM_SIZE];
+        int mUid;
+        String mPackageName;
+
+        void update(String packageName, int uid, MemoryFile file) {
+            mUid = uid;
+            mPackageName = packageName;
+            try {
+                file.readBytes(mBuffer, 0, 0, ASHMEM_SIZE);
+            } catch (IOException e) {}
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index cea1ebe..744156b 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -47,6 +47,7 @@
     final private static String TAG = "IntentResolver";
     final private static boolean DEBUG = false;
     final private static boolean localLOGV = DEBUG || false;
+    final private static boolean localVerificationLOGV = DEBUG || false;
 
     public void addFilter(F f) {
         if (localLOGV) {
@@ -478,7 +479,7 @@
 
     /**
      * Returns whether the object associated with the given filter is
-     * "stopped," that is whether it should not be included in the result
+     * "stopped", that is whether it should not be included in the result
      * if the intent requests to excluded stopped objects.
      */
     protected boolean isFilterStopped(F filter, int userId) {
@@ -486,6 +487,22 @@
     }
 
     /**
+     * Returns whether the given filter is "verified" that is whether it has been verified against
+     * its data URIs.
+     *
+     * The verification would happen only and only if the Intent action is
+     * {@link android.content.Intent#ACTION_VIEW} and the Intent category is
+     * {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent data scheme
+     * is "http" or "https".
+     *
+     * @see android.content.IntentFilter#setAutoVerify(boolean)
+     * @see android.content.IntentFilter#getAutoVerify()
+     */
+    protected boolean isFilterVerified(F filter) {
+        return filter.isVerified();
+    }
+
+    /**
      * Returns whether this filter is owned by this package. This must be
      * implemented to provide correct filtering of Intents that have
      * specified a package name they are to be delivered to.
@@ -710,6 +727,13 @@
                 continue;
             }
 
+            // Are we verified ?
+            if (filter.getAutoVerify()) {
+                if (localVerificationLOGV || debug) {
+                    Slog.v(TAG, "  Filter verified: " + isFilterVerified(filter));
+                }
+            }
+
             // Do we already have this one?
             if (!allowFilterResult(filter, dest)) {
                 if (debug) {
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index 0de6a03..9409615 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -36,6 +36,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.service.carrier.CarrierMessagingService;
+import android.telephony.SmsManager;
 import android.telephony.TelephonyManager;
 import android.util.Slog;
 
@@ -111,6 +112,106 @@
         }
     };
 
+    // Instance of IMms for returning failure to service API caller,
+    // used when MmsService cannot be connected.
+    private final IMms mServiceStubForFailure = new IMms() {
+
+        @Override
+        public IBinder asBinder() {
+            return null;
+        }
+
+        @Override
+        public void sendMessage(int subId, String callingPkg, Uri contentUri, String locationUrl,
+                Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
+            returnPendingIntentWithError(sentIntent);
+        }
+
+        @Override
+        public void downloadMessage(int subId, String callingPkg, String locationUrl,
+                Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)
+                throws RemoteException {
+            returnPendingIntentWithError(downloadedIntent);
+        }
+
+        @Override
+        public Bundle getCarrierConfigValues(int subId) throws RemoteException {
+            return null;
+        }
+
+        @Override
+        public Uri importTextMessage(String callingPkg, String address, int type, String text,
+                long timestampMillis, boolean seen, boolean read) throws RemoteException {
+            return null;
+        }
+
+        @Override
+        public Uri importMultimediaMessage(String callingPkg, Uri contentUri, String messageId,
+                long timestampSecs, boolean seen, boolean read) throws RemoteException {
+            return null;
+        }
+
+        @Override
+        public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
+                throws RemoteException {
+            return false;
+        }
+
+        @Override
+        public boolean deleteStoredConversation(String callingPkg, long conversationId)
+                throws RemoteException {
+            return false;
+        }
+
+        @Override
+        public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
+                ContentValues statusValues) throws RemoteException {
+            return false;
+        }
+
+        @Override
+        public boolean archiveStoredConversation(String callingPkg, long conversationId,
+                boolean archived) throws RemoteException {
+            return false;
+        }
+
+        @Override
+        public Uri addTextMessageDraft(String callingPkg, String address, String text)
+                throws RemoteException {
+            return null;
+        }
+
+        @Override
+        public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
+                throws RemoteException {
+            return null;
+        }
+
+        @Override
+        public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
+                Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
+            returnPendingIntentWithError(sentIntent);
+        }
+
+        @Override
+        public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
+            // Do nothing
+        }
+
+        @Override
+        public boolean getAutoPersisting() throws RemoteException {
+            return false;
+        }
+
+        private void returnPendingIntentWithError(PendingIntent pendingIntent) {
+            try {
+                pendingIntent.send(mContext, SmsManager.MMS_ERROR_UNSPECIFIED, null);
+            } catch (PendingIntent.CanceledException e) {
+                Slog.e(TAG, "Failed to return pending intent result", e);
+            }
+        }
+    };
+
     public MmsServiceBroker(Context context) {
         super(context);
         mContext = context;
@@ -145,44 +246,51 @@
         }
     }
 
-    private void ensureService() {
+    private IMms getOrConnectService() {
         synchronized (this) {
-            if (mService == null) {
-                // Service is not connected. Try blocking connecting.
-                Slog.w(TAG, "MmsService not connected. Try connecting...");
-                mConnectionHandler.sendMessage(
-                        mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING));
-                final long shouldEnd =
-                        SystemClock.elapsedRealtime() + SERVICE_CONNECTION_WAIT_TIME_MS;
-                long waitTime = SERVICE_CONNECTION_WAIT_TIME_MS;
-                while (waitTime > 0) {
-                    try {
-                        // TODO: consider using Java concurrent construct instead of raw object wait
-                        this.wait(waitTime);
-                    } catch (InterruptedException e) {
-                        Slog.w(TAG, "Connection wait interrupted", e);
-                    }
-                    if (mService != null) {
-                        // Success
-                        return;
-                    }
-                    // Calculate remaining waiting time to make sure we wait the full timeout period
-                    waitTime = shouldEnd - SystemClock.elapsedRealtime();
-                }
-                // Timed out. Something's really wrong.
-                Slog.e(TAG, "Can not connect to MmsService (timed out)");
-                throw new RuntimeException("Timed out in connecting to MmsService");
+            if (mService != null) {
+                return mService;
             }
+            // Service is not connected. Try blocking connecting.
+            Slog.w(TAG, "MmsService not connected. Try connecting...");
+            mConnectionHandler.sendMessage(
+                    mConnectionHandler.obtainMessage(MSG_TRY_CONNECTING));
+            final long shouldEnd =
+                    SystemClock.elapsedRealtime() + SERVICE_CONNECTION_WAIT_TIME_MS;
+            long waitTime = SERVICE_CONNECTION_WAIT_TIME_MS;
+            while (waitTime > 0) {
+                try {
+                    // TODO: consider using Java concurrent construct instead of raw object wait
+                    this.wait(waitTime);
+                } catch (InterruptedException e) {
+                    Slog.w(TAG, "Connection wait interrupted", e);
+                }
+                if (mService != null) {
+                    // Success
+                    return mService;
+                }
+                // Calculate remaining waiting time to make sure we wait the full timeout period
+                waitTime = shouldEnd - SystemClock.elapsedRealtime();
+            }
+            // Timed out. Something's really wrong.
+            Slog.e(TAG, "Can not connect to MmsService (timed out)");
+            return null;
         }
     }
 
     /**
-     * Making sure when we obtain the mService instance it is always valid.
-     * Throws {@link RuntimeException} when it is empty.
+     * Make sure to return a non-empty service instance. Return the connected MmsService
+     * instance, if not connected, try connecting. If fail to connect, return a fake service
+     * instance which returns failure to service caller.
+     *
+     * @return a non-empty service instance, real or fake
      */
     private IMms getServiceGuarded() {
-        ensureService();
-        return mService;
+        final IMms service = getOrConnectService();
+        if (service != null) {
+            return service;
+        }
+        return mServiceStubForFailure;
     }
 
     private AppOpsManager getAppOpsManager() {
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index b8d9ec5..a341c95 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -16,40 +16,34 @@
 
 package com.android.server;
 
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
 import android.Manifest;
 import android.app.ActivityManagerNative;
 import android.app.AppOpsManager;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.content.res.ObbInfo;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.hardware.usb.UsbManager;
+import android.mtp.MtpStorage;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
+import android.os.FileUtils;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteCallbackList;
 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.os.storage.DiskInfo;
 import android.os.storage.IMountService;
 import android.os.storage.IMountServiceListener;
 import android.os.storage.IMountShutdownObserver;
@@ -58,27 +52,25 @@
 import android.os.storage.StorageManager;
 import android.os.storage.StorageResultCode;
 import android.os.storage.StorageVolume;
+import android.os.storage.VolumeInfo;
 import android.text.TextUtils;
-import android.util.AttributeSet;
+import android.util.ArrayMap;
+import android.util.Log;
 import android.util.Slog;
-import android.util.Xml;
+
+import libcore.util.EmptyArray;
+import libcore.util.HexEncoding;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IMediaContainerService;
+import com.android.internal.os.SomeArgs;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
-import com.android.internal.util.XmlUtils;
 import com.android.server.NativeDaemonConnector.Command;
 import com.android.server.NativeDaemonConnector.SensitiveArg;
-import com.android.server.am.ActivityManagerService;
 import com.android.server.pm.PackageManagerService;
-import com.android.server.pm.UserManagerService;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-import libcore.util.HexEncoding;
-
-import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -101,7 +93,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -110,19 +102,18 @@
 import javax.crypto.spec.PBEKeySpec;
 
 /**
- * MountService implements back-end services for platform storage
- * management.
- * @hide - Applications should use android.os.storage.StorageManager
- * to access the MountService.
+ * Service responsible for various storage media. Connects to {@code vold} to
+ * watch for and manage dynamically added storage, such as SD cards and USB mass
+ * storage. Also decides how storage should be presented to users on the device.
  */
 class MountService extends IMountService.Stub
         implements INativeDaemonConnectorCallbacks, Watchdog.Monitor {
 
+    // TODO: finish enforcing UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA
+
     // Static direct instance pointer for the tightly-coupled idle service to use
     static MountService sSelf = null;
 
-    // TODO: listen for user creation/deletion
-
     public static class Lifecycle extends SystemService {
         private MountService mMountService;
 
@@ -142,10 +133,19 @@
                 mMountService.systemReady();
             }
         }
+
+        @Override
+        public void onStartUser(int userHandle) {
+            mMountService.onStartUser(userHandle);
+        }
+
+        @Override
+        public void onCleanupUser(int userHandle) {
+            mMountService.onCleanupUser(userHandle);
+        }
     }
 
     private static final boolean LOCAL_LOGD = false;
-    private static final boolean DEBUG_UNMOUNT = false;
     private static final boolean DEBUG_EVENTS = false;
     private static final boolean DEBUG_OBB = false;
 
@@ -160,22 +160,6 @@
     private static final int MAX_CONTAINERS = 250;
 
     /*
-     * Internal vold volume state constants
-     */
-    class VolumeState {
-        public static final int Init       = -1;
-        public static final int NoMedia    = 0;
-        public static final int Idle       = 1;
-        public static final int Pending    = 2;
-        public static final int Checking   = 3;
-        public static final int Mounted    = 4;
-        public static final int Unmounting = 5;
-        public static final int Formatting = 6;
-        public static final int Shared     = 7;
-        public static final int SharedMnt  = 8;
-    }
-
-    /*
      * Internal vold response code constants
      */
     class VoldResponseCode {
@@ -209,12 +193,19 @@
         /*
          * 600 series - Unsolicited broadcasts.
          */
-        public static final int VolumeStateChange              = 605;
-        public static final int VolumeUuidChange               = 613;
-        public static final int VolumeUserLabelChange          = 614;
-        public static final int VolumeDiskInserted             = 630;
-        public static final int VolumeDiskRemoved              = 631;
-        public static final int VolumeBadRemoval               = 632;
+        public static final int DISK_CREATED = 640;
+        public static final int DISK_SIZE_CHANGED = 641;
+        public static final int DISK_LABEL_CHANGED = 642;
+        public static final int DISK_VOLUME_CREATED = 643;
+        public static final int DISK_DESTROYED = 649;
+
+        public static final int VOLUME_CREATED = 650;
+        public static final int VOLUME_STATE_CHANGED = 651;
+        public static final int VOLUME_FS_TYPE_CHANGED = 652;
+        public static final int VOLUME_FS_UUID_CHANGED = 653;
+        public static final int VOLUME_FS_LABEL_CHANGED = 654;
+        public static final int VOLUME_PATH_CHANGED = 655;
+        public static final int VOLUME_DESTROYED = 659;
 
         /*
          * 700 series - fstrim
@@ -222,6 +213,62 @@
         public static final int FstrimCompleted                = 700;
     }
 
+    /**
+     * <em>Never</em> hold the lock while performing downcalls into vold, since
+     * unsolicited events can suddenly appear to update data structures.
+     */
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private int[] mStartedUsers = EmptyArray.INT;
+    @GuardedBy("mLock")
+    private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
+    @GuardedBy("mLock")
+    private ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
+
+    private DiskInfo findDiskById(String id) {
+        synchronized (mLock) {
+            final DiskInfo disk = mDisks.get(id);
+            if (disk != null) {
+                return disk;
+            }
+        }
+        throw new IllegalArgumentException("No disk found for ID " + id);
+    }
+
+    private VolumeInfo findVolumeById(String id) {
+        synchronized (mLock) {
+            final VolumeInfo vol = mVolumes.get(id);
+            if (vol != null) {
+                return vol;
+            }
+        }
+        throw new IllegalArgumentException("No volume found for ID " + id);
+    }
+
+    @Deprecated
+    private String findVolumeIdForPath(String path) {
+        synchronized (mLock) {
+            for (int i = 0; i < mVolumes.size(); i++) {
+                final VolumeInfo vol = mVolumes.valueAt(i);
+                if (vol.path != null && path.startsWith(vol.path)) {
+                    return vol.id;
+                }
+            }
+        }
+        throw new IllegalArgumentException("No volume found for path " + path);
+    }
+
+    private static int sNextMtpIndex = 1;
+
+    private static int allocateMtpIndex(String volId) {
+        if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volId)) {
+            return 0;
+        } else {
+            return sNextMtpIndex++;
+        }
+    }
+
     /** List of crypto types.
       * These must match CRYPT_TYPE_XXX in cryptfs.h AND their
       * corresponding commands in CommandListener.cpp */
@@ -231,33 +278,19 @@
     private final Context mContext;
     private final NativeDaemonConnector mConnector;
 
-    private final Object mVolumesLock = new Object();
-
-    /** When defined, base template for user-specific {@link StorageVolume}. */
-    private StorageVolume mEmulatedTemplate;
-
-    // TODO: separate storage volumes on per-user basis
-
-    @GuardedBy("mVolumesLock")
-    private final ArrayList<StorageVolume> mVolumes = Lists.newArrayList();
-    /** Map from path to {@link StorageVolume} */
-    @GuardedBy("mVolumesLock")
-    private final HashMap<String, StorageVolume> mVolumesByPath = Maps.newHashMap();
-    /** Map from path to state */
-    @GuardedBy("mVolumesLock")
-    private final HashMap<String, String> mVolumeStates = Maps.newHashMap();
-
     private volatile boolean mSystemReady = false;
+    private volatile boolean mDaemonConnected = false;
 
-    private PackageManagerService                 mPms;
-    private boolean                               mUmsEnabling;
-    private boolean                               mUmsAvailable = false;
-    // Used as a lock for methods that register/unregister listeners.
-    final private ArrayList<MountServiceBinderListener> mListeners =
-            new ArrayList<MountServiceBinderListener>();
+    private PackageManagerService mPms;
+
+    private final Callbacks mCallbacks;
+
     private final CountDownLatch mConnectedSignal = new CountDownLatch(1);
     private final CountDownLatch mAsecsScanned = new CountDownLatch(1);
-    private boolean                               mSendUmsConnectedOnBoot = false;
+
+    private final Object mUnmountLock = new Object();
+    @GuardedBy("mUnmountLock")
+    private CountDownLatch mUnmountSignal;
 
     /**
      * Private hash of currently mounted secure containers.
@@ -366,6 +399,7 @@
     final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection();
 
     class DefaultContainerConnection implements ServiceConnection {
+        @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (DEBUG_OBB)
                 Slog.i(TAG, "onServiceConnected");
@@ -373,6 +407,7 @@
             mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs));
         }
 
+        @Override
         public void onServiceDisconnected(ComponentName name) {
             if (DEBUG_OBB)
                 Slog.i(TAG, "onServiceDisconnected");
@@ -388,177 +423,27 @@
     private long mLastMaintenance;
 
     // Handler messages
-    private static final int H_UNMOUNT_PM_UPDATE = 1;
-    private static final int H_UNMOUNT_PM_DONE = 2;
-    private static final int H_UNMOUNT_MS = 3;
-    private static final int H_SYSTEM_READY = 4;
-    private static final int H_FSTRIM = 5;
-
-    private static final int RETRY_UNMOUNT_DELAY = 30; // in ms
-    private static final int MAX_UNMOUNT_RETRIES = 4;
-
-    class UnmountCallBack {
-        final String path;
-        final boolean force;
-        final boolean removeEncryption;
-        int retries;
-
-        UnmountCallBack(String path, boolean force, boolean removeEncryption) {
-            retries = 0;
-            this.path = path;
-            this.force = force;
-            this.removeEncryption = removeEncryption;
-        }
-
-        void handleFinished() {
-            if (DEBUG_UNMOUNT) Slog.i(TAG, "Unmounting " + path);
-            doUnmountVolume(path, true, removeEncryption);
-        }
-    }
-
-    class UmsEnableCallBack extends UnmountCallBack {
-        final String method;
-
-        UmsEnableCallBack(String path, String method, boolean force) {
-            super(path, force, false);
-            this.method = method;
-        }
-
-        @Override
-        void handleFinished() {
-            super.handleFinished();
-            doShareUnshareVolume(path, method, true);
-        }
-    }
-
-    class ShutdownCallBack extends UnmountCallBack {
-        MountShutdownLatch mMountShutdownLatch;
-        ShutdownCallBack(String path, final MountShutdownLatch mountShutdownLatch) {
-            super(path, true, false);
-            mMountShutdownLatch = mountShutdownLatch;
-        }
-
-        @Override
-        void handleFinished() {
-            int ret = doUnmountVolume(path, true, removeEncryption);
-            Slog.i(TAG, "Unmount completed: " + path + ", result code: " + ret);
-            mMountShutdownLatch.countDown();
-        }
-    }
-
-    static class MountShutdownLatch {
-        private IMountShutdownObserver mObserver;
-        private AtomicInteger mCount;
-
-        MountShutdownLatch(final IMountShutdownObserver observer, int count) {
-            mObserver = observer;
-            mCount = new AtomicInteger(count);
-        }
-
-        void countDown() {
-            boolean sendShutdown = false;
-            if (mCount.decrementAndGet() == 0) {
-                sendShutdown = true;
-            }
-            if (sendShutdown && mObserver != null) {
-                try {
-                    mObserver.onShutDownComplete(StorageResultCode.OperationSucceeded);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "RemoteException when shutting down");
-                }
-            }
-        }
-    }
+    private static final int H_SYSTEM_READY = 1;
+    private static final int H_DAEMON_CONNECTED = 2;
+    private static final int H_SHUTDOWN = 3;
+    private static final int H_FSTRIM = 4;
+    private static final int H_VOLUME_MOUNT = 5;
+    private static final int H_VOLUME_BROADCAST = 6;
 
     class MountServiceHandler extends Handler {
-        ArrayList<UnmountCallBack> mForceUnmounts = new ArrayList<UnmountCallBack>();
-        boolean mUpdatingStatus = false;
-
-        MountServiceHandler(Looper l) {
-            super(l);
+        public MountServiceHandler(Looper looper) {
+            super(looper);
         }
 
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case H_UNMOUNT_PM_UPDATE: {
-                    if (DEBUG_UNMOUNT) Slog.i(TAG, "H_UNMOUNT_PM_UPDATE");
-                    UnmountCallBack ucb = (UnmountCallBack) msg.obj;
-                    mForceUnmounts.add(ucb);
-                    if (DEBUG_UNMOUNT) Slog.i(TAG, " registered = " + mUpdatingStatus);
-                    // Register only if needed.
-                    if (!mUpdatingStatus) {
-                        if (DEBUG_UNMOUNT) Slog.i(TAG, "Updating external media status on PackageManager");
-                        mUpdatingStatus = true;
-                        mPms.updateExternalMediaStatus(false, true);
-                    }
-                    break;
-                }
-                case H_UNMOUNT_PM_DONE: {
-                    if (DEBUG_UNMOUNT) Slog.i(TAG, "H_UNMOUNT_PM_DONE");
-                    if (DEBUG_UNMOUNT) Slog.i(TAG, "Updated status. Processing requests");
-                    mUpdatingStatus = false;
-                    int size = mForceUnmounts.size();
-                    int sizeArr[] = new int[size];
-                    int sizeArrN = 0;
-                    // Kill processes holding references first
-                    ActivityManagerService ams = (ActivityManagerService)
-                    ServiceManager.getService("activity");
-                    for (int i = 0; i < size; i++) {
-                        UnmountCallBack ucb = mForceUnmounts.get(i);
-                        String path = ucb.path;
-                        boolean done = false;
-                        if (!ucb.force) {
-                            done = true;
-                        } else {
-                            int pids[] = getStorageUsers(path);
-                            if (pids == null || pids.length == 0) {
-                                done = true;
-                            } else {
-                                // Eliminate system process here?
-                                ams.killPids(pids, "unmount media", true);
-                                // Confirm if file references have been freed.
-                                pids = getStorageUsers(path);
-                                if (pids == null || pids.length == 0) {
-                                    done = true;
-                                }
-                            }
-                        }
-                        if (!done && (ucb.retries < MAX_UNMOUNT_RETRIES)) {
-                            // Retry again
-                            Slog.i(TAG, "Retrying to kill storage users again");
-                            mHandler.sendMessageDelayed(
-                                    mHandler.obtainMessage(H_UNMOUNT_PM_DONE,
-                                            ucb.retries++),
-                                    RETRY_UNMOUNT_DELAY);
-                        } else {
-                            if (ucb.retries >= MAX_UNMOUNT_RETRIES) {
-                                Slog.i(TAG, "Failed to unmount media inspite of " +
-                                        MAX_UNMOUNT_RETRIES + " retries. Forcibly killing processes now");
-                            }
-                            sizeArr[sizeArrN++] = i;
-                            mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_MS,
-                                    ucb));
-                        }
-                    }
-                    // Remove already processed elements from list.
-                    for (int i = (sizeArrN-1); i >= 0; i--) {
-                        mForceUnmounts.remove(sizeArr[i]);
-                    }
-                    break;
-                }
-                case H_UNMOUNT_MS: {
-                    if (DEBUG_UNMOUNT) Slog.i(TAG, "H_UNMOUNT_MS");
-                    UnmountCallBack ucb = (UnmountCallBack) msg.obj;
-                    ucb.handleFinished();
-                    break;
-                }
                 case H_SYSTEM_READY: {
-                    try {
-                        handleSystemReady();
-                    } catch (Exception ex) {
-                        Slog.e(TAG, "Boot-time mount exception", ex);
-                    }
+                    handleSystemReady();
+                    break;
+                }
+                case H_DAEMON_CONNECTED: {
+                    handleDaemonConnected();
                     break;
                 }
                 case H_FSTRIM: {
@@ -589,29 +474,68 @@
                     }
                     break;
                 }
+                case H_SHUTDOWN: {
+                    final IMountShutdownObserver obs = (IMountShutdownObserver) msg.obj;
+                    boolean success = false;
+                    try {
+                        success = mConnector.execute("volume", "shutdown").isClassOk();
+                    } catch (NativeDaemonConnectorException ignored) {
+                    }
+                    if (obs != null) {
+                        try {
+                            obs.onShutDownComplete(success ? 0 : -1);
+                        } catch (RemoteException ignored) {
+                        }
+                    }
+                    break;
+                }
+                case H_VOLUME_MOUNT: {
+                    final VolumeInfo vol = (VolumeInfo) msg.obj;
+                    try {
+                        mConnector.execute("volume", "mount", vol.id, vol.flags, vol.userId);
+                    } catch (NativeDaemonConnectorException ignored) {
+                    }
+                    break;
+                }
+                case H_VOLUME_BROADCAST: {
+                    final StorageVolume userVol = (StorageVolume) msg.obj;
+                    final String envState = userVol.getState();
+                    Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
+                            + userVol.getOwner());
+
+                    final String action = VolumeInfo.getBroadcastForEnvironment(envState);
+                    if (action != null) {
+                        final Intent intent = new Intent(action,
+                                Uri.fromFile(userVol.getPathFile()));
+                        intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
+                        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                        mContext.sendBroadcastAsUser(intent, userVol.getOwner());
+                    }
+                    break;
+                }
             }
         }
-    };
+    }
 
     private final Handler mHandler;
 
     @Override
     public void waitForAsecScan() {
-        waitForLatch(mAsecsScanned);
+        waitForLatch(mAsecsScanned, "mAsecsScanned");
     }
 
     private void waitForReady() {
-        waitForLatch(mConnectedSignal);
+        waitForLatch(mConnectedSignal, "mConnectedSignal");
     }
 
-    private void waitForLatch(CountDownLatch latch) {
+    private void waitForLatch(CountDownLatch latch, String condition) {
         for (;;) {
             try {
                 if (latch.await(5000, TimeUnit.MILLISECONDS)) {
                     return;
                 } else {
                     Slog.w(TAG, "Thread " + Thread.currentThread().getName()
-                            + " still waiting for MountService ready...");
+                            + " still waiting for " + condition + "...");
                 }
             } catch (InterruptedException e) {
                 Slog.w(TAG, "Interrupt while waiting for MountService to be ready.");
@@ -628,109 +552,65 @@
     }
 
     private void handleSystemReady() {
-        // Snapshot current volume states since it's not safe to call into vold
-        // while holding locks.
-        final HashMap<String, String> snapshot;
-        synchronized (mVolumesLock) {
-            snapshot = new HashMap<String, String>(mVolumeStates);
-        }
+        resetIfReadyAndConnected();
 
-        for (Map.Entry<String, String> entry : snapshot.entrySet()) {
-            final String path = entry.getKey();
-            final String state = entry.getValue();
-
-            if (state.equals(Environment.MEDIA_UNMOUNTED)) {
-                int rc = doMountVolume(path);
-                if (rc != StorageResultCode.OperationSucceeded) {
-                    Slog.e(TAG, String.format("Boot-time mount failed (%d)",
-                            rc));
-                }
-            } else if (state.equals(Environment.MEDIA_SHARED)) {
-                /*
-                 * Bootstrap UMS enabled state since vold indicates
-                 * the volume is shared (runtime restart while ums enabled)
-                 */
-                notifyVolumeStateChange(null, path, VolumeState.NoMedia,
-                        VolumeState.Shared);
-            }
-        }
-
-        // Push mounted state for all emulated storage
-        synchronized (mVolumesLock) {
-            for (StorageVolume volume : mVolumes) {
-                if (volume.isEmulated()) {
-                    updatePublicVolumeState(volume, Environment.MEDIA_MOUNTED);
-                }
-            }
-        }
-
-        /*
-         * If UMS was connected on boot, send the connected event
-         * now that we're up.
-         */
-        if (mSendUmsConnectedOnBoot) {
-            sendUmsIntent(true);
-            mSendUmsConnectedOnBoot = false;
-        }
-
-        /*
-         * Start scheduling nominally-daily fstrim operations
-         */
+        // Start scheduling nominally-daily fstrim operations
         MountServiceIdler.scheduleIdlePass(mContext);
     }
 
-    private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
-            if (userId == -1) return;
-            final UserHandle user = new UserHandle(userId);
+    private void resetIfReadyAndConnected() {
+        Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
+                + ", mDaemonConnected=" + mDaemonConnected);
+        if (mSystemReady && mDaemonConnected) {
+            mDisks.clear();
+            mVolumes.clear();
 
-            final String action = intent.getAction();
-            if (Intent.ACTION_USER_ADDED.equals(action)) {
-                synchronized (mVolumesLock) {
-                    createEmulatedVolumeForUserLocked(user);
-                }
-
-            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                synchronized (mVolumesLock) {
-                    final List<StorageVolume> toRemove = Lists.newArrayList();
-                    for (StorageVolume volume : mVolumes) {
-                        if (user.equals(volume.getOwner())) {
-                            toRemove.add(volume);
-                        }
-                    }
-                    for (StorageVolume volume : toRemove) {
-                        removeVolumeLocked(volume);
-                    }
-                }
+            try {
+                mConnector.execute("volume", "reset");
+            } catch (NativeDaemonConnectorException e) {
+                Slog.w(TAG, "Failed to reset vold", e);
             }
         }
-    };
+    }
 
-    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            boolean available = (intent.getBooleanExtra(UsbManager.USB_CONNECTED, false) &&
-                    intent.getBooleanExtra(UsbManager.USB_FUNCTION_MASS_STORAGE, false));
-            notifyShareAvailabilityChange(available);
-        }
-    };
+    private void onStartUser(int userId) {
+        Slog.d(TAG, "onStartUser " + userId);
 
-    private final class MountServiceBinderListener implements IBinder.DeathRecipient {
-        final IMountServiceListener mListener;
-
-        MountServiceBinderListener(IMountServiceListener listener) {
-            mListener = listener;
-
+        // We purposefully block here to make sure that user-specific
+        // staging area is ready so it's ready for zygote-forked apps to
+        // bind mount against.
+        try {
+            mConnector.execute("volume", "start_user", userId);
+        } catch (NativeDaemonConnectorException ignored) {
         }
 
-        public void binderDied() {
-            if (LOCAL_LOGD) Slog.d(TAG, "An IMountServiceListener has died!");
-            synchronized (mListeners) {
-                mListeners.remove(this);
-                mListener.asBinder().unlinkToDeath(this, 0);
+        // Record user as started so newly mounted volumes kick off events
+        // correctly, then synthesize events for any already-mounted volumes.
+        synchronized (mVolumes) {
+            for (int i = 0; i < mVolumes.size(); i++) {
+                final VolumeInfo vol = mVolumes.valueAt(i);
+                if (vol.isVisibleToUser(userId) && vol.state == VolumeInfo.STATE_MOUNTED) {
+                    final StorageVolume userVol = vol.buildStorageVolume(mContext, userId);
+                    mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
+
+                    mCallbacks.notifyStorageStateChanged(userVol.getPath(),
+                            Environment.MEDIA_MOUNTED, Environment.MEDIA_MOUNTED);
+                }
             }
+            mStartedUsers = ArrayUtils.appendInt(mStartedUsers, userId);
+        }
+    }
+
+    private void onCleanupUser(int userId) {
+        Slog.d(TAG, "onCleanupUser " + userId);
+
+        try {
+            mConnector.execute("volume", "cleanup_user", userId);
+        } catch (NativeDaemonConnectorException ignored) {
+        }
+
+        synchronized (mVolumes) {
+            mStartedUsers = ArrayUtils.removeInt(mStartedUsers, userId);
         }
     }
 
@@ -741,7 +621,7 @@
     // Binder entry point for kicking off an immediate fstrim
     @Override
     public void runMaintenance() {
-        validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
+        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
         runIdleMaintenance(null);
     }
 
@@ -750,144 +630,35 @@
         return mLastMaintenance;
     }
 
-    private void doShareUnshareVolume(String path, String method, boolean enable) {
-        // TODO: Add support for multiple share methods
-        if (!method.equals("ums")) {
-            throw new IllegalArgumentException(String.format("Method %s not supported", method));
-        }
-
-        try {
-            mConnector.execute("volume", enable ? "share" : "unshare", path, method);
-        } catch (NativeDaemonConnectorException e) {
-            Slog.e(TAG, "Failed to share/unshare", e);
-        }
-    }
-
-    private void updatePublicVolumeState(StorageVolume volume, String state) {
-        final String path = volume.getPath();
-        final String oldState;
-        synchronized (mVolumesLock) {
-            oldState = mVolumeStates.put(path, state);
-            volume.setState(state);
-        }
-
-        if (state.equals(oldState)) {
-            Slog.w(TAG, String.format("Duplicate state transition (%s -> %s) for %s",
-                    state, state, path));
-            return;
-        }
-
-        Slog.d(TAG, "volume state changed for " + path + " (" + oldState + " -> " + state + ")");
-
-        // Tell PackageManager about changes to primary volume state, but only
-        // when not emulated.
-        if (volume.isPrimary() && !volume.isEmulated()) {
-            if (Environment.MEDIA_UNMOUNTED.equals(state)) {
-                mPms.updateExternalMediaStatus(false, false);
-
-                /*
-                 * Some OBBs might have been unmounted when this volume was
-                 * unmounted, so send a message to the handler to let it know to
-                 * remove those from the list of mounted OBBS.
-                 */
-                mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
-                        OBB_FLUSH_MOUNT_STATE, path));
-            } else if (Environment.MEDIA_MOUNTED.equals(state)) {
-                mPms.updateExternalMediaStatus(true, false);
-            }
-        }
-
-        synchronized (mListeners) {
-            for (int i = mListeners.size() -1; i >= 0; i--) {
-                MountServiceBinderListener bl = mListeners.get(i);
-                try {
-                    bl.mListener.onStorageStateChanged(path, oldState, state);
-                } catch (RemoteException rex) {
-                    Slog.e(TAG, "Listener dead");
-                    mListeners.remove(i);
-                } catch (Exception ex) {
-                    Slog.e(TAG, "Listener failed", ex);
-                }
-            }
-        }
-    }
-
     /**
      * Callback from NativeDaemonConnector
      */
+    @Override
     public void onDaemonConnected() {
+        mDaemonConnected = true;
+        mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
+    }
+
+    private void handleDaemonConnected() {
+        resetIfReadyAndConnected();
+
         /*
-         * Since we'll be calling back into the NativeDaemonConnector,
-         * we need to do our work in a new thread.
+         * Now that we've done our initialization, release
+         * the hounds!
          */
-        new Thread("MountService#onDaemonConnected") {
-            @Override
-            public void run() {
-                /**
-                 * Determine media state and UMS detection status
-                 */
-                try {
-                    final String[] vols = NativeDaemonEvent.filterMessageList(
-                            mConnector.executeForList("volume", "list", "broadcast"),
-                            VoldResponseCode.VolumeListResult);
-                    for (String volstr : vols) {
-                        String[] tok = volstr.split(" ");
-                        // FMT: <label> <mountpoint> <state>
-                        String path = tok[1];
-                        String state = Environment.MEDIA_REMOVED;
+        mConnectedSignal.countDown();
 
-                        final StorageVolume volume;
-                        synchronized (mVolumesLock) {
-                            volume = mVolumesByPath.get(path);
-                        }
+        // On an encrypted device we can't see system properties yet, so pull
+        // the system locale out of the mount service.
+        if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
+            copyLocaleFromMountService();
+        }
 
-                        int st = Integer.parseInt(tok[2]);
-                        if (st == VolumeState.NoMedia) {
-                            state = Environment.MEDIA_REMOVED;
-                        } else if (st == VolumeState.Idle) {
-                            state = Environment.MEDIA_UNMOUNTED;
-                        } else if (st == VolumeState.Mounted) {
-                            state = Environment.MEDIA_MOUNTED;
-                            Slog.i(TAG, "Media already mounted on daemon connection");
-                        } else if (st == VolumeState.Shared) {
-                            state = Environment.MEDIA_SHARED;
-                            Slog.i(TAG, "Media shared on daemon connection");
-                        } else {
-                            throw new Exception(String.format("Unexpected state %d", st));
-                        }
+        // Let package manager load internal ASECs.
+        mPms.scanAvailableAsecs();
 
-                        if (state != null) {
-                            if (DEBUG_EVENTS) Slog.i(TAG, "Updating valid state " + state);
-                            updatePublicVolumeState(volume, state);
-                        }
-                    }
-                } catch (Exception e) {
-                    Slog.e(TAG, "Error processing initial volume state", e);
-                    final StorageVolume primary = getPrimaryPhysicalVolume();
-                    if (primary != null) {
-                        updatePublicVolumeState(primary, Environment.MEDIA_REMOVED);
-                    }
-                }
-
-                /*
-                 * Now that we've done our initialization, release
-                 * the hounds!
-                 */
-                mConnectedSignal.countDown();
-
-                // On an encrypted device we can't see system properties yet, so pull
-                // the system locale out of the mount service.
-                if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
-                    copyLocaleFromMountService();
-                }
-
-                // Let package manager load internal ASECs.
-                mPms.scanAvailableAsecs();
-
-                // Notify people waiting for ASECs to be scanned that it's done.
-                mAsecsScanned.countDown();
-            }
-        }.start();
+        // Notify people waiting for ASECs to be scanned that it's done.
+        mAsecsScanned.countDown();
     }
 
     private void copyLocaleFromMountService() {
@@ -919,6 +690,7 @@
     /**
      * Callback from NativeDaemonConnector
      */
+    @Override
     public boolean onCheckHoldWakeLock(int code) {
         return false;
     }
@@ -926,570 +698,193 @@
     /**
      * Callback from NativeDaemonConnector
      */
+    @Override
     public boolean onEvent(int code, String raw, String[] cooked) {
-        if (DEBUG_EVENTS) {
-            StringBuilder builder = new StringBuilder();
-            builder.append("onEvent::");
-            builder.append(" raw= " + raw);
-            if (cooked != null) {
-                builder.append(" cooked = " );
-                for (String str : cooked) {
-                    builder.append(" " + str);
-                }
-            }
-            Slog.i(TAG, builder.toString());
+        synchronized (mLock) {
+            return onEventLocked(code, raw, cooked);
         }
-        if (code == VoldResponseCode.VolumeStateChange) {
-            /*
-             * One of the volumes we're managing has changed state.
-             * Format: "NNN Volume <label> <path> state changed
-             * from <old_#> (<old_str>) to <new_#> (<new_str>)"
-             */
-            notifyVolumeStateChange(
-                    cooked[2], cooked[3], Integer.parseInt(cooked[7]),
-                            Integer.parseInt(cooked[10]));
-        } else if (code == VoldResponseCode.VolumeUuidChange) {
-            // Format: nnn <label> <path> <uuid>
-            final String path = cooked[2];
-            final String uuid = (cooked.length > 3) ? cooked[3] : null;
+    }
 
-            final StorageVolume vol = mVolumesByPath.get(path);
-            if (vol != null) {
-                vol.setUuid(uuid);
+    private boolean onEventLocked(int code, String raw, String[] cooked) {
+        switch (code) {
+            case VoldResponseCode.DISK_CREATED: {
+                if (cooked.length != 3) break;
+                final String id = cooked[1];
+                final int flags = Integer.parseInt(cooked[2]);
+                mDisks.put(id, new DiskInfo(id, flags));
+                break;
             }
-
-        } else if (code == VoldResponseCode.VolumeUserLabelChange) {
-            // Format: nnn <label> <path> <label>
-            final String path = cooked[2];
-            final String userLabel = (cooked.length > 3) ? cooked[3] : null;
-
-            final StorageVolume vol = mVolumesByPath.get(path);
-            if (vol != null) {
-                vol.setUserLabel(userLabel);
-            }
-
-        } else if ((code == VoldResponseCode.VolumeDiskInserted) ||
-                   (code == VoldResponseCode.VolumeDiskRemoved) ||
-                   (code == VoldResponseCode.VolumeBadRemoval)) {
-            // FMT: NNN Volume <label> <mountpoint> disk inserted (<major>:<minor>)
-            // FMT: NNN Volume <label> <mountpoint> disk removed (<major>:<minor>)
-            // FMT: NNN Volume <label> <mountpoint> bad removal (<major>:<minor>)
-            String action = null;
-            final String label = cooked[2];
-            final String path = cooked[3];
-            int major = -1;
-            int minor = -1;
-
-            try {
-                String devComp = cooked[6].substring(1, cooked[6].length() -1);
-                String[] devTok = devComp.split(":");
-                major = Integer.parseInt(devTok[0]);
-                minor = Integer.parseInt(devTok[1]);
-            } catch (Exception ex) {
-                Slog.e(TAG, "Failed to parse major/minor", ex);
-            }
-
-            final StorageVolume volume;
-            final String state;
-            synchronized (mVolumesLock) {
-                volume = mVolumesByPath.get(path);
-                state = mVolumeStates.get(path);
-            }
-
-            if (code == VoldResponseCode.VolumeDiskInserted) {
-                new Thread("MountService#VolumeDiskInserted") {
-                    @Override
-                    public void run() {
-                        try {
-                            int rc;
-                            if ((rc = doMountVolume(path)) != StorageResultCode.OperationSucceeded) {
-                                Slog.w(TAG, String.format("Insertion mount failed (%d)", rc));
-                            }
-                        } catch (Exception ex) {
-                            Slog.w(TAG, "Failed to mount media on insertion", ex);
-                        }
-                    }
-                }.start();
-            } else if (code == VoldResponseCode.VolumeDiskRemoved) {
-                /*
-                 * This event gets trumped if we're already in BAD_REMOVAL state
-                 */
-                if (getVolumeState(path).equals(Environment.MEDIA_BAD_REMOVAL)) {
-                    return true;
+            case VoldResponseCode.DISK_SIZE_CHANGED: {
+                if (cooked.length != 3) break;
+                final DiskInfo disk = mDisks.get(cooked[1]);
+                if (disk != null) {
+                    disk.size = Long.parseLong(cooked[2]);
                 }
-                /* Send the media unmounted event first */
-                if (DEBUG_EVENTS) Slog.i(TAG, "Sending unmounted event first");
-                updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTED);
-                sendStorageIntent(Intent.ACTION_MEDIA_UNMOUNTED, volume, UserHandle.ALL);
+                break;
+            }
+            case VoldResponseCode.DISK_LABEL_CHANGED: {
+                if (cooked.length != 3) break;
+                final DiskInfo disk = mDisks.get(cooked[1]);
+                if (disk != null) {
+                    disk.label = cooked[2];
+                }
+                break;
+            }
+            case VoldResponseCode.DISK_VOLUME_CREATED: {
+                if (cooked.length != 3) break;
+                final DiskInfo disk = mDisks.get(cooked[1]);
+                final String volId = cooked[2];
+                if (disk != null) {
+                    disk.volumes = ArrayUtils.appendElement(String.class, disk.volumes, volId);
+                }
+                break;
+            }
+            case VoldResponseCode.DISK_DESTROYED: {
+                if (cooked.length != 2) break;
+                mDisks.remove(cooked[1]);
+                break;
+            }
 
-                if (DEBUG_EVENTS) Slog.i(TAG, "Sending media removed");
-                updatePublicVolumeState(volume, Environment.MEDIA_REMOVED);
-                action = Intent.ACTION_MEDIA_REMOVED;
-            } else if (code == VoldResponseCode.VolumeBadRemoval) {
-                if (DEBUG_EVENTS) Slog.i(TAG, "Sending unmounted event first");
-                /* Send the media unmounted event first */
-                updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTED);
-                sendStorageIntent(Intent.ACTION_MEDIA_UNMOUNTED, volume, UserHandle.ALL);
+            case VoldResponseCode.VOLUME_CREATED: {
+                if (cooked.length != 3) break;
+                final String id = cooked[1];
+                final int type = Integer.parseInt(cooked[2]);
+                final int mtpIndex = allocateMtpIndex(id);
+                final VolumeInfo vol = new VolumeInfo(id, type, mtpIndex);
+                mVolumes.put(id, vol);
+                onVolumeCreatedLocked(vol);
+                break;
+            }
+            case VoldResponseCode.VOLUME_STATE_CHANGED: {
+                if (cooked.length != 3) break;
+                final VolumeInfo vol = mVolumes.get(cooked[1]);
+                if (vol != null) {
+                    final int oldState = vol.state;
+                    final int newState = Integer.parseInt(cooked[2]);
+                    vol.state = newState;
+                    onVolumeStateChangedLocked(vol, oldState, newState);
+                }
+                break;
+            }
+            case VoldResponseCode.VOLUME_FS_TYPE_CHANGED: {
+                if (cooked.length != 3) break;
+                final VolumeInfo vol = mVolumes.get(cooked[1]);
+                if (vol != null) {
+                    vol.fsType = cooked[2];
+                }
+                break;
+            }
+            case VoldResponseCode.VOLUME_FS_UUID_CHANGED: {
+                if (cooked.length != 3) break;
+                final VolumeInfo vol = mVolumes.get(cooked[1]);
+                if (vol != null) {
+                    vol.fsUuid = cooked[2];
+                }
+                break;
+            }
+            case VoldResponseCode.VOLUME_FS_LABEL_CHANGED: {
+                if (cooked.length != 3) break;
+                final VolumeInfo vol = mVolumes.get(cooked[1]);
+                if (vol != null) {
+                    vol.fsLabel = cooked[2];
+                }
+                break;
+            }
+            case VoldResponseCode.VOLUME_PATH_CHANGED: {
+                if (cooked.length != 3) break;
+                final VolumeInfo vol = mVolumes.get(cooked[1]);
+                if (vol != null) {
+                    vol.path = cooked[2];
+                }
+                break;
+            }
+            case VoldResponseCode.VOLUME_DESTROYED: {
+                // TODO: send ACTION_MEDIA_REMOVED broadcast
+                if (cooked.length != 2) break;
+                mVolumes.remove(cooked[1]);
+                break;
+            }
 
-                if (DEBUG_EVENTS) Slog.i(TAG, "Sending media bad removal");
-                updatePublicVolumeState(volume, Environment.MEDIA_BAD_REMOVAL);
-                action = Intent.ACTION_MEDIA_BAD_REMOVAL;
-            } else if (code == VoldResponseCode.FstrimCompleted) {
+            case VoldResponseCode.FstrimCompleted: {
                 EventLogTags.writeFstrimFinish(SystemClock.elapsedRealtime());
-            } else {
-                Slog.e(TAG, String.format("Unknown code {%d}", code));
+                break;
             }
-
-            if (action != null) {
-                sendStorageIntent(action, volume, UserHandle.ALL);
+            default: {
+                Slog.d(TAG, "Unhandled vold event " + code);
             }
-        } else {
-            return false;
         }
 
         return true;
     }
 
-    private void notifyVolumeStateChange(String label, String path, int oldState, int newState) {
-        final StorageVolume volume;
-        final String state;
-        synchronized (mVolumesLock) {
-            volume = mVolumesByPath.get(path);
-            state = getVolumeState(path);
-        }
+    private void onVolumeCreatedLocked(VolumeInfo vol) {
+        final boolean primaryPhysical = SystemProperties.getBoolean(
+                StorageManager.PROP_PRIMARY_PHYSICAL, false);
+        if (vol.type == VolumeInfo.TYPE_EMULATED && !primaryPhysical) {
+            vol.flags |= VolumeInfo.FLAG_PRIMARY;
+            vol.flags |= VolumeInfo.FLAG_VISIBLE;
+            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
 
-        if (DEBUG_EVENTS) Slog.i(TAG, "notifyVolumeStateChange::" + state);
-
-        String action = null;
-
-        if (oldState == VolumeState.Shared && newState != oldState) {
-            if (LOCAL_LOGD) Slog.d(TAG, "Sending ACTION_MEDIA_UNSHARED intent");
-            sendStorageIntent(Intent.ACTION_MEDIA_UNSHARED, volume, UserHandle.ALL);
-        }
-
-        if (newState == VolumeState.Init) {
-        } else if (newState == VolumeState.NoMedia) {
-            // NoMedia is handled via Disk Remove events
-        } else if (newState == VolumeState.Idle) {
-            /*
-             * Don't notify if we're in BAD_REMOVAL, NOFS, UNMOUNTABLE, or
-             * if we're in the process of enabling UMS
-             */
-            if (!state.equals(
-                    Environment.MEDIA_BAD_REMOVAL) && !state.equals(
-                            Environment.MEDIA_NOFS) && !state.equals(
-                                    Environment.MEDIA_UNMOUNTABLE) && !getUmsEnabling()) {
-                if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state for media bad removal nofs and unmountable");
-                updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTED);
-                action = Intent.ACTION_MEDIA_UNMOUNTED;
+        } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
+            if (primaryPhysical) {
+                vol.flags |= VolumeInfo.FLAG_PRIMARY;
             }
-        } else if (newState == VolumeState.Pending) {
-        } else if (newState == VolumeState.Checking) {
-            if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state checking");
-            updatePublicVolumeState(volume, Environment.MEDIA_CHECKING);
-            action = Intent.ACTION_MEDIA_CHECKING;
-        } else if (newState == VolumeState.Mounted) {
-            if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state mounted");
-            updatePublicVolumeState(volume, Environment.MEDIA_MOUNTED);
-            action = Intent.ACTION_MEDIA_MOUNTED;
-        } else if (newState == VolumeState.Unmounting) {
-            action = Intent.ACTION_MEDIA_EJECT;
-        } else if (newState == VolumeState.Formatting) {
-        } else if (newState == VolumeState.Shared) {
-            if (DEBUG_EVENTS) Slog.i(TAG, "Updating volume state media mounted");
-            /* Send the media unmounted event first */
-            updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTED);
-            sendStorageIntent(Intent.ACTION_MEDIA_UNMOUNTED, volume, UserHandle.ALL);
+            vol.flags |= VolumeInfo.FLAG_VISIBLE;
+            vol.userId = UserHandle.USER_OWNER;
+            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
 
-            if (DEBUG_EVENTS) Slog.i(TAG, "Updating media shared");
-            updatePublicVolumeState(volume, Environment.MEDIA_SHARED);
-            action = Intent.ACTION_MEDIA_SHARED;
-            if (LOCAL_LOGD) Slog.d(TAG, "Sending ACTION_MEDIA_SHARED intent");
-        } else if (newState == VolumeState.SharedMnt) {
-            Slog.e(TAG, "Live shared mounts not supported yet!");
-            return;
+        } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
+            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
+
         } else {
-            Slog.e(TAG, "Unhandled VolumeState {" + newState + "}");
-        }
-
-        if (action != null) {
-            sendStorageIntent(action, volume, UserHandle.ALL);
+            Slog.d(TAG, "Skipping automatic mounting of " + vol);
         }
     }
 
-    private int doMountVolume(String path) {
-        int rc = StorageResultCode.OperationSucceeded;
+    private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
+        mCallbacks.notifyVolumeStateChanged(vol.clone(), oldState, newState);
 
-        final StorageVolume volume;
-        synchronized (mVolumesLock) {
-            volume = mVolumesByPath.get(path);
-        }
+        final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
+        final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
 
-        if (!volume.isEmulated() && hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA)) {
-            Slog.w(TAG, "User has restriction DISALLOW_MOUNT_PHYSICAL_MEDIA; cannot mount volume.");
-            return StorageResultCode.OperationFailedInternalError;
-        }
+        if (!Objects.equals(oldStateEnv, newStateEnv)) {
+            // Kick state changed event towards all started users. Any users
+            // started after this point will trigger additional
+            // user-specific broadcasts.
+            for (int userId : mStartedUsers) {
+                if (vol.isVisibleToUser(userId)) {
+                    final StorageVolume userVol = vol.buildStorageVolume(mContext, userId);
+                    mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
 
-        if (DEBUG_EVENTS) Slog.i(TAG, "doMountVolume: Mouting " + path);
-        try {
-            mConnector.execute("volume", "mount", path);
-        } catch (NativeDaemonConnectorException e) {
-            /*
-             * Mount failed for some reason
-             */
-            String action = null;
-            int code = e.getCode();
-            if (code == VoldResponseCode.OpFailedNoMedia) {
-                /*
-                 * Attempt to mount but no media inserted
-                 */
-                rc = StorageResultCode.OperationFailedNoMedia;
-            } else if (code == VoldResponseCode.OpFailedMediaBlank) {
-                if (DEBUG_EVENTS) Slog.i(TAG, " updating volume state :: media nofs");
-                /*
-                 * Media is blank or does not contain a supported filesystem
-                 */
-                updatePublicVolumeState(volume, Environment.MEDIA_NOFS);
-                action = Intent.ACTION_MEDIA_NOFS;
-                rc = StorageResultCode.OperationFailedMediaBlank;
-            } else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
-                if (DEBUG_EVENTS) Slog.i(TAG, "updating volume state media corrupt");
-                /*
-                 * Volume consistency check failed
-                 */
-                updatePublicVolumeState(volume, Environment.MEDIA_UNMOUNTABLE);
-                action = Intent.ACTION_MEDIA_UNMOUNTABLE;
-                rc = StorageResultCode.OperationFailedMediaCorrupt;
-            } else {
-                rc = StorageResultCode.OperationFailedInternalError;
-            }
-
-            /*
-             * Send broadcast intent (if required for the failure)
-             */
-            if (action != null) {
-                sendStorageIntent(action, volume, UserHandle.ALL);
-            }
-        }
-
-        return rc;
-    }
-
-    /*
-     * If force is not set, we do not unmount if there are
-     * processes holding references to the volume about to be unmounted.
-     * If force is set, all the processes holding references need to be
-     * killed via the ActivityManager before actually unmounting the volume.
-     * This might even take a while and might be retried after timed delays
-     * to make sure we dont end up in an instable state and kill some core
-     * processes.
-     * If removeEncryption is set, force is implied, and the system will remove any encryption
-     * mapping set on the volume when unmounting.
-     */
-    private int doUnmountVolume(String path, boolean force, boolean removeEncryption) {
-        if (!getVolumeState(path).equals(Environment.MEDIA_MOUNTED)) {
-            return VoldResponseCode.OpFailedVolNotMounted;
-        }
-
-        /*
-         * Force a GC to make sure AssetManagers in other threads of the
-         * system_server are cleaned up. We have to do this since AssetManager
-         * instances are kept as a WeakReference and it's possible we have files
-         * open on the external storage.
-         */
-        Runtime.getRuntime().gc();
-
-        // Redundant probably. But no harm in updating state again.
-        mPms.updateExternalMediaStatus(false, false);
-        try {
-            final Command cmd = new Command("volume", "unmount", path);
-            if (removeEncryption) {
-                cmd.appendArg("force_and_revert");
-            } else if (force) {
-                cmd.appendArg("force");
-            }
-            mConnector.execute(cmd);
-            // We unmounted the volume. None of the asec containers are available now.
-            synchronized (mAsecMountSet) {
-                mAsecMountSet.clear();
-            }
-            return StorageResultCode.OperationSucceeded;
-        } catch (NativeDaemonConnectorException e) {
-            // Don't worry about mismatch in PackageManager since the
-            // call back will handle the status changes any way.
-            int code = e.getCode();
-            if (code == VoldResponseCode.OpFailedVolNotMounted) {
-                return StorageResultCode.OperationFailedStorageNotMounted;
-            } else if (code == VoldResponseCode.OpFailedStorageBusy) {
-                return StorageResultCode.OperationFailedStorageBusy;
-            } else {
-                return StorageResultCode.OperationFailedInternalError;
-            }
-        }
-    }
-
-    private int doFormatVolume(String path) {
-        try {
-            mConnector.execute("volume", "format", path);
-            return StorageResultCode.OperationSucceeded;
-        } catch (NativeDaemonConnectorException e) {
-            int code = e.getCode();
-            if (code == VoldResponseCode.OpFailedNoMedia) {
-                return StorageResultCode.OperationFailedNoMedia;
-            } else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
-                return StorageResultCode.OperationFailedMediaCorrupt;
-            } else {
-                return StorageResultCode.OperationFailedInternalError;
-            }
-        }
-    }
-
-    private boolean doGetVolumeShared(String path, String method) {
-        final NativeDaemonEvent event;
-        try {
-            event = mConnector.execute("volume", "shared", path, method);
-        } catch (NativeDaemonConnectorException ex) {
-            Slog.e(TAG, "Failed to read response to volume shared " + path + " " + method);
-            return false;
-        }
-
-        if (event.getCode() == VoldResponseCode.ShareEnabledResult) {
-            return event.getMessage().endsWith("enabled");
-        } else {
-            return false;
-        }
-    }
-
-    private void notifyShareAvailabilityChange(final boolean avail) {
-        synchronized (mListeners) {
-            mUmsAvailable = avail;
-            for (int i = mListeners.size() -1; i >= 0; i--) {
-                MountServiceBinderListener bl = mListeners.get(i);
-                try {
-                    bl.mListener.onUsbMassStorageConnectionChanged(avail);
-                } catch (RemoteException rex) {
-                    Slog.e(TAG, "Listener dead");
-                    mListeners.remove(i);
-                } catch (Exception ex) {
-                    Slog.e(TAG, "Listener failed", ex);
+                    mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
+                            newStateEnv);
                 }
             }
         }
 
-        if (mSystemReady == true) {
-            sendUmsIntent(avail);
-        } else {
-            mSendUmsConnectedOnBoot = avail;
-        }
-
-        final StorageVolume primary = getPrimaryPhysicalVolume();
-        if (avail == false && primary != null
-                && Environment.MEDIA_SHARED.equals(getVolumeState(primary.getPath()))) {
-            final String path = primary.getPath();
+        if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_UNMOUNTING) {
+            // TODO: this should eventually be handled by new ObbVolume state changes
             /*
-             * USB mass storage disconnected while enabled
+             * Some OBBs might have been unmounted when this volume was
+             * unmounted, so send a message to the handler to let it know to
+             * remove those from the list of mounted OBBS.
              */
-            new Thread("MountService#AvailabilityChange") {
-                @Override
-                public void run() {
-                    try {
-                        int rc;
-                        Slog.w(TAG, "Disabling UMS after cable disconnect");
-                        doShareUnshareVolume(path, "ums", false);
-                        if ((rc = doMountVolume(path)) != StorageResultCode.OperationSucceeded) {
-                            Slog.e(TAG, String.format(
-                                    "Failed to remount {%s} on UMS enabled-disconnect (%d)",
-                                            path, rc));
-                        }
-                    } catch (Exception ex) {
-                        Slog.w(TAG, "Failed to mount media on UMS enabled-disconnect", ex);
-                    }
-                }
-            }.start();
+            mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
+                    OBB_FLUSH_MOUNT_STATE, vol.path));
         }
     }
 
-    private void sendStorageIntent(String action, StorageVolume volume, UserHandle user) {
-        final Intent intent = new Intent(action, Uri.parse("file://" + volume.getPath()));
-        intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, volume);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        Slog.d(TAG, "sendStorageIntent " + intent + " to " + user);
-        mContext.sendBroadcastAsUser(intent, user);
+    private void enforcePermission(String perm) {
+        mContext.enforceCallingOrSelfPermission(perm, perm);
     }
 
-    private void sendUmsIntent(boolean c) {
-        mContext.sendBroadcastAsUser(
-                new Intent((c ? Intent.ACTION_UMS_CONNECTED : Intent.ACTION_UMS_DISCONNECTED)),
-                UserHandle.ALL);
-    }
-
-    private void validatePermission(String perm) {
-        if (mContext.checkCallingOrSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(String.format("Requires %s permission", perm));
-        }
-    }
-
-    private boolean hasUserRestriction(String restriction) {
+    private void enforceUserRestriction(String restriction) {
         UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        return um.hasUserRestriction(restriction, Binder.getCallingUserHandle());
-    }
-
-    private void validateUserRestriction(String restriction) {
-        if (hasUserRestriction(restriction)) {
+        if (um.hasUserRestriction(restriction, Binder.getCallingUserHandle())) {
             throw new SecurityException("User has restriction " + restriction);
         }
     }
 
-    // Storage list XML tags
-    private static final String TAG_STORAGE_LIST = "StorageList";
-    private static final String TAG_STORAGE = "storage";
-
-    private void readStorageListLocked() {
-        mVolumes.clear();
-        mVolumeStates.clear();
-
-        Resources resources = mContext.getResources();
-
-        int id = com.android.internal.R.xml.storage_list;
-        XmlResourceParser parser = resources.getXml(id);
-        AttributeSet attrs = Xml.asAttributeSet(parser);
-
-        try {
-            XmlUtils.beginDocument(parser, TAG_STORAGE_LIST);
-            while (true) {
-                XmlUtils.nextElement(parser);
-
-                String element = parser.getName();
-                if (element == null) break;
-
-                if (TAG_STORAGE.equals(element)) {
-                    TypedArray a = resources.obtainAttributes(attrs,
-                            com.android.internal.R.styleable.Storage);
-
-                    String path = a.getString(
-                            com.android.internal.R.styleable.Storage_mountPoint);
-                    int descriptionId = a.getResourceId(
-                            com.android.internal.R.styleable.Storage_storageDescription, -1);
-                    CharSequence description = a.getText(
-                            com.android.internal.R.styleable.Storage_storageDescription);
-                    boolean primary = a.getBoolean(
-                            com.android.internal.R.styleable.Storage_primary, false);
-                    boolean removable = a.getBoolean(
-                            com.android.internal.R.styleable.Storage_removable, false);
-                    boolean emulated = a.getBoolean(
-                            com.android.internal.R.styleable.Storage_emulated, false);
-                    int mtpReserve = a.getInt(
-                            com.android.internal.R.styleable.Storage_mtpReserve, 0);
-                    boolean allowMassStorage = a.getBoolean(
-                            com.android.internal.R.styleable.Storage_allowMassStorage, false);
-                    // resource parser does not support longs, so XML value is in megabytes
-                    long maxFileSize = a.getInt(
-                            com.android.internal.R.styleable.Storage_maxFileSize, 0) * 1024L * 1024L;
-
-                    Slog.d(TAG, "got storage path: " + path + " description: " + description +
-                            " primary: " + primary + " removable: " + removable +
-                            " emulated: " + emulated +  " mtpReserve: " + mtpReserve +
-                            " allowMassStorage: " + allowMassStorage +
-                            " maxFileSize: " + maxFileSize);
-
-                    if (emulated) {
-                        // For devices with emulated storage, we create separate
-                        // volumes for each known user.
-                        mEmulatedTemplate = new StorageVolume(null, descriptionId, true, false,
-                                true, mtpReserve, false, maxFileSize, null);
-
-                        final UserManagerService userManager = UserManagerService.getInstance();
-                        for (UserInfo user : userManager.getUsers(false)) {
-                            createEmulatedVolumeForUserLocked(user.getUserHandle());
-                        }
-
-                    } else {
-                        if (path == null || description == null) {
-                            Slog.e(TAG, "Missing storage path or description in readStorageList");
-                        } else {
-                            final StorageVolume volume = new StorageVolume(new File(path),
-                                    descriptionId, primary, removable, emulated, mtpReserve,
-                                    allowMassStorage, maxFileSize, null);
-                            addVolumeLocked(volume);
-
-                            // Until we hear otherwise, treat as unmounted
-                            mVolumeStates.put(volume.getPath(), Environment.MEDIA_UNMOUNTED);
-                            volume.setState(Environment.MEDIA_UNMOUNTED);
-                        }
-                    }
-
-                    a.recycle();
-                }
-            }
-        } catch (XmlPullParserException e) {
-            throw new RuntimeException(e);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        } finally {
-            // Compute storage ID for each physical volume; emulated storage is
-            // always 0 when defined.
-            int index = isExternalStorageEmulated() ? 1 : 0;
-            for (StorageVolume volume : mVolumes) {
-                if (!volume.isEmulated()) {
-                    volume.setStorageId(index++);
-                }
-            }
-            parser.close();
-        }
-    }
-
-    /**
-     * Create and add new {@link StorageVolume} for given {@link UserHandle}
-     * using {@link #mEmulatedTemplate} as template.
-     */
-    private void createEmulatedVolumeForUserLocked(UserHandle user) {
-        if (mEmulatedTemplate == null) {
-            throw new IllegalStateException("Missing emulated volume multi-user template");
-        }
-
-        final UserEnvironment userEnv = new UserEnvironment(user.getIdentifier());
-        final File path = userEnv.getExternalStorageDirectory();
-        final StorageVolume volume = StorageVolume.fromTemplate(mEmulatedTemplate, path, user);
-        volume.setStorageId(0);
-        addVolumeLocked(volume);
-
-        if (mSystemReady) {
-            updatePublicVolumeState(volume, Environment.MEDIA_MOUNTED);
-        } else {
-            // Place stub status for early callers to find
-            mVolumeStates.put(volume.getPath(), Environment.MEDIA_MOUNTED);
-            volume.setState(Environment.MEDIA_MOUNTED);
-        }
-    }
-
-    private void addVolumeLocked(StorageVolume volume) {
-        Slog.d(TAG, "addVolumeLocked() " + volume);
-        mVolumes.add(volume);
-        final StorageVolume existing = mVolumesByPath.put(volume.getPath(), volume);
-        if (existing != null) {
-            throw new IllegalStateException(
-                    "Volume at " + volume.getPath() + " already exists: " + existing);
-        }
-    }
-
-    private void removeVolumeLocked(StorageVolume volume) {
-        Slog.d(TAG, "removeVolumeLocked() " + volume);
-        mVolumes.remove(volume);
-        mVolumesByPath.remove(volume.getPath());
-        mVolumeStates.remove(volume.getPath());
-    }
-
-    private StorageVolume getPrimaryPhysicalVolume() {
-        synchronized (mVolumesLock) {
-            for (StorageVolume volume : mVolumes) {
-                if (volume.isPrimary() && !volume.isEmulated()) {
-                    return volume;
-                }
-            }
-        }
-        return null;
-    }
-
     /**
      * Constructs a new MountService instance
      *
@@ -1499,10 +894,7 @@
         sSelf = this;
 
         mContext = context;
-
-        synchronized (mVolumesLock) {
-            readStorageListLocked();
-        }
+        mCallbacks = new Callbacks(FgThread.get().getLooper());
 
         // XXX: This will go away soon in favor of IMountServiceObserver
         mPms = (PackageManagerService) ServiceManager.getService("package");
@@ -1511,19 +903,6 @@
         hthread.start();
         mHandler = new MountServiceHandler(hthread.getLooper());
 
-        // Watch for user changes
-        final IntentFilter userFilter = new IntentFilter();
-        userFilter.addAction(Intent.ACTION_USER_ADDED);
-        userFilter.addAction(Intent.ACTION_USER_REMOVED);
-        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
-
-        // Watch for USB changes on primary volume
-        final StorageVolume primary = getPrimaryPhysicalVolume();
-        if (primary != null && primary.allowMassStorage()) {
-            mContext.registerReceiver(
-                    mUsbReceiver, new IntentFilter(UsbManager.ACTION_USB_STATE), null, mHandler);
-        }
-
         // Add OBB Action Handler to MountService thread.
         mObbActionHandler = new ObbActionHandler(IoThread.get().getLooper());
 
@@ -1550,6 +929,7 @@
          */
         mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
                 null);
+        mConnector.setDebug(true);
 
         Thread thread = new Thread(mConnector, VOLD_TAG);
         thread.start();
@@ -1569,225 +949,158 @@
      * Exposed API calls below here
      */
 
+    @Override
     public void registerListener(IMountServiceListener listener) {
-        synchronized (mListeners) {
-            MountServiceBinderListener bl = new MountServiceBinderListener(listener);
-            try {
-                listener.asBinder().linkToDeath(bl, 0);
-                mListeners.add(bl);
-            } catch (RemoteException rex) {
-                Slog.e(TAG, "Failed to link to listener death");
-            }
-        }
+        mCallbacks.register(listener);
     }
 
+    @Override
     public void unregisterListener(IMountServiceListener listener) {
-        synchronized (mListeners) {
-            for(MountServiceBinderListener bl : mListeners) {
-                if (bl.mListener.asBinder() == listener.asBinder()) {
-                    mListeners.remove(mListeners.indexOf(bl));
-                    listener.asBinder().unlinkToDeath(bl, 0);
-                    return;
-                }
-            }
-        }
+        mCallbacks.unregister(listener);
     }
 
+    @Override
     public void shutdown(final IMountShutdownObserver observer) {
-        validatePermission(android.Manifest.permission.SHUTDOWN);
+        enforcePermission(android.Manifest.permission.SHUTDOWN);
 
         Slog.i(TAG, "Shutting down");
-        synchronized (mVolumesLock) {
-            // Get all volumes to be unmounted.
-            MountShutdownLatch mountShutdownLatch = new MountShutdownLatch(observer,
-                                                            mVolumeStates.size());
-
-            for (String path : mVolumeStates.keySet()) {
-                String state = mVolumeStates.get(path);
-
-                if (state.equals(Environment.MEDIA_SHARED)) {
-                    /*
-                     * If the media is currently shared, unshare it.
-                     * XXX: This is still dangerous!. We should not
-                     * be rebooting at *all* if UMS is enabled, since
-                     * the UMS host could have dirty FAT cache entries
-                     * yet to flush.
-                     */
-                    setUsbMassStorageEnabled(false);
-                } else if (state.equals(Environment.MEDIA_CHECKING)) {
-                    /*
-                     * If the media is being checked, then we need to wait for
-                     * it to complete before being able to proceed.
-                     */
-                    // XXX: @hackbod - Should we disable the ANR timer here?
-                    int retries = 30;
-                    while (state.equals(Environment.MEDIA_CHECKING) && (retries-- >=0)) {
-                        try {
-                            Thread.sleep(1000);
-                        } catch (InterruptedException iex) {
-                            Slog.e(TAG, "Interrupted while waiting for media", iex);
-                            break;
-                        }
-                        state = Environment.getExternalStorageState();
-                    }
-                    if (retries == 0) {
-                        Slog.e(TAG, "Timed out waiting for media to check");
-                    }
-                }
-
-                if (state.equals(Environment.MEDIA_MOUNTED)) {
-                    // Post a unmount message.
-                    ShutdownCallBack ucb = new ShutdownCallBack(path, mountShutdownLatch);
-                    mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb));
-                } else if (observer != null) {
-                    /*
-                     * Count down, since nothing will be done. The observer will be
-                     * notified when we are done so shutdown sequence can continue.
-                     */
-                    mountShutdownLatch.countDown();
-                    Slog.i(TAG, "Unmount completed: " + path +
-                        ", result code: " + StorageResultCode.OperationSucceeded);
-                }
-            }
-        }
+        mHandler.obtainMessage(H_SHUTDOWN, observer).sendToTarget();
     }
 
-    private boolean getUmsEnabling() {
-        synchronized (mListeners) {
-            return mUmsEnabling;
-        }
-    }
-
-    private void setUmsEnabling(boolean enable) {
-        synchronized (mListeners) {
-            mUmsEnabling = enable;
-        }
-    }
-
+    @Override
     public boolean isUsbMassStorageConnected() {
-        waitForReady();
-
-        if (getUmsEnabling()) {
-            return true;
-        }
-        synchronized (mListeners) {
-            return mUmsAvailable;
-        }
+        throw new UnsupportedOperationException();
     }
 
+    @Override
     public void setUsbMassStorageEnabled(boolean enable) {
-        waitForReady();
-        validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
-        validateUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER);
-
-        final StorageVolume primary = getPrimaryPhysicalVolume();
-        if (primary == null) return;
-
-        // TODO: Add support for multiple share methods
-
-        /*
-         * If the volume is mounted and we're enabling then unmount it
-         */
-        String path = primary.getPath();
-        String vs = getVolumeState(path);
-        String method = "ums";
-        if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
-            // Override for isUsbMassStorageEnabled()
-            setUmsEnabling(enable);
-            UmsEnableCallBack umscb = new UmsEnableCallBack(path, method, true);
-            mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, umscb));
-            // Clear override
-            setUmsEnabling(false);
-        }
-        /*
-         * If we disabled UMS then mount the volume
-         */
-        if (!enable) {
-            doShareUnshareVolume(path, method, enable);
-            if (doMountVolume(path) != StorageResultCode.OperationSucceeded) {
-                Slog.e(TAG, "Failed to remount " + path +
-                        " after disabling share method " + method);
-                /*
-                 * Even though the mount failed, the unshare didn't so don't indicate an error.
-                 * The mountVolume() call will have set the storage state and sent the necessary
-                 * broadcasts.
-                 */
-            }
-        }
+        throw new UnsupportedOperationException();
     }
 
+    @Override
     public boolean isUsbMassStorageEnabled() {
-        waitForReady();
-
-        final StorageVolume primary = getPrimaryPhysicalVolume();
-        if (primary != null) {
-            return doGetVolumeShared(primary.getPath(), "ums");
-        } else {
-            return false;
-        }
+        throw new UnsupportedOperationException();
     }
 
-    /**
-     * @return state of the volume at the specified mount point
-     */
+    @Override
     public String getVolumeState(String mountPoint) {
-        synchronized (mVolumesLock) {
-            String state = mVolumeStates.get(mountPoint);
-            if (state == null) {
-                Slog.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume");
-                if (SystemProperties.get("vold.encrypt_progress").length() != 0) {
-                    state = Environment.MEDIA_REMOVED;
-                } else {
-                    throw new IllegalArgumentException();
-                }
-            }
-
-            return state;
-        }
+        throw new UnsupportedOperationException();
     }
 
     @Override
     public boolean isExternalStorageEmulated() {
-        return mEmulatedTemplate != null;
+        throw new UnsupportedOperationException();
     }
 
+    @Override
     public int mountVolume(String path) {
-        validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
-        waitForReady();
-        return doMountVolume(path);
+        mount(findVolumeIdForPath(path));
+        return 0;
     }
 
+    @Override
     public void unmountVolume(String path, boolean force, boolean removeEncryption) {
-        validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
-        waitForReady();
-
-        String volState = getVolumeState(path);
-        if (DEBUG_UNMOUNT) {
-            Slog.i(TAG, "Unmounting " + path
-                    + " force = " + force
-                    + " removeEncryption = " + removeEncryption);
-        }
-        if (Environment.MEDIA_UNMOUNTED.equals(volState) ||
-                Environment.MEDIA_REMOVED.equals(volState) ||
-                Environment.MEDIA_SHARED.equals(volState) ||
-                Environment.MEDIA_UNMOUNTABLE.equals(volState)) {
-            // Media already unmounted or cannot be unmounted.
-            // TODO return valid return code when adding observer call back.
-            return;
-        }
-        UnmountCallBack ucb = new UnmountCallBack(path, force, removeEncryption);
-        mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb));
+        unmount(findVolumeIdForPath(path));
     }
 
+    @Override
     public int formatVolume(String path) {
-        validatePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
-        waitForReady();
-
-        return doFormatVolume(path);
+        format(findVolumeIdForPath(path));
+        return 0;
     }
 
+    @Override
+    public void mount(String volId) {
+        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
+        waitForReady();
+
+        final VolumeInfo vol = findVolumeById(volId);
+        if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
+            enforceUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
+        }
+        try {
+            mConnector.execute("volume", "mount", vol.id, vol.flags, vol.userId);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void unmount(String volId) {
+        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
+        waitForReady();
+
+        final VolumeInfo vol = findVolumeById(volId);
+
+        // TODO: expand PMS to know about multiple volumes
+        if (vol.isPrimary()) {
+            synchronized (mUnmountLock) {
+                mUnmountSignal = new CountDownLatch(1);
+                mPms.updateExternalMediaStatus(false, true);
+                waitForLatch(mUnmountSignal, "mUnmountSignal");
+                mUnmountSignal = null;
+            }
+        }
+
+        try {
+            mConnector.execute("volume", "unmount", vol.id);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void format(String volId) {
+        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
+        waitForReady();
+
+        final VolumeInfo vol = findVolumeById(volId);
+        try {
+            mConnector.execute("volume", "format", vol.id);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void partitionPublic(String diskId) {
+        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
+        waitForReady();
+
+        try {
+            mConnector.execute("volume", "partition", diskId, "public");
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void partitionPrivate(String diskId) {
+        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
+        waitForReady();
+
+        try {
+            mConnector.execute("volume", "partition", diskId, "private");
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
+    public void partitionMixed(String diskId, int ratio) {
+        enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
+        waitForReady();
+
+        try {
+            mConnector.execute("volume", "partition", diskId, "mixed", ratio);
+        } catch (NativeDaemonConnectorException e) {
+            throw e.rethrowAsParcelableException();
+        }
+    }
+
+    @Override
     public int[] getStorageUsers(String path) {
-        validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
+        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
         waitForReady();
         try {
             final String[] r = NativeDaemonEvent.filterMessageList(
@@ -1813,22 +1126,21 @@
     }
 
     private void warnOnNotMounted() {
-        final StorageVolume primary = getPrimaryPhysicalVolume();
-        if (primary != null) {
-            boolean mounted = false;
-            try {
-                mounted = Environment.MEDIA_MOUNTED.equals(getVolumeState(primary.getPath()));
-            } catch (IllegalArgumentException e) {
-            }
-
-            if (!mounted) {
-                Slog.w(TAG, "getSecureContainerList() called when storage not mounted");
+        synchronized (mLock) {
+            for (int i = 0; i < mVolumes.size(); i++) {
+                final VolumeInfo vol = mVolumes.valueAt(i);
+                if (vol.isPrimary() && vol.state == VolumeInfo.STATE_MOUNTED) {
+                    // Cool beans, we have a mounted primary volume
+                    return;
+                }
             }
         }
+
+        Slog.w(TAG, "No primary storage mounted!");
     }
 
     public String[] getSecureContainerList() {
-        validatePermission(android.Manifest.permission.ASEC_ACCESS);
+        enforcePermission(android.Manifest.permission.ASEC_ACCESS);
         waitForReady();
         warnOnNotMounted();
 
@@ -1842,7 +1154,7 @@
 
     public int createSecureContainer(String id, int sizeMb, String fstype, String key,
             int ownerUid, boolean external) {
-        validatePermission(android.Manifest.permission.ASEC_CREATE);
+        enforcePermission(android.Manifest.permission.ASEC_CREATE);
         waitForReady();
         warnOnNotMounted();
 
@@ -1864,7 +1176,7 @@
 
     @Override
     public int resizeSecureContainer(String id, int sizeMb, String key) {
-        validatePermission(android.Manifest.permission.ASEC_CREATE);
+        enforcePermission(android.Manifest.permission.ASEC_CREATE);
         waitForReady();
         warnOnNotMounted();
 
@@ -1878,7 +1190,7 @@
     }
 
     public int finalizeSecureContainer(String id) {
-        validatePermission(android.Manifest.permission.ASEC_CREATE);
+        enforcePermission(android.Manifest.permission.ASEC_CREATE);
         warnOnNotMounted();
 
         int rc = StorageResultCode.OperationSucceeded;
@@ -1895,7 +1207,7 @@
     }
 
     public int fixPermissionsSecureContainer(String id, int gid, String filename) {
-        validatePermission(android.Manifest.permission.ASEC_CREATE);
+        enforcePermission(android.Manifest.permission.ASEC_CREATE);
         warnOnNotMounted();
 
         int rc = StorageResultCode.OperationSucceeded;
@@ -1912,7 +1224,7 @@
     }
 
     public int destroySecureContainer(String id, boolean force) {
-        validatePermission(android.Manifest.permission.ASEC_DESTROY);
+        enforcePermission(android.Manifest.permission.ASEC_DESTROY);
         waitForReady();
         warnOnNotMounted();
 
@@ -1952,7 +1264,7 @@
     }
 
     public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly) {
-        validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
+        enforcePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
         waitForReady();
         warnOnNotMounted();
 
@@ -1982,7 +1294,7 @@
     }
 
     public int unmountSecureContainer(String id, boolean force) {
-        validatePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
+        enforcePermission(android.Manifest.permission.ASEC_MOUNT_UNMOUNT);
         waitForReady();
         warnOnNotMounted();
 
@@ -2025,7 +1337,7 @@
     }
 
     public boolean isSecureContainerMounted(String id) {
-        validatePermission(android.Manifest.permission.ASEC_ACCESS);
+        enforcePermission(android.Manifest.permission.ASEC_ACCESS);
         waitForReady();
         warnOnNotMounted();
 
@@ -2035,7 +1347,7 @@
     }
 
     public int renameSecureContainer(String oldId, String newId) {
-        validatePermission(android.Manifest.permission.ASEC_RENAME);
+        enforcePermission(android.Manifest.permission.ASEC_RENAME);
         waitForReady();
         warnOnNotMounted();
 
@@ -2060,7 +1372,7 @@
     }
 
     public String getSecureContainerPath(String id) {
-        validatePermission(android.Manifest.permission.ASEC_ACCESS);
+        enforcePermission(android.Manifest.permission.ASEC_ACCESS);
         waitForReady();
         warnOnNotMounted();
 
@@ -2081,7 +1393,7 @@
     }
 
     public String getSecureContainerFilesystemPath(String id) {
-        validatePermission(android.Manifest.permission.ASEC_ACCESS);
+        enforcePermission(android.Manifest.permission.ASEC_ACCESS);
         waitForReady();
         warnOnNotMounted();
 
@@ -2101,8 +1413,13 @@
         }
     }
 
+    @Override
     public void finishMediaUpdate() {
-        mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE);
+        if (mUnmountSignal != null) {
+            mUnmountSignal.countDown();
+        } else {
+            Slog.w(TAG, "Odd, nobody asked to unmount?");
+        }
     }
 
     private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) {
@@ -2477,108 +1794,101 @@
                 Context.APP_OPS_SERVICE);
         appOps.checkPackage(Binder.getCallingUid(), callingPkg);
 
+        File appFile = null;
         try {
-            appPath = new File(appPath).getCanonicalPath();
+            appFile = new File(appPath).getCanonicalFile();
         } catch (IOException e) {
             Slog.e(TAG, "Failed to resolve " + appPath + ": " + e);
             return -1;
         }
 
-        if (!appPath.endsWith("/")) {
-            appPath = appPath + "/";
-        }
-
         // Try translating the app path into a vold path, but require that it
         // belong to the calling package.
-        String voldPath = maybeTranslatePathForVold(appPath,
-                userEnv.buildExternalStorageAppDataDirs(callingPkg),
-                userEnv.buildExternalStorageAppDataDirsForVold(callingPkg));
-        if (voldPath != null) {
+        if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
+                FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
+                FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
+            appPath = appFile.getAbsolutePath();
+            if (!appPath.endsWith("/")) {
+                appPath = appPath + "/";
+            }
+
             try {
-                mConnector.execute("volume", "mkdirs", voldPath);
+                mConnector.execute("volume", "mkdirs", appPath);
                 return 0;
             } catch (NativeDaemonConnectorException e) {
                 return e.getCode();
             }
         }
 
-        voldPath = maybeTranslatePathForVold(appPath,
-                userEnv.buildExternalStorageAppObbDirs(callingPkg),
-                userEnv.buildExternalStorageAppObbDirsForVold(callingPkg));
-        if (voldPath != null) {
-            try {
-                mConnector.execute("volume", "mkdirs", voldPath);
-                return 0;
-            } catch (NativeDaemonConnectorException e) {
-                return e.getCode();
-            }
-        }
-
-        voldPath = maybeTranslatePathForVold(appPath,
-                userEnv.buildExternalStorageAppMediaDirs(callingPkg),
-                userEnv.buildExternalStorageAppMediaDirsForVold(callingPkg));
-        if (voldPath != null) {
-            try {
-                mConnector.execute("volume", "mkdirs", voldPath);
-                return 0;
-            } catch (NativeDaemonConnectorException e) {
-                return e.getCode();
-            }
-        }
-
-        throw new SecurityException("Invalid mkdirs path: " + appPath);
-    }
-
-    /**
-     * Translate the given path from an app-visible path to a vold-visible path,
-     * but only if it's under the given whitelisted paths.
-     *
-     * @param path a canonicalized app-visible path.
-     * @param appPaths list of app-visible paths that are allowed.
-     * @param voldPaths list of vold-visible paths directly corresponding to the
-     *            allowed app-visible paths argument.
-     * @return a vold-visible path representing the original path, or
-     *         {@code null} if the given path didn't have an app-to-vold
-     *         mapping.
-     */
-    @VisibleForTesting
-    public static String maybeTranslatePathForVold(
-            String path, File[] appPaths, File[] voldPaths) {
-        if (appPaths.length != voldPaths.length) {
-            throw new IllegalStateException("Paths must be 1:1 mapping");
-        }
-
-        for (int i = 0; i < appPaths.length; i++) {
-            final String appPath = appPaths[i].getAbsolutePath() + "/";
-            if (path.startsWith(appPath)) {
-                path = new File(voldPaths[i], path.substring(appPath.length()))
-                        .getAbsolutePath();
-                if (!path.endsWith("/")) {
-                    path = path + "/";
-                }
-                return path;
-            }
-        }
-        return null;
+        throw new SecurityException("Invalid mkdirs path: " + appFile);
     }
 
     @Override
-    public StorageVolume[] getVolumeList() {
-        final int callingUserId = UserHandle.getCallingUserId();
-        final boolean accessAll = (mContext.checkPermission(
-                android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
-                Binder.getCallingPid(), Binder.getCallingUid()) == PERMISSION_GRANTED);
+    public StorageVolume[] getVolumeList(int userId) {
+        final ArrayList<StorageVolume> res = new ArrayList<>();
+        boolean foundPrimary = false;
 
-        synchronized (mVolumesLock) {
-            final ArrayList<StorageVolume> filtered = Lists.newArrayList();
-            for (StorageVolume volume : mVolumes) {
-                final UserHandle owner = volume.getOwner();
-                final boolean ownerMatch = owner == null || owner.getIdentifier() == callingUserId;
-                if (accessAll || ownerMatch) {
-                    filtered.add(volume);
+        synchronized (mLock) {
+            for (int i = 0; i < mVolumes.size(); i++) {
+                final VolumeInfo vol = mVolumes.valueAt(i);
+                if (vol.isVisibleToUser(userId)) {
+                    final StorageVolume userVol = vol.buildStorageVolume(mContext, userId);
+                    if (vol.isPrimary()) {
+                        res.add(0, userVol);
+                        foundPrimary = true;
+                    } else {
+                        res.add(userVol);
+                    }
                 }
             }
-            return filtered.toArray(new StorageVolume[filtered.size()]);
+        }
+
+        if (!foundPrimary) {
+            Log.w(TAG, "No primary storage defined yet; hacking together a stub");
+
+            final boolean primaryPhysical = SystemProperties.getBoolean(
+                    StorageManager.PROP_PRIMARY_PHYSICAL, false);
+
+            final String id = "stub_primary";
+            final File path = Environment.getLegacyExternalStorageDirectory();
+            final String description = mContext.getString(android.R.string.unknownName);
+            final boolean primary = true;
+            final boolean removable = primaryPhysical;
+            final boolean emulated = !primaryPhysical;
+            final long mtpReserveSize = 0L;
+            final boolean allowMassStorage = false;
+            final long maxFileSize = 0L;
+            final UserHandle owner = new UserHandle(userId);
+            final String uuid = null;
+            final String state = Environment.MEDIA_REMOVED;
+
+            res.add(0, new StorageVolume(id, MtpStorage.getStorageIdForIndex(0), path,
+                    description, primary, removable, emulated, mtpReserveSize,
+                    allowMassStorage, maxFileSize, owner, uuid, state));
+        }
+
+        return res.toArray(new StorageVolume[res.size()]);
+    }
+
+    @Override
+    public DiskInfo[] getDisks() {
+        synchronized (mLock) {
+            final DiskInfo[] res = new DiskInfo[mDisks.size()];
+            for (int i = 0; i < mDisks.size(); i++) {
+                res[i] = mDisks.valueAt(i);
+            }
+            return res;
+        }
+    }
+
+    @Override
+    public VolumeInfo[] getVolumes() {
+        synchronized (mLock) {
+            final VolumeInfo[] res = new VolumeInfo[mVolumes.size()];
+            for (int i = 0; i < mVolumes.size(); i++) {
+                res[i] = mVolumes.valueAt(i);
+            }
+            return res;
         }
     }
 
@@ -3073,20 +2383,78 @@
         if (path.startsWith(obbPath)) {
             path = path.substring(obbPath.length() + 1);
 
-            if (forVold) {
-                return new File(Environment.getEmulatedStorageObbSource(), path).getAbsolutePath();
-            } else {
-                final UserEnvironment ownerEnv = new UserEnvironment(UserHandle.USER_OWNER);
-                return new File(ownerEnv.buildExternalStorageAndroidObbDirs()[0], path)
-                        .getAbsolutePath();
-            }
+            final UserEnvironment ownerEnv = new UserEnvironment(UserHandle.USER_OWNER);
+            return new File(ownerEnv.buildExternalStorageAndroidObbDirs()[0], path)
+                    .getAbsolutePath();
         }
 
         // Handle normal external storage paths
-        if (forVold) {
-            return new File(Environment.getEmulatedStorageSource(userId), path).getAbsolutePath();
-        } else {
-            return new File(userEnv.getExternalDirsForApp()[0], path).getAbsolutePath();
+        return new File(userEnv.getExternalStorageDirectory(), path).getAbsolutePath();
+    }
+
+    private static class Callbacks extends Handler {
+        private static final int MSG_STORAGE_STATE_CHANGED = 1;
+        private static final int MSG_VOLUME_STATE_CHANGED = 2;
+
+        private final RemoteCallbackList<IMountServiceListener>
+                mCallbacks = new RemoteCallbackList<>();
+
+        public Callbacks(Looper looper) {
+            super(looper);
+        }
+
+        public void register(IMountServiceListener callback) {
+            mCallbacks.register(callback);
+        }
+
+        public void unregister(IMountServiceListener callback) {
+            mCallbacks.unregister(callback);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            final SomeArgs args = (SomeArgs) msg.obj;
+            final int n = mCallbacks.beginBroadcast();
+            for (int i = 0; i < n; i++) {
+                final IMountServiceListener callback = mCallbacks.getBroadcastItem(i);
+                try {
+                    invokeCallback(callback, msg.what, args);
+                } catch (RemoteException ignored) {
+                }
+            }
+            mCallbacks.finishBroadcast();
+            args.recycle();
+        }
+
+        private void invokeCallback(IMountServiceListener callback, int what, SomeArgs args)
+                throws RemoteException {
+            switch (what) {
+                case MSG_STORAGE_STATE_CHANGED: {
+                    callback.onStorageStateChanged((String) args.arg1, (String) args.arg2,
+                            (String) args.arg3);
+                    break;
+                }
+                case MSG_VOLUME_STATE_CHANGED: {
+                    callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3);
+                    break;
+                }
+            }
+        }
+
+        private void notifyStorageStateChanged(String path, String oldState, String newState) {
+            final SomeArgs args = SomeArgs.obtain();
+            args.arg1 = path;
+            args.arg2 = oldState;
+            args.arg3 = newState;
+            obtainMessage(MSG_STORAGE_STATE_CHANGED, args).sendToTarget();
+        }
+
+        private void notifyVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
+            final SomeArgs args = SomeArgs.obtain();
+            args.arg1 = vol;
+            args.argi2 = oldState;
+            args.argi3 = newState;
+            obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget();
         }
     }
 
@@ -3126,15 +2494,22 @@
             pw.decreaseIndent();
         }
 
-        synchronized (mVolumesLock) {
+        synchronized (mLock) {
             pw.println();
-            pw.println("mVolumes:");
+            pw.println("Disks:");
             pw.increaseIndent();
-            for (StorageVolume volume : mVolumes) {
-                pw.println(volume);
-                pw.increaseIndent();
-                pw.println("Current state: " + mVolumeStates.get(volume.getPath()));
-                pw.decreaseIndent();
+            for (int i = 0; i < mDisks.size(); i++) {
+                final DiskInfo disk = mDisks.valueAt(i);
+                disk.dump(pw);
+            }
+            pw.decreaseIndent();
+
+            pw.println();
+            pw.println("Volumes:");
+            pw.increaseIndent();
+            for (int i = 0; i < mVolumes.size(); i++) {
+                final VolumeInfo vol = mVolumes.valueAt(i);
+                vol.dump(pw);
             }
             pw.decreaseIndent();
         }
@@ -3153,6 +2528,7 @@
     }
 
     /** {@inheritDoc} */
+    @Override
     public void monitor() {
         if (mConnector != null) {
             mConnector.monitor();
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index d2dfc7b..78c7f38 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -48,8 +48,6 @@
  * {@code libsysutils} FrameworkListener protocol.
  */
 final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdog.Monitor {
-    private static final boolean LOGD = false;
-
     private final static boolean VDBG = false;
 
     private final String TAG;
@@ -58,6 +56,8 @@
     private OutputStream mOutputStream;
     private LocalLog mLocalLog;
 
+    private volatile boolean mDebug = false;
+
     private final ResponseQueue mResponseQueue;
 
     private final PowerManager.WakeLock mWakeLock;
@@ -99,6 +99,14 @@
         mLocalLog = new LocalLog(maxLogSize);
     }
 
+    /**
+     * Enable Set debugging mode, which causes messages to also be written to both
+     * {@link Slog} in addition to internal log.
+     */
+    public void setDebug(boolean debug) {
+        mDebug = debug;
+    }
+
     @Override
     public void run() {
         mCallbackHandler = new Handler(mLooper, this);
@@ -513,7 +521,7 @@
     }
 
     private void log(String logstring) {
-        if (LOGD) Slog.d(TAG, logstring);
+        if (mDebug) Slog.d(TAG, logstring);
         mLocalLog.log(logstring);
     }
 
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 97d16c0..b36f515 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -70,6 +70,7 @@
     // Limit to 100k as blocks larger than this might cause strain on Binder.
     private static final int MAX_DATA_BLOCK_SIZE = 1024 * 100;
     public static final int DIGEST_SIZE_BYTES = 32;
+    private static final String OEM_UNLOCK_PROP = "sys.oem_unlock_allowed";
 
     private final Context mContext;
     private final String mDataBlockFile;
@@ -108,11 +109,14 @@
     }
 
     private void formatIfOemUnlockEnabled() {
-        if (doGetOemUnlockEnabled()) {
+        boolean enabled = doGetOemUnlockEnabled();
+        if (enabled) {
             synchronized (mLock) {
                 formatPartitionLocked(true);
             }
         }
+
+        SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0");
     }
 
     private void enforceOemUnlockPermission() {
@@ -132,7 +136,6 @@
             throw new SecurityException("Only the Owner is allowed to change OEM unlock state");
         }
     }
-
     private int getTotalDataSizeLocked(DataInputStream inputStream) throws IOException {
         // skip over checksum
         inputStream.skipBytes(DIGEST_SIZE_BYTES);
@@ -290,6 +293,7 @@
             Slog.e(TAG, "unable to access persistent partition", e);
             return;
         } finally {
+            SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0");
             IoUtils.closeQuietly(outputStream);
         }
     }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index a64e6c3..1b32f57 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -109,7 +109,7 @@
 
     private static final int TIMEOUT_DELAY_MS = 1000 * 60;
     private static final String DATABASE_NAME = "accounts.db";
-    private static final int DATABASE_VERSION = 6;
+    private static final int DATABASE_VERSION = 7;
 
     private final Context mContext;
 
@@ -131,6 +131,8 @@
     private static final String ACCOUNTS_TYPE_COUNT = "count(type)";
     private static final String ACCOUNTS_PASSWORD = "password";
     private static final String ACCOUNTS_PREVIOUS_NAME = "previous_name";
+    private static final String ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS =
+            "last_password_entry_time_millis_epoch";
 
     private static final String TABLE_AUTHTOKENS = "authtokens";
     private static final String AUTHTOKENS_ID = "_id";
@@ -697,7 +699,8 @@
         long identityToken = clearCallingIdentity();
         try {
             new Session(fromAccounts, response, account.type, false,
-                    false /* stripAuthTokenFromResult */) {
+                    false /* stripAuthTokenFromResult */, account.name,
+                    false /* authDetailsRequired */) {
                 @Override
                 protected String toDebugString(long now) {
                     return super.toDebugString(now) + ", getAccountCredentialsForClone"
@@ -725,12 +728,43 @@
         }
     }
 
+    @Override
+    public boolean accountAuthenticated(final Account account) {
+        if (account == null) {
+            throw new IllegalArgumentException("account is null");
+        }
+        checkAuthenticateAccountsPermission(account);
+
+        final UserAccounts accounts = getUserAccountsForCaller();
+        int userId = Binder.getCallingUserHandle().getIdentifier();
+        if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
+            return false;
+        }
+        synchronized (accounts.cacheLock) {
+            final ContentValues values = new ContentValues();
+            values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, System.currentTimeMillis());
+            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
+            int i = db.update(
+                    TABLE_ACCOUNTS,
+                    values,
+                    ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
+                    new String[] {
+                            account.name, account.type
+                    });
+            if (i > 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void completeCloningAccount(IAccountManagerResponse response,
             final Bundle accountCredentials, final Account account, final UserAccounts targetUser) {
         long id = clearCallingIdentity();
         try {
             new Session(targetUser, response, account.type, false,
-                    false /* stripAuthTokenFromResult */) {
+                    false /* stripAuthTokenFromResult */, account.name,
+                    false /* authDetailsRequired */) {
                 @Override
                 protected String toDebugString(long now) {
                     return super.toDebugString(now) + ", getAccountCredentialsForClone"
@@ -795,6 +829,7 @@
                 values.put(ACCOUNTS_NAME, account.name);
                 values.put(ACCOUNTS_TYPE, account.type);
                 values.put(ACCOUNTS_PASSWORD, password);
+                values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, System.currentTimeMillis());
                 long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
                 if (accountId < 0) {
                     Log.w(TAG, "insertAccountIntoDatabase: " + account
@@ -885,7 +920,8 @@
         public TestFeaturesSession(UserAccounts accounts, IAccountManagerResponse response,
                 Account account, String[] features) {
             super(accounts, response, account.type, false /* expectActivityLaunch */,
-                    true /* stripAuthTokenFromResult */);
+                    true /* stripAuthTokenFromResult */, account.name,
+                    false /* authDetailsRequired */);
             mFeatures = features;
             mAccount = account;
         }
@@ -1184,7 +1220,8 @@
         public RemoveAccountSession(UserAccounts accounts, IAccountManagerResponse response,
                 Account account, boolean expectActivityLaunch) {
             super(accounts, response, account.type, expectActivityLaunch,
-                    true /* stripAuthTokenFromResult */);
+                    true /* stripAuthTokenFromResult */, account.name,
+                    false /* authDetailsRequired */);
             mAccount = account;
         }
 
@@ -1419,6 +1456,13 @@
             try {
                 final ContentValues values = new ContentValues();
                 values.put(ACCOUNTS_PASSWORD, password);
+                long time = 0;
+                // Only set current time, if it is a valid password. For clear password case, it
+                // should not be set.
+                if (password != null) {
+                    time = System.currentTimeMillis();
+                }
+                values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, time);
                 final long accountId = getAccountIdLocked(db, account);
                 if (accountId >= 0) {
                     final String[] argsAccountId = {String.valueOf(accountId)};
@@ -1547,8 +1591,9 @@
         UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
         long identityToken = clearCallingIdentity();
         try {
-            new Session(accounts, response, accountType, false,
-                    false /* stripAuthTokenFromResult */) {
+            new Session(accounts, response, accountType, false /* expectActivityLaunch */,
+                    false /* stripAuthTokenFromResult */,  null /* accountName */,
+                    false /* authDetailsRequired */) {
                 @Override
                 protected String toDebugString(long now) {
                     return super.toDebugString(now) + ", getAuthTokenLabel"
@@ -1648,7 +1693,8 @@
             }
 
             new Session(accounts, response, account.type, expectActivityLaunch,
-                    false /* stripAuthTokenFromResult */) {
+                    false /* stripAuthTokenFromResult */, account.name,
+                    false /* authDetailsRequired */) {
                 @Override
                 protected String toDebugString(long now) {
                     if (loginOptions != null) loginOptions.keySet();
@@ -1842,7 +1888,8 @@
         long identityToken = clearCallingIdentity();
         try {
             new Session(accounts, response, accountType, expectActivityLaunch,
-                    true /* stripAuthTokenFromResult */) {
+                    true /* stripAuthTokenFromResult */, null /* accountName */,
+                    false /* authDetailsRequired */) {
                 @Override
                 public void run() throws RemoteException {
                     mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
@@ -1917,7 +1964,8 @@
         long identityToken = clearCallingIdentity();
         try {
             new Session(accounts, response, accountType, expectActivityLaunch,
-                    true /* stripAuthTokenFromResult */) {
+                    true /* stripAuthTokenFromResult */, null /* accountName */,
+                    false /* authDetailsRequired */) {
                 @Override
                 public void run() throws RemoteException {
                     mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
@@ -1973,7 +2021,8 @@
         long identityToken = clearCallingIdentity();
         try {
             new Session(accounts, response, account.type, expectActivityLaunch,
-                    true /* stripAuthTokenFromResult */) {
+                    true /* stripAuthTokenFromResult */, account.name,
+                    true /* authDetailsRequired */) {
                 @Override
                 public void run() throws RemoteException {
                     mAuthenticator.confirmCredentials(this, account, options);
@@ -2009,7 +2058,8 @@
         long identityToken = clearCallingIdentity();
         try {
             new Session(accounts, response, account.type, expectActivityLaunch,
-                    true /* stripAuthTokenFromResult */) {
+                    true /* stripAuthTokenFromResult */, account.name,
+                    false /* authDetailsRequired */) {
                 @Override
                 public void run() throws RemoteException {
                     mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions);
@@ -2045,7 +2095,8 @@
         long identityToken = clearCallingIdentity();
         try {
             new Session(accounts, response, accountType, expectActivityLaunch,
-                    true /* stripAuthTokenFromResult */) {
+                    true /* stripAuthTokenFromResult */, null /* accountName */,
+                    false /* authDetailsRequired */) {
                 @Override
                 public void run() throws RemoteException {
                     mAuthenticator.editProperties(this, mAccountType);
@@ -2071,7 +2122,8 @@
         public GetAccountsByTypeAndFeatureSession(UserAccounts accounts,
                 IAccountManagerResponse response, String type, String[] features, int callingUid) {
             super(accounts, response, type, false /* expectActivityLaunch */,
-                    true /* stripAuthTokenFromResult */);
+                    true /* stripAuthTokenFromResult */, null /* accountName */,
+                    false /* authDetailsRequired */);
             mCallingUid = callingUid;
             mFeatures = features;
         }
@@ -2437,6 +2489,9 @@
         final String mAccountType;
         final boolean mExpectActivityLaunch;
         final long mCreationTime;
+        final String mAccountName;
+        // Indicates if we need to add auth details(like last credential time)
+        final boolean mAuthDetailsRequired;
 
         public int mNumResults = 0;
         private int mNumRequestContinued = 0;
@@ -2448,7 +2503,8 @@
         protected final UserAccounts mAccounts;
 
         public Session(UserAccounts accounts, IAccountManagerResponse response, String accountType,
-                boolean expectActivityLaunch, boolean stripAuthTokenFromResult) {
+                boolean expectActivityLaunch, boolean stripAuthTokenFromResult, String accountName,
+                boolean authDetailsRequired) {
             super();
             //if (response == null) throw new IllegalArgumentException("response is null");
             if (accountType == null) throw new IllegalArgumentException("accountType is null");
@@ -2458,6 +2514,9 @@
             mAccountType = accountType;
             mExpectActivityLaunch = expectActivityLaunch;
             mCreationTime = SystemClock.elapsedRealtime();
+            mAccountName = accountName;
+            mAuthDetailsRequired = authDetailsRequired;
+
             synchronized (mSessions) {
                 mSessions.put(toString(), this);
             }
@@ -2592,6 +2651,16 @@
         public void onResult(Bundle result) {
             mNumResults++;
             Intent intent = null;
+            if (result != null && mAuthDetailsRequired) {
+                long lastAuthenticatedTime = DatabaseUtils.longForQuery(
+                        mAccounts.openHelper.getReadableDatabase(),
+                        "select " + ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS + " from " +
+                                TABLE_ACCOUNTS + " WHERE " + ACCOUNTS_NAME + "=? AND "
+                                + ACCOUNTS_TYPE + "=?",
+                        new String[]{mAccountName, mAccountType});
+                result.putLong(AccountManager.KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH,
+                        lastAuthenticatedTime);
+            }
             if (result != null
                     && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
                 /*
@@ -2798,6 +2867,7 @@
                     + ACCOUNTS_TYPE + " TEXT NOT NULL, "
                     + ACCOUNTS_PASSWORD + " TEXT, "
                     + ACCOUNTS_PREVIOUS_NAME + " TEXT, "
+                    + ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS + " INTEGER DEFAULT 0, "
                     + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))");
 
             db.execSQL("CREATE TABLE " + TABLE_AUTHTOKENS + " (  "
@@ -2833,6 +2903,11 @@
                     + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))");
         }
 
+        private void addLastSuccessfullAuthenticatedTimeColumn(SQLiteDatabase db) {
+            db.execSQL("ALTER TABLE " + TABLE_ACCOUNTS + " ADD COLUMN "
+                    + ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS + " DEFAULT 0");
+        }
+
         private void addOldAccountNameColumn(SQLiteDatabase db) {
             db.execSQL("ALTER TABLE " + TABLE_ACCOUNTS + " ADD COLUMN " + ACCOUNTS_PREVIOUS_NAME);
         }
@@ -2892,6 +2967,11 @@
                 oldVersion++;
             }
 
+            if (oldVersion == 6) {
+                addLastSuccessfullAuthenticatedTimeColumn(db);
+                oldVersion++;
+            }
+
             if (oldVersion != newVersion) {
                 Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion);
             }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3859904..e92443c 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2193,8 +2193,16 @@
             }
         }
 
-        // First clear app state from services.
-        for (int i=app.services.size()-1; i>=0; i--) {
+        // Clean up any connections this application has to other services.
+        for (int i = app.connections.size() - 1; i >= 0; i--) {
+            ConnectionRecord r = app.connections.valueAt(i);
+            removeConnectionLocked(r, app, null);
+        }
+        updateServiceConnectionActivitiesLocked(app);
+        app.connections.clear();
+
+        // Clear app state from services.
+        for (int i = app.services.size() - 1; i >= 0; i--) {
             ServiceRecord sr = app.services.valueAt(i);
             synchronized (sr.stats.getBatteryStats()) {
                 sr.stats.stopLaunchedLocked();
@@ -2254,14 +2262,6 @@
             }
         }
 
-        // Clean up any connections this application has to other services.
-        for (int i=app.connections.size()-1; i>=0; i--) {
-            ConnectionRecord r = app.connections.valueAt(i);
-            removeConnectionLocked(r, app, null);
-        }
-        updateServiceConnectionActivitiesLocked(app);
-        app.connections.clear();
-
         ServiceMap smap = getServiceMap(app.userId);
 
         // Now do remaining service cleanup.
@@ -2294,7 +2294,7 @@
                 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
                         sr.userId, sr.crashCount, sr.shortName, app.pid);
                 bringDownServiceLocked(sr);
-            } else if (!allowRestart) {
+            } else if (!allowRestart || !mAm.isUserRunningLocked(sr.userId, false)) {
                 bringDownServiceLocked(sr);
             } else {
                 boolean canceled = scheduleServiceRestartLocked(sr, true);
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index fd4974e..d64e39f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -72,7 +72,8 @@
     static final boolean DEBUG_TRANSITION = DEBUG_ALL || false;
     static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false;
     static final boolean DEBUG_USER_LEAVING = DEBUG_ALL || false;
-    static final boolean DEBUG_VISBILITY = DEBUG_ALL || false;
+    static final boolean DEBUG_VISIBILITY = DEBUG_ALL || false;
+    static final boolean DEBUG_USAGE_STATS = DEBUG_ALL || false;
 
     static final String POSTFIX_BACKUP = (APPEND_CATEGORY_NAME) ? "_Backup" : "";
     static final String POSTFIX_BROADCAST = (APPEND_CATEGORY_NAME) ? "_Broadcast" : "";
@@ -80,11 +81,29 @@
     static final String POSTFIX_CONFIGURATION = (APPEND_CATEGORY_NAME) ? "_Configuration" : "";
     static final String POSTFIX_FOCUS = (APPEND_CATEGORY_NAME) ? "_Focus" : "";
     static final String POSTFIX_IMMERSIVE = (APPEND_CATEGORY_NAME) ? "_Immersive" : "";
+    static final String POSTFIX_LOCKSCREEN = (APPEND_CATEGORY_NAME) ? "_LOCKSCREEN" : "";
     static final String POSTFIX_LRU = (APPEND_CATEGORY_NAME) ? "_LRU" : "";
     static final String POSTFIX_MU = "_MU";
     static final String POSTFIX_OOM_ADJ = (APPEND_CATEGORY_NAME) ? "_OomAdj" : "";
+    static final String POSTFIX_PAUSE = (APPEND_CATEGORY_NAME) ? "_Pause" : "";
+    static final String POSTFIX_POWER = (APPEND_CATEGORY_NAME) ? "_Power" : "";
+    static final String POSTFIX_PROCESS_OBSERVERS = (APPEND_CATEGORY_NAME)
+            ? "_ProcessObservers" : "";
+    static final String POSTFIX_PROCESSES = (APPEND_CATEGORY_NAME) ? "_Processes" : "";
+    static final String POSTFIX_PROVIDER = (APPEND_CATEGORY_NAME) ? "_Provider" : "";
+    static final String POSTFIX_PSS = (APPEND_CATEGORY_NAME) ? "_Pss" : "";
+    static final String POSTFIX_RESULTS = (APPEND_CATEGORY_NAME) ? "_Results" : "";
+    static final String POSTFIX_RECENTS = (APPEND_CATEGORY_NAME) ? "_Recents" : "";
     static final String POSTFIX_SERVICE = (APPEND_CATEGORY_NAME) ? "_Service" : "";
     static final String POSTFIX_SERVICE_EXECUTING =
             (APPEND_CATEGORY_NAME) ? "_ServiceExecuting" : "";
+    static final String POSTFIX_STACK = (APPEND_CATEGORY_NAME) ? "_Stack" : "";
+    static final String POSTFIX_SWITCH = (APPEND_CATEGORY_NAME) ? "_Switch" : "";
+    static final String POSTFIX_TASKS = (APPEND_CATEGORY_NAME) ? "_Tasks" : "";
+    static final String POSTFIX_THUMBNAILS = (APPEND_CATEGORY_NAME) ? "_Thumbnails" : "";
+    static final String POSTFIX_TRANSITION = (APPEND_CATEGORY_NAME) ? "_Transition" : "";
+    static final String POSTFIX_URI_PERMISSION = (APPEND_CATEGORY_NAME) ? "_UriPermission" : "";
+    static final String POSTFIX_USER_LEAVING = (APPEND_CATEGORY_NAME) ? "_UserLeaving" : "";
+    static final String POSTFIX_VISIBILITY = (APPEND_CATEGORY_NAME) ? "_Visibility" : "";
 
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 626b442..18ab3b4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -26,12 +26,12 @@
 import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
 import static com.android.internal.util.XmlUtils.writeIntAttribute;
 import static com.android.internal.util.XmlUtils.writeLongAttribute;
-import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
-import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
-import static org.xmlpull.v1.XmlPullParser.START_TAG;
 import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
 import static com.android.server.am.ActivityManagerDebugConfig.*;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
+import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
 import android.Manifest;
 import android.app.AppOpsManager;
@@ -41,8 +41,8 @@
 import android.app.IAppTask;
 import android.app.ITaskStackListener;
 import android.app.ProfilerInfo;
-import android.app.admin.DevicePolicyManager;
 import android.app.usage.UsageEvents;
+import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
 import android.content.res.Resources;
@@ -61,8 +61,8 @@
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.SparseIntArray;
-
 import android.view.Display;
+
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.DumpHeapActivity;
@@ -96,7 +96,6 @@
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.wm.AppTransition;
 import com.android.server.wm.WindowManagerService;
-
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
@@ -259,37 +258,30 @@
     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
     private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
     private static final String TAG_IMMERSIVE = TAG + POSTFIX_IMMERSIVE;
+    private static final String TAG_LOCKSCREEN = TAG + POSTFIX_LOCKSCREEN;
     private static final String TAG_LRU = TAG + POSTFIX_LRU;
     private static final String TAG_MU = TAG + POSTFIX_MU;
     private static final String TAG_OOM_ADJ = TAG + POSTFIX_OOM_ADJ;
+    private static final String TAG_POWER = TAG + POSTFIX_POWER;
+    private static final String TAG_PROCESS_OBSERVERS = TAG + POSTFIX_PROCESS_OBSERVERS;
+    private static final String TAG_PROCESSES = TAG + POSTFIX_PROCESSES;
+    private static final String TAG_PROVIDER = TAG + POSTFIX_PROVIDER;
+    private static final String TAG_PSS = TAG + POSTFIX_PSS;
+    private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
+    private static final String TAG_SERVICE = TAG + POSTFIX_SERVICE;
+    private static final String TAG_STACK = TAG + POSTFIX_STACK;
+    private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
+    private static final String TAG_URI_PERMISSION = TAG + POSTFIX_URI_PERMISSION;
+    private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
 
-    // TODO(ogunwale): Migrate all the constants below to use ActivityManagerDebugConfig class.
-    static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
-    static final boolean DEBUG_POWER = DEBUG_ALL || false;
-    static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
-    static final boolean DEBUG_PROCESS_OBSERVERS = DEBUG_ALL || false;
-    static final boolean DEBUG_PROCESSES = DEBUG_ALL || false;
-    static final boolean DEBUG_PROVIDER = DEBUG_ALL || false;
-    static final boolean DEBUG_RESULTS = DEBUG_ALL || false;
-    static final boolean DEBUG_SERVICE = DEBUG_ALL || false;
-    static final boolean DEBUG_SERVICE_EXECUTING = DEBUG_ALL || false;
-    static final boolean DEBUG_STACK = DEBUG_ALL || false;
-    static final boolean DEBUG_SWITCH = DEBUG_ALL || false;
-    static final boolean DEBUG_TASKS = DEBUG_ALL || false;
-    static final boolean DEBUG_THUMBNAILS = DEBUG_ALL || false;
-    static final boolean DEBUG_TRANSITION = DEBUG_ALL || false;
-    static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false;
-    static final boolean DEBUG_USER_LEAVING = DEBUG_ALL || false;
-    static final boolean DEBUG_VISBILITY = DEBUG_ALL || false;
-    static final boolean DEBUG_PSS = DEBUG_ALL || false;
-    static final boolean DEBUG_LOCKSCREEN = DEBUG_ALL || false;
-    static final boolean DEBUG_RECENTS = DEBUG_ALL || false;
-
-    // Control over CPU and battery monitoring.
-    static final long BATTERY_STATS_TIME = 30*60*1000;      // write battery stats every 30 minutes.
+    /** Control over CPU and battery monitoring */
+    // write battery stats every 30 minutes.
+    static final long BATTERY_STATS_TIME = 30 * 60 * 1000;
     static final boolean MONITOR_CPU_USAGE = true;
-    static final long MONITOR_CPU_MIN_TIME = 5*1000;        // don't sample cpu less than every 5 seconds.
-    static final long MONITOR_CPU_MAX_TIME = 0x0fffffff;    // wait possibly forever for next cpu sample.
+    // don't sample cpu less than every 5 seconds.
+    static final long MONITOR_CPU_MIN_TIME = 5 * 1000;
+    // wait possibly forever for next cpu sample.
+    static final long MONITOR_CPU_MAX_TIME = 0x0fffffff;
     static final boolean MONITOR_THREAD_CPU_USAGE = false;
 
     // The flags that are set for all calls we make to the package manager.
@@ -436,6 +428,11 @@
      */
     ActivityInfo mLastAddedTaskActivity;
 
+    /**
+     * List of packages whitelisted by DevicePolicyManager for locktask. Indexed by userId.
+     */
+    SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
+
     public class PendingAssistExtras extends Binder implements Runnable {
         public final ActivityRecord activity;
         public final Bundle extras;
@@ -1131,7 +1128,7 @@
     boolean mAutoStopProfiler = false;
     int mProfileType = 0;
     String mOpenGlTraceApp = null;
-    final ArrayMap<String, Long> mMemWatchProcesses = new ArrayMap<>();
+    final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>();
     String mMemWatchDumpProcName;
     String mMemWatchDumpFile;
     int mMemWatchDumpPid;
@@ -1837,18 +1834,28 @@
                 final String procName;
                 final int uid;
                 final long memLimit;
+                final String reportPackage;
                 synchronized (ActivityManagerService.this) {
                     procName = mMemWatchDumpProcName;
                     uid = mMemWatchDumpUid;
-                    Long limit = mMemWatchProcesses.get(procName);
-                    memLimit = limit != null ? limit : 0;
+                    Pair<Long, String> val = mMemWatchProcesses.get(procName, uid);
+                    if (val == null) {
+                        val = mMemWatchProcesses.get(procName, 0);
+                    }
+                    if (val != null) {
+                        memLimit = val.first;
+                        reportPackage = val.second;
+                    } else {
+                        memLimit = 0;
+                        reportPackage = null;
+                    }
                 }
                 if (procName == null) {
                     return;
                 }
 
-                if (DEBUG_PSS) Slog.d(TAG, "Showing dump heap notification from "
-                        + procName + "/" + uid);
+                if (DEBUG_PSS) Slog.d(TAG_PSS,
+                        "Showing dump heap notification from " + procName + "/" + uid);
 
                 INotificationManager inm = NotificationManager.getService();
                 if (inm == null) {
@@ -1874,6 +1881,9 @@
                 intent.setClassName("android", DumpHeapActivity.class.getName());
                 intent.putExtra(DumpHeapActivity.KEY_PROCESS, procName);
                 intent.putExtra(DumpHeapActivity.KEY_SIZE, memLimit);
+                if (reportPackage != null) {
+                    intent.putExtra(DumpHeapActivity.KEY_DIRECT_LAUNCH, reportPackage);
+                }
                 int userId = UserHandle.getUserId(uid);
                 notification.setLatestEventInfo(mContext, text,
                         mContext.getText(R.string.dump_heap_notification_detail),
@@ -1946,7 +1956,7 @@
                     }
                     memInfo.readMemInfo();
                     synchronized (ActivityManagerService.this) {
-                        if (DEBUG_PSS) Slog.d(TAG, "Collected native and kernel memory in "
+                        if (DEBUG_PSS) Slog.d(TAG_PSS, "Collected native and kernel memory in "
                                 + (SystemClock.uptimeMillis()-start) + "ms");
                         final long cachedKb = memInfo.getCachedSizeKb();
                         final long freeKb = memInfo.getFreeSizeKb();
@@ -1968,8 +1978,9 @@
                     long lastPssTime;
                     synchronized (ActivityManagerService.this) {
                         if (mPendingPssProcesses.size() <= 0) {
-                            if (mTestPssMode || DEBUG_PSS) Slog.d(TAG, "Collected PSS of " + num
-                                    + " processes in " + (SystemClock.uptimeMillis()-start) + "ms");
+                            if (mTestPssMode || DEBUG_PSS) Slog.d(TAG_PSS,
+                                    "Collected PSS of " + num + " processes in "
+                                    + (SystemClock.uptimeMillis() - start) + "ms");
                             mPendingPssProcesses.clear();
                             return;
                         }
@@ -2188,7 +2199,7 @@
         systemDir.mkdirs();
         mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
         mBatteryStatsService.getActiveStatistics().readLocked();
-        mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
+        mBatteryStatsService.scheduleWriteToDisk();
         mOnBattery = DEBUG_POWER ? true
                 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
         mBatteryStatsService.getActiveStatistics().setCallback(this);
@@ -2210,7 +2221,7 @@
         mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));
 
         mConfiguration.setToDefaults();
-        mConfiguration.locale = Locale.getDefault();
+        mConfiguration.setLocale(Locale.getDefault());
 
         mConfigurationSeq = mConfiguration.seq = 1;
         mProcessCpuTracker.init();
@@ -2432,7 +2443,7 @@
 
                 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
                     mLastWriteTime = now;
-                    mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
+                    mBatteryStatsService.scheduleWriteToDisk();
                 }
             }
         }
@@ -2480,11 +2491,19 @@
     final void setFocusedActivityLocked(ActivityRecord r, String reason) {
         if (r != null && mFocusedActivity != r) {
             if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: r=" + r);
+            ActivityRecord last = mFocusedActivity;
             mFocusedActivity = r;
             if (r.task != null && r.task.voiceInteractor != null) {
                 startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
             } else {
                 finishRunningVoiceLocked();
+                if (last != null && last.task.voiceSession != null) {
+                    // We had been in a voice interaction session, but now focused has
+                    // move to something different.  Just finish the session, we can't
+                    // return to it and retain the proper state and synchronization with
+                    // the voice interaction service.
+                    finishVoiceTask(last.task.voiceSession);
+                }
             }
             if (mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity")) {
                 mWindowManager.setFocusedApp(r.appToken, true);
@@ -2528,7 +2547,7 @@
 
     @Override
     public void notifyActivityDrawn(IBinder token) {
-        if (DEBUG_VISBILITY) Slog.d(TAG, "notifyActivityDrawn: token=" + token);
+        if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY, "notifyActivityDrawn: token=" + token);
         synchronized (this) {
             ActivityRecord r = mStackSupervisor.isInAnyStackLocked(token);
             if (r != null) {
@@ -2828,7 +2847,7 @@
         } else if (proc != null && !keepIfLarge
                 && mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
                 && proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
-            if (DEBUG_PSS) Slog.d(TAG, "May not keep " + proc + ": pss=" + proc.lastCachedPss);
+            if (DEBUG_PSS) Slog.d(TAG_PSS, "May not keep " + proc + ": pss=" + proc.lastCachedPss);
             if (proc.lastCachedPss >= mProcessList.getCachedRestoreThresholdKb()) {
                 if (proc.baseProcessTracker != null) {
                     proc.baseProcessTracker.reportCachedKill(proc.pkgList, proc.lastCachedPss);
@@ -2900,45 +2919,8 @@
         if (!isolated) {
             app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
             checkTime(startTime, "startProcess: after getProcessRecord");
-        } else {
-            // If this is an isolated process, it can't re-use an existing process.
-            app = null;
-        }
-        // We don't have to do anything more if:
-        // (1) There is an existing application record; and
-        // (2) The caller doesn't think it is dead, OR there is no thread
-        //     object attached to it so we know it couldn't have crashed; and
-        // (3) There is a pid assigned to it, so it is either starting or
-        //     already running.
-        if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
-                + " app=" + app + " knownToBeDead=" + knownToBeDead
-                + " thread=" + (app != null ? app.thread : null)
-                + " pid=" + (app != null ? app.pid : -1));
-        if (app != null && app.pid > 0) {
-            if (!knownToBeDead || app.thread == null) {
-                // We already have the app running, or are waiting for it to
-                // come up (we have a pid but not yet its thread), so keep it.
-                if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
-                // If this is a new package in the process, add the package to the list
-                app.addPackage(info.packageName, info.versionCode, mProcessStats);
-                checkTime(startTime, "startProcess: done, added package to proc");
-                return app;
-            }
 
-            // An application record is attached to a previous process,
-            // clean it up now.
-            if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG, "App died: " + app);
-            checkTime(startTime, "startProcess: bad proc running, killing");
-            Process.killProcessGroup(app.info.uid, app.pid);
-            handleAppDiedLocked(app, true, true);
-            checkTime(startTime, "startProcess: done killing old proc");
-        }
-
-        String hostingNameStr = hostingName != null
-                ? hostingName.flattenToShortString() : null;
-
-        if (!isolated) {
-            if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
+            if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
                 // If we are in the background, then check to see if this process
                 // is bad.  If so, we will just silently fail.
                 if (mBadProcesses.get(info.processName, info.uid) != null) {
@@ -2964,8 +2946,44 @@
                     }
                 }
             }
+        } else {
+            // If this is an isolated process, it can't re-use an existing process.
+            app = null;
         }
 
+        // We don't have to do anything more if:
+        // (1) There is an existing application record; and
+        // (2) The caller doesn't think it is dead, OR there is no thread
+        //     object attached to it so we know it couldn't have crashed; and
+        // (3) There is a pid assigned to it, so it is either starting or
+        //     already running.
+        if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName
+                + " app=" + app + " knownToBeDead=" + knownToBeDead
+                + " thread=" + (app != null ? app.thread : null)
+                + " pid=" + (app != null ? app.pid : -1));
+        if (app != null && app.pid > 0) {
+            if (!knownToBeDead || app.thread == null) {
+                // We already have the app running, or are waiting for it to
+                // come up (we have a pid but not yet its thread), so keep it.
+                if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
+                // If this is a new package in the process, add the package to the list
+                app.addPackage(info.packageName, info.versionCode, mProcessStats);
+                checkTime(startTime, "startProcess: done, added package to proc");
+                return app;
+            }
+
+            // An application record is attached to a previous process,
+            // clean it up now.
+            if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app);
+            checkTime(startTime, "startProcess: bad proc running, killing");
+            Process.killProcessGroup(app.info.uid, app.pid);
+            handleAppDiedLocked(app, true, true);
+            checkTime(startTime, "startProcess: done killing old proc");
+        }
+
+        String hostingNameStr = hostingName != null
+                ? hostingName.flattenToShortString() : null;
+
         if (app == null) {
             checkTime(startTime, "startProcess: creating new process record");
             app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
@@ -2994,7 +3012,8 @@
             if (!mProcessesOnHold.contains(app)) {
                 mProcessesOnHold.add(app);
             }
-            if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
+            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
+                    "System not ready, putting on hold: " + app);
             checkTime(startTime, "startProcess: returning with proc on hold");
             return app;
         }
@@ -3029,7 +3048,7 @@
             app.setPid(0);
         }
 
-        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
                 "startProcessLocked removing on hold: " + app);
         mProcessesOnHold.remove(app);
 
@@ -3041,25 +3060,14 @@
             int uid = app.uid;
 
             int[] gids = null;
-            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
+            int mountExternal = Zygote.MOUNT_EXTERNAL_DEFAULT;
             if (!app.isolated) {
                 int[] permGids = null;
                 try {
                     checkTime(startTime, "startProcess: getting gids from package manager");
-                    final PackageManager pm = mContext.getPackageManager();
-                    permGids = pm.getPackageGids(app.info.packageName);
-
-                    if (Environment.isExternalStorageEmulated()) {
-                        checkTime(startTime, "startProcess: checking external storage perm");
-                        if (pm.checkPermission(
-                                android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
-                                app.info.packageName) == PERMISSION_GRANTED) {
-                            mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
-                        } else {
-                            mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
-                        }
-                    }
-                } catch (PackageManager.NameNotFoundException e) {
+                    permGids = AppGlobals.getPackageManager().getPackageGids(app.info.packageName,
+                            app.userId);
+                } catch (RemoteException e) {
                     Slog.w(TAG, "Unable to retrieve gids", e);
                 }
 
@@ -3209,7 +3217,8 @@
     }
 
     void updateUsageStats(ActivityRecord component, boolean resumed) {
-        if (DEBUG_SWITCH) Slog.d(TAG, "updateUsageStats: comp=" + component + "res=" + resumed);
+        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH,
+                "updateUsageStats: comp=" + component + "res=" + resumed);
         final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         if (resumed) {
             if (mUsageStatsService != null) {
@@ -3427,7 +3436,8 @@
             mPendingProcessChanges.toArray(mActiveProcessChanges);
             mAvailProcessChanges.addAll(mPendingProcessChanges);
             mPendingProcessChanges.clear();
-            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "*** Delivering " + N + " process changes");
+            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                    "*** Delivering " + N + " process changes");
         }
 
         int i = mProcessObservers.beginBroadcast();
@@ -3439,15 +3449,16 @@
                     for (int j=0; j<N; j++) {
                         ProcessChangeItem item = mActiveProcessChanges[j];
                         if ((item.changes&ProcessChangeItem.CHANGE_ACTIVITIES) != 0) {
-                            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "ACTIVITIES CHANGED pid="
-                                    + item.pid + " uid=" + item.uid + ": "
-                                    + item.foregroundActivities);
+                            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                                    "ACTIVITIES CHANGED pid=" + item.pid + " uid="
+                                    + item.uid + ": " + item.foregroundActivities);
                             observer.onForegroundActivitiesChanged(item.pid, item.uid,
                                     item.foregroundActivities);
                         }
                         if ((item.changes&ProcessChangeItem.CHANGE_PROCESS_STATE) != 0) {
-                            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "PROCSTATE CHANGED pid="
-                                    + item.pid + " uid=" + item.uid + ": " + item.processState);
+                            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                                    "PROCSTATE CHANGED pid=" + item.pid + " uid=" + item.uid
+                                    + ": " + item.processState);
                             observer.onProcessStateChanged(item.pid, item.uid, item.processState);
                         }
                     }
@@ -4207,17 +4218,13 @@
             finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
         }
 
-        if (!restarting) {
-            if (!mStackSupervisor.resumeTopActivitiesLocked()) {
-                // If there was nothing to resume, and we are not already
-                // restarting this process, but there is a visible activity that
-                // is hosted by the process...  then make sure all visible
-                // activities are running, taking care of restarting this
-                // process.
-                if (hasVisibleActivities) {
-                    mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
-                }
-            }
+        if (!restarting && hasVisibleActivities && !mStackSupervisor.resumeTopActivitiesLocked()) {
+            // If there was nothing to resume, and we are not already
+            // restarting this process, but there is a visible activity that
+            // is hosted by the process...  then make sure all visible
+            // activities are running, taking care of restarting this
+            // process.
+            mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
         }
     }
 
@@ -4363,7 +4370,7 @@
                     + ") has died and restarted (pid " + app.pid + ").");
             EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName);
         } else if (DEBUG_PROCESSES) {
-            Slog.d(TAG, "Received spurious death notification for thread "
+            Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "
                     + thread.asBinder());
         }
     }
@@ -5398,9 +5405,8 @@
             boolean callerWillRestart, boolean allowRestart, String reason) {
         final String name = app.processName;
         final int uid = app.uid;
-        if (DEBUG_PROCESSES) Slog.d(
-            TAG, "Force removing proc " + app.toShortString() + " (" + name
-            + "/" + uid + ")");
+        if (DEBUG_PROCESSES) Slog.d(TAG_PROCESSES,
+            "Force removing proc " + app.toShortString() + " (" + name + "/" + uid + ")");
 
         mProcessNames.remove(name, uid);
         mIsolatedProcesses.remove(app.uid);
@@ -5644,7 +5650,7 @@
 
         // Remove this record from the list of starting applications.
         mPersistentStartingProcesses.remove(app);
-        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
                 "Attach application locked removing on hold: " + app);
         mProcessesOnHold.remove(app);
 
@@ -5852,7 +5858,7 @@
                 ArrayList<ProcessRecord> procs =
                     new ArrayList<ProcessRecord>(mProcessesOnHold);
                 for (int ip=0; ip<NP; ip++) {
-                    if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
+                    if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "Starting process on hold: "
                             + procs.get(ip));
                     startProcessLocked(procs.get(ip), "on-hold", null);
                 }
@@ -5993,7 +5999,7 @@
 
     @Override
     public final void activityDestroyed(IBinder token) {
-        if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
+        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "ACTIVITY DESTROYED: " + token);
         synchronized (this) {
             ActivityStack stack = ActivityRecord.getStackLocked(token);
             if (stack != null) {
@@ -6326,31 +6332,38 @@
         }
         try {
             PendingIntentRecord res = (PendingIntentRecord)pendingResult;
-            Intent intent = res.key.requestIntent;
-            if (intent != null) {
-                if (res.lastTag != null && res.lastTagPrefix == prefix && (res.lastTagPrefix == null
-                        || res.lastTagPrefix.equals(prefix))) {
-                    return res.lastTag;
-                }
-                res.lastTagPrefix = prefix;
-                StringBuilder sb = new StringBuilder(128);
-                if (prefix != null) {
-                    sb.append(prefix);
-                }
-                if (intent.getAction() != null) {
-                    sb.append(intent.getAction());
-                } else if (intent.getComponent() != null) {
-                    intent.getComponent().appendShortString(sb);
-                } else {
-                    sb.append("?");
-                }
-                return res.lastTag = sb.toString();
+            synchronized (this) {
+                return getTagForIntentSenderLocked(res, prefix);
             }
         } catch (ClassCastException e) {
         }
         return null;
     }
 
+    String getTagForIntentSenderLocked(PendingIntentRecord res, String prefix) {
+        final Intent intent = res.key.requestIntent;
+        if (intent != null) {
+            if (res.lastTag != null && res.lastTagPrefix == prefix && (res.lastTagPrefix == null
+                    || res.lastTagPrefix.equals(prefix))) {
+                return res.lastTag;
+            }
+            res.lastTagPrefix = prefix;
+            final StringBuilder sb = new StringBuilder(128);
+            if (prefix != null) {
+                sb.append(prefix);
+            }
+            if (intent.getAction() != null) {
+                sb.append(intent.getAction());
+            } else if (intent.getComponent() != null) {
+                intent.getComponent().appendShortString(sb);
+            } else {
+                sb.append("?");
+            }
+            return res.lastTag = sb.toString();
+        }
+        return null;
+    }
+
     @Override
     public void setProcessLimit(int max) {
         enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
@@ -6591,7 +6604,7 @@
      */
     private final boolean checkHoldingPermissionsLocked(
             IPackageManager pm, ProviderInfo pi, GrantUri grantUri, int uid, final int modeFlags) {
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG,
+        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
                 "checkHoldingPermissionsLocked: uri=" + grantUri + " uid=" + uid);
         if (UserHandle.getUserId(uid) != grantUri.sourceUserId) {
             if (ActivityManager.checkComponentPermission(INTERACT_ACROSS_USERS, uid, -1, true)
@@ -6639,8 +6652,8 @@
                     if (pp.match(path)) {
                         if (!readMet) {
                             final String pprperm = pp.getReadPermission();
-                            if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
-                                    + pprperm + " for " + pp.getPath()
+                            if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
+                                    "Checking read perm for " + pprperm + " for " + pp.getPath()
                                     + ": match=" + pp.match(path)
                                     + " check=" + pm.checkUidPermission(pprperm, uid));
                             if (pprperm != null) {
@@ -6654,8 +6667,8 @@
                         }
                         if (!writeMet) {
                             final String ppwperm = pp.getWritePermission();
-                            if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
-                                    + ppwperm + " for " + pp.getPath()
+                            if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
+                                    "Checking write perm " + ppwperm + " for " + pp.getPath()
                                     + ": match=" + pp.match(path)
                                     + " check=" + pm.checkUidPermission(ppwperm, uid));
                             if (ppwperm != null) {
@@ -6800,7 +6813,7 @@
         }
 
         if (targetPkg != null) {
-            if (DEBUG_URI_PERMISSION) Slog.v(TAG,
+            if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
                     "Checking grant " + targetPkg + " permission to " + grantUri);
         }
 
@@ -6808,7 +6821,7 @@
 
         // If this is not a content: uri, we can't do anything with it.
         if (!ContentResolver.SCHEME_CONTENT.equals(grantUri.uri.getScheme())) {
-            if (DEBUG_URI_PERMISSION) Slog.v(TAG,
+            if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
                     "Can't grant URI permission for non-content URI: " + grantUri);
             return -1;
         }
@@ -6826,7 +6839,7 @@
             try {
                 targetUid = pm.getPackageUid(targetPkg, UserHandle.getUserId(callingUid));
                 if (targetUid < 0) {
-                    if (DEBUG_URI_PERMISSION) Slog.v(TAG,
+                    if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
                             "Can't grant URI permission no uid for: " + targetPkg);
                     return -1;
                 }
@@ -6839,7 +6852,7 @@
             // First...  does the target actually need this permission?
             if (checkHoldingPermissionsLocked(pm, pi, grantUri, targetUid, modeFlags)) {
                 // No need to grant the target this permission.
-                if (DEBUG_URI_PERMISSION) Slog.v(TAG,
+                if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
                         "Target " + targetPkg + " already has full permission to " + grantUri);
                 return -1;
             }
@@ -6936,7 +6949,7 @@
         // to the uri, and the target doesn't.  Let's now give this to
         // the target.
 
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG,
+        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
                 "Granting " + targetPkg + "/" + targetUid + " permission to " + grantUri);
 
         final String authority = grantUri.uri.getAuthority();
@@ -6994,7 +7007,7 @@
      */
     NeededUriGrants checkGrantUriPermissionFromIntentLocked(int callingUid,
             String targetPkg, Intent intent, int mode, NeededUriGrants needed, int targetUserId) {
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG,
+        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
                 "Checking URI perm to data=" + (intent != null ? intent.getData() : null)
                 + " clip=" + (intent != null ? intent.getClipData() : null)
                 + " from " + intent + "; flags=0x"
@@ -7028,10 +7041,9 @@
                 return null;
             }
             if (targetUid < 0) {
-                if (DEBUG_URI_PERMISSION) {
-                    Slog.v(TAG, "Can't grant URI permission no uid for: " + targetPkg
-                            + " on user " + targetUserId);
-                }
+                if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
+                        "Can't grant URI permission no uid for: " + targetPkg
+                        + " on user " + targetUserId);
                 return null;
             }
         }
@@ -7138,7 +7150,7 @@
             final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
                     perm.targetUid);
             if (perms != null) {
-                if (DEBUG_URI_PERMISSION) Slog.v(TAG,
+                if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
                         "Removing " + perm.targetUid + " permission to " + perm.uri);
 
                 perms.remove(perm.uri);
@@ -7150,7 +7162,8 @@
     }
 
     private void revokeUriPermissionLocked(int callingUid, GrantUri grantUri, final int modeFlags) {
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Revoking all granted permissions to " + grantUri);
+        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
+                "Revoking all granted permissions to " + grantUri);
 
         final IPackageManager pm = AppGlobals.getPackageManager();
         final String authority = grantUri.uri.getAuthority();
@@ -7172,9 +7185,9 @@
                     final UriPermission perm = it.next();
                     if (perm.uri.sourceUserId == grantUri.sourceUserId
                             && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
-                        if (DEBUG_URI_PERMISSION)
-                            Slog.v(TAG, "Revoking non-owned " + perm.targetUid +
-                                    " permission to " + perm.uri);
+                        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
+                                "Revoking non-owned " + perm.targetUid
+                                + " permission to " + perm.uri);
                         persistChanged |= perm.revokeModes(
                                 modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
                         if (perm.modeFlags == 0) {
@@ -7204,8 +7217,7 @@
                 final UriPermission perm = it.next();
                 if (perm.uri.sourceUserId == grantUri.sourceUserId
                         && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) {
-                    if (DEBUG_URI_PERMISSION)
-                        Slog.v(TAG,
+                    if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
                                 "Revoking " + perm.targetUid + " permission to " + perm.uri);
                     persistChanged |= perm.revokeModes(
                             modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
@@ -7390,7 +7402,7 @@
     }
 
     private void writeGrantedUriPermissions() {
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG, "writeGrantedUriPermissions()");
+        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "writeGrantedUriPermissions()");
 
         // Snapshot permissions so we can persist without lock
         ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList();
@@ -7438,7 +7450,7 @@
     }
 
     private void readGrantedUriPermissionsLocked() {
-        if (DEBUG_URI_PERMISSION) Slog.v(TAG, "readGrantedUriPermissions()");
+        if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "readGrantedUriPermissions()");
 
         final long now = System.currentTimeMillis();
 
@@ -7616,9 +7628,8 @@
         for (int i = 0; i < trimCount; i++) {
             final UriPermission perm = persisted.get(i);
 
-            if (DEBUG_URI_PERMISSION) {
-                Slog.v(TAG, "Trimming grant created at " + perm.persistedCreateTime);
-            }
+            if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
+                    "Trimming grant created at " + perm.persistedCreateTime);
 
             perm.releasePersistableModes(~0);
             removeUriPermissionIfNeededLocked(perm);
@@ -7812,7 +7823,7 @@
         }
         if (!allowed) {
             Slog.w(TAG, caller + ": caller " + callingUid
-                    + " does not hold GET_TASKS; limiting output");
+                    + " does not hold REAL_GET_TASKS; limiting output");
         }
         return allowed;
     }
@@ -7848,7 +7859,7 @@
                 TaskRecord tr = mRecentTasks.get(i);
                 // Only add calling user or related users recent tasks
                 if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
-                    if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, not user: " + tr);
+                    if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not user: " + tr);
                     continue;
                 }
 
@@ -7867,25 +7878,27 @@
                         // If the caller doesn't have the GET_TASKS permission, then only
                         // allow them to see a small subset of tasks -- their own and home.
                         if (!tr.isHomeTask() && tr.effectiveUid != callingUid) {
-                            if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, not allowed: " + tr);
+                            if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not allowed: " + tr);
                             continue;
                         }
                     }
                     if ((flags & ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS) != 0) {
                         if (tr.stack != null && tr.stack.isHomeStack()) {
-                            if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, home stack task: " + tr);
+                            if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+                                    "Skipping, home stack task: " + tr);
                             continue;
                         }
                     }
                     if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
                         // Don't include auto remove tasks that are finished or finishing.
-                        if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, auto-remove without activity: "
-                                + tr);
+                        if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+                                "Skipping, auto-remove without activity: " + tr);
                         continue;
                     }
                     if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0
                             && !tr.isAvailable) {
-                        if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, unavail real act: " + tr);
+                        if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+                                "Skipping, unavail real act: " + tr);
                         continue;
                     }
 
@@ -8219,10 +8232,9 @@
      */
     @Override
     public void moveTaskToFront(int taskId, int flags, Bundle options) {
-        enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
-                "moveTaskToFront()");
+        enforceCallingPermission(android.Manifest.permission.REORDER_TASKS, "moveTaskToFront()");
 
-        if (DEBUG_STACK) Slog.d(TAG, "moveTaskToFront: moving taskId=" + taskId);
+        if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId);
         synchronized(this) {
             moveTaskToFrontLocked(taskId, flags, options);
         }
@@ -8382,8 +8394,8 @@
         synchronized (this) {
             long ident = Binder.clearCallingIdentity();
             try {
-                if (DEBUG_STACK) Slog.d(TAG, "moveTaskToStack: moving task=" + taskId + " to stackId="
-                        + stackId + " toTop=" + toTop);
+                if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
+                        + " to stackId=" + stackId + " toTop=" + toTop);
                 mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop);
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -8455,52 +8467,54 @@
         }
     }
 
-    private boolean isLockTaskAuthorized(String pkg) {
-        final DevicePolicyManager dpm = (DevicePolicyManager)
-                mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
-        try {
-            int uid = mContext.getPackageManager().getPackageUid(pkg,
-                    Binder.getCallingUserHandle().getIdentifier());
-            return (uid == Binder.getCallingUid()) && dpm != null && dpm.isLockTaskPermitted(pkg);
-        } catch (NameNotFoundException e) {
-            return false;
+    @Override
+    public void updateLockTaskPackages(int userId, String[] packages) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("updateLockTaskPackage called from non-system process");
+        }
+        synchronized (this) {
+            mLockTaskPackages.put(userId, packages);
         }
     }
 
-    void startLockTaskMode(TaskRecord task) {
-        final String pkg;
-        synchronized (this) {
-            pkg = task.intent.getComponent().getPackageName();
+    private boolean isLockTaskAuthorizedLocked(String pkg) {
+        String[] packages = mLockTaskPackages.get(mCurrentUserId);
+        if (packages == null) {
+            return false;
         }
+        for (int i = packages.length - 1; i >= 0; --i) {
+            if (pkg.equals(packages[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void startLockTaskModeLocked(TaskRecord task) {
+        final String pkg = task.intent.getComponent().getPackageName();
         // isSystemInitiated is used to distinguish between locked and pinned mode, as pinned mode
         // is initiated by system after the pinning request was shown and locked mode is initiated
         // by an authorized app directly
         boolean isSystemInitiated = Binder.getCallingUid() == Process.SYSTEM_UID;
-        if (!isSystemInitiated && !isLockTaskAuthorized(pkg)) {
-            StatusBarManagerInternal statusBarManager = LocalServices.getService(
-                    StatusBarManagerInternal.class);
-            if (statusBarManager != null) {
-                statusBarManager.showScreenPinningRequest();
-            }
-            return;
-        }
         long ident = Binder.clearCallingIdentity();
         try {
-            synchronized (this) {
-                // Since we lost lock on task, make sure it is still there.
-                task = mStackSupervisor.anyTaskForIdLocked(task.taskId);
-                if (task != null) {
-                    if (!isSystemInitiated
-                            && ((mStackSupervisor.getFocusedStack() == null)
-                                    || (task != mStackSupervisor.getFocusedStack().topTask()))) {
-                        throw new IllegalArgumentException("Invalid task, not in foreground");
-                    }
-                    mStackSupervisor.setLockTaskModeLocked(task, isSystemInitiated ?
-                            ActivityManager.LOCK_TASK_MODE_PINNED :
-                            ActivityManager.LOCK_TASK_MODE_LOCKED,
-                            "startLockTask");
+            if (!isSystemInitiated && !isLockTaskAuthorizedLocked(pkg)) {
+                StatusBarManagerInternal statusBarManager =
+                        LocalServices.getService(StatusBarManagerInternal.class);
+                if (statusBarManager != null) {
+                    statusBarManager.showScreenPinningRequest();
                 }
+                return;
             }
+
+            final ActivityStack stack = mStackSupervisor.getFocusedStack();
+            if (!isSystemInitiated && (stack == null || task != stack.topTask())) {
+                throw new IllegalArgumentException("Invalid task, not in foreground");
+            }
+            mStackSupervisor.setLockTaskModeLocked(task, isSystemInitiated ?
+                    ActivityManager.LOCK_TASK_MODE_PINNED :
+                    ActivityManager.LOCK_TASK_MODE_LOCKED,
+                    "startLockTask");
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -8508,37 +8522,25 @@
 
     @Override
     public void startLockTaskMode(int taskId) {
-        final TaskRecord task;
-        long ident = Binder.clearCallingIdentity();
-        try {
-            synchronized (this) {
-                task = mStackSupervisor.anyTaskForIdLocked(taskId);
+        synchronized (this) {
+            final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+            if (task != null) {
+                startLockTaskModeLocked(task);
             }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-        if (task != null) {
-            startLockTaskMode(task);
         }
     }
 
     @Override
     public void startLockTaskMode(IBinder token) {
-        final TaskRecord task;
-        long ident = Binder.clearCallingIdentity();
-        try {
-            synchronized (this) {
-                final ActivityRecord r = ActivityRecord.forTokenLocked(token);
-                if (r == null) {
-                    return;
-                }
-                task = r.task;
+        synchronized (this) {
+            final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+            if (r == null) {
+                return;
             }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-        if (task != null) {
-            startLockTaskMode(task);
+            final TaskRecord task = r.task;
+            if (task != null) {
+                startLockTaskModeLocked(task);
+            }
         }
     }
 
@@ -8548,11 +8550,12 @@
                 "startLockTaskModeOnCurrent");
         long ident = Binder.clearCallingIdentity();
         try {
-            ActivityRecord r = null;
             synchronized (this) {
-                r = mStackSupervisor.topRunningActivityLocked();
+                ActivityRecord r = mStackSupervisor.topRunningActivityLocked();
+                if (r != null) {
+                    startLockTaskModeLocked(r.task);
+                }
             }
-            startLockTaskMode(r.task);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -8794,7 +8797,7 @@
             for (int i=0; i<r.conProviders.size(); i++) {
                 ContentProviderConnection conn = r.conProviders.get(i);
                 if (conn.provider == cpr) {
-                    if (DEBUG_PROVIDER) Slog.v(TAG,
+                    if (DEBUG_PROVIDER) Slog.v(TAG_PROVIDER,
                             "Adding provider requested by "
                             + r.processName + " from process "
                             + cpr.info.processName + ": " + cpr.name.flattenToShortString()
@@ -8830,7 +8833,7 @@
             ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
         if (conn != null) {
             cpr = conn.provider;
-            if (DEBUG_PROVIDER) Slog.v(TAG,
+            if (DEBUG_PROVIDER) Slog.v(TAG_PROVIDER,
                     "Removing provider requested by "
                     + conn.client.processName + " from process "
                     + cpr.info.processName + ": " + cpr.name.flattenToShortString()
@@ -8958,7 +8961,7 @@
                     checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
                     boolean success = updateOomAdjLocked(cpr.proc);
                     checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
-                    if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success);
+                    if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
                     // NOTE: there is still a race here where a signal could be
                     // pending on the process even though we managed to update its
                     // adj level.  Not sure what to do about this, but at least
@@ -8968,8 +8971,7 @@
                         // has been killed on us.  We need to wait for a new
                         // process to be started, and make sure its death
                         // doesn't kill our process.
-                        Slog.i(TAG,
-                                "Existing provider " + cpr.name.flattenToShortString()
+                        Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
                                 + " is crashing; detaching " + r);
                         boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
                         checkTime(startTime, "getContentProviderImpl: before appDied");
@@ -9080,18 +9082,16 @@
                     return cpr.newHolder(null);
                 }
 
-                if (DEBUG_PROVIDER) {
-                    RuntimeException e = new RuntimeException("here");
-                    Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + (r != null ? r.uid : null)
-                          + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
-                }
+                if (DEBUG_PROVIDER) Slog.w(TAG_PROVIDER, "LAUNCHING REMOTE PROVIDER (myuid "
+                            + (r != null ? r.uid : null) + " pruid " + cpr.appInfo.uid + "): "
+                            + cpr.info.name + " callers=" + Debug.getCallers(6));
 
                 // This is single process, and our app is now connecting to it.
                 // See if we are already in the process of launching this
                 // provider.
                 final int N = mLaunchingProviders.size();
                 int i;
-                for (i=0; i<N; i++) {
+                for (i = 0; i < N; i++) {
                     if (mLaunchingProviders.get(i) == cpr) {
                         break;
                     }
@@ -9120,9 +9120,8 @@
                         ProcessRecord proc = getProcessRecordLocked(
                                 cpi.processName, cpr.appInfo.uid, false);
                         if (proc != null && proc.thread != null) {
-                            if (DEBUG_PROVIDER) {
-                                Slog.d(TAG, "Installing in existing process " + proc);
-                            }
+                            if (DEBUG_PROVIDER) Slog.d(TAG_PROVIDER,
+                                    "Installing in existing process " + proc);
                             if (!proc.pubProviders.containsKey(cpi.name)) {
                                 checkTime(startTime, "getContentProviderImpl: scheduling install");
                                 proc.pubProviders.put(cpi.name, cpr);
@@ -9837,7 +9836,7 @@
     }
 
     void logLockScreen(String msg) {
-        if (DEBUG_LOCKSCREEN) Slog.d(TAG, Debug.getCallers(2) + ":" + msg
+        if (DEBUG_LOCKSCREEN) Slog.d(TAG_LOCKSCREEN, Debug.getCallers(2) + ":" + msg
                 + " mLockScreenShown=" + lockScreenShownToString() + " mWakefulness="
                 + PowerManagerInternal.wakefulnessToString(mWakefulness)
                 + " mSleeping=" + mSleeping);
@@ -10479,17 +10478,21 @@
         if (!(sender instanceof PendingIntentRecord)) {
             return;
         }
-        BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+        final PendingIntentRecord rec = (PendingIntentRecord)sender;
+        final String tag;
+        synchronized (this) {
+            tag = getTagForIntentSenderLocked(rec, "*walarm*:");
+        }
+        final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         synchronized (stats) {
             if (mBatteryStatsService.isOnBattery()) {
                 mBatteryStatsService.enforceCallingPermission();
-                PendingIntentRecord rec = (PendingIntentRecord)sender;
                 int MY_UID = Binder.getCallingUid();
                 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
                 BatteryStatsImpl.Uid.Pkg pkg =
                     stats.getPackageStatsLocked(sourceUid >= 0 ? sourceUid : uid,
                             sourcePkg != null ? sourcePkg : rec.key.packageName);
-                pkg.incWakeupsLocked();
+                pkg.noteWakeupAlarmLocked(tag);
             }
         }
     }
@@ -12032,16 +12035,23 @@
 
     public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
         enforceNotIsolatedCaller("getRunningAppProcesses");
+
+        final int callingUid = Binder.getCallingUid();
+
         // Lazy instantiation of list
         List<ActivityManager.RunningAppProcessInfo> runList = null;
         final boolean allUsers = ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL,
-                Binder.getCallingUid()) == PackageManager.PERMISSION_GRANTED;
-        int userId = UserHandle.getUserId(Binder.getCallingUid());
+                callingUid) == PackageManager.PERMISSION_GRANTED;
+        final int userId = UserHandle.getUserId(callingUid);
+        final boolean allUids = isGetTasksAllowed(
+                "getRunningAppProcesses", Binder.getCallingPid(), callingUid);
+
         synchronized (this) {
             // Iterate across all processes
-            for (int i=mLruProcesses.size()-1; i>=0; i--) {
+            for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
                 ProcessRecord app = mLruProcesses.get(i);
-                if (!allUsers && app.userId != userId) {
+                if ((!allUsers && app.userId != userId)
+                        || (!allUids && app.uid != callingUid)) {
                     continue;
                 }
                 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
@@ -12065,7 +12075,7 @@
                     //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
                     //        + " lru=" + currApp.lru);
                     if (runList == null) {
-                        runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
+                        runList = new ArrayList<>();
                     }
                     runList.add(currApp);
                 }
@@ -12868,16 +12878,28 @@
                         + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
             }
         }
-        if (mMemWatchProcesses.size() > 0) {
+        if (mMemWatchProcesses.getMap().size() > 0) {
             pw.println("  Mem watch processes:");
-            for (int i=0; i<mMemWatchProcesses.size(); i++) {
-                if (needSep) {
-                    pw.println();
-                    needSep = false;
+            final ArrayMap<String, SparseArray<Pair<Long, String>>> procs
+                    = mMemWatchProcesses.getMap();
+            for (int i=0; i<procs.size(); i++) {
+                final String proc = procs.keyAt(i);
+                final SparseArray<Pair<Long, String>> uids = procs.valueAt(i);
+                for (int j=0; j<uids.size(); j++) {
+                    if (needSep) {
+                        pw.println();
+                        needSep = false;
+                    }
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("    ").append(proc).append('/');
+                    UserHandle.formatUid(sb, uids.keyAt(j));
+                    Pair<Long, String> val = uids.valueAt(i);
+                    sb.append(": "); DebugUtils.sizeValueToString(val.first, sb);
+                    if (val.second != null) {
+                        sb.append(", report to ").append(val.second);
+                    }
+                    pw.println(sb.toString());
                 }
-                pw.print("    "); pw.print(mMemWatchProcesses.keyAt(i));
-                pw.print(": "); DebugUtils.printSizeValue(pw, mMemWatchProcesses.valueAt(i));
-                pw.println();
             }
             pw.print("  mMemWatchDumpProcName="); pw.println(mMemWatchDumpProcName);
             pw.print("  mMemWatchDumpFile="); pw.println(mMemWatchDumpFile);
@@ -14905,8 +14927,8 @@
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
 
-        if (DEBUG_SERVICE)
-            Slog.v(TAG, "startService: " + service + " type=" + resolvedType);
+        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
+                "startService: " + service + " type=" + resolvedType);
         synchronized(this) {
             final int callingPid = Binder.getCallingPid();
             final int callingUid = Binder.getCallingUid();
@@ -14921,8 +14943,8 @@
     ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, int userId)
             throws TransactionTooLargeException {
         synchronized(this) {
-            if (DEBUG_SERVICE)
-                Slog.v(TAG, "startServiceInPackage: " + service + " type=" + resolvedType);
+            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
+                    "startServiceInPackage: " + service + " type=" + resolvedType);
             final long origId = Binder.clearCallingIdentity();
             ComponentName res = mServices.startServiceLocked(null, service,
                     resolvedType, -1, uid, userId);
@@ -17388,11 +17410,11 @@
      * Record new PSS sample for a process.
      */
     void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss, long now) {
-        EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss*1024, uss*1024);
+        EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024);
         proc.lastPssTime = now;
         proc.baseProcessTracker.addPss(pss, uss, true, proc.pkgList);
-        if (DEBUG_PSS) Slog.d(TAG, "PSS of " + proc.toShortString()
-                + ": " + pss + " lastPss=" + proc.lastPss
+        if (DEBUG_PSS) Slog.d(TAG_PSS,
+                "PSS of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
                 + " state=" + ProcessList.makeProcStateString(procState));
         if (proc.initialIdlePss == 0) {
             proc.initialIdlePss = pss;
@@ -17402,9 +17424,20 @@
             proc.lastCachedPss = pss;
         }
 
-        Long check = mMemWatchProcesses.get(proc.processName);
+        final SparseArray<Pair<Long, String>> watchUids
+                = mMemWatchProcesses.getMap().get(proc.processName);
+        Long check = null;
+        if (watchUids != null) {
+            Pair<Long, String> val = watchUids.get(proc.uid);
+            if (val == null) {
+                val = watchUids.get(0);
+            }
+            if (val != null) {
+                check = val.first;
+            }
+        }
         if (check != null) {
-            if ((pss*1024) >= check && proc.thread != null && mMemWatchDumpProcName == null) {
+            if ((pss * 1024) >= check && proc.thread != null && mMemWatchDumpProcName == null) {
                 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
                 if (!isDebuggable) {
                     if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
@@ -17438,7 +17471,8 @@
                                 IApplicationThread thread = myProc.thread;
                                 if (thread != null) {
                                     try {
-                                        if (DEBUG_PSS) Slog.d(TAG, "Requesting dump heap from "
+                                        if (true || DEBUG_PSS) Slog.d(TAG_PSS,
+                                                "Requesting dump heap from "
                                                 + myProc + " to " + heapdumpFile);
                                         thread.dumpHeap(true, heapdumpFile.toString(), fd);
                                     } catch (RemoteException e) {
@@ -17474,7 +17508,7 @@
         if (mPendingPssProcesses.size() == 0) {
             mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
         }
-        if (DEBUG_PSS) Slog.d(TAG, "Requesting PSS of: " + proc);
+        if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting PSS of: " + proc);
         proc.pssProcState = procState;
         mPendingPssProcesses.add(proc);
     }
@@ -17489,13 +17523,17 @@
                 return;
             }
         }
-        if (DEBUG_PSS) Slog.d(TAG, "Requesting PSS of all procs!  memLowered=" + memLowered);
+        if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting PSS of all procs!  memLowered=" + memLowered);
         mLastFullPssTime = now;
         mFullPssPending = true;
         mPendingPssProcesses.ensureCapacity(mLruProcesses.size());
         mPendingPssProcesses.clear();
-        for (int i=mLruProcesses.size()-1; i>=0; i--) {
+        for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
             ProcessRecord app = mLruProcesses.get(i);
+            if (app.thread == null
+                    || app.curProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
+                continue;
+            }
             if (memLowered || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) {
                 app.pssProcState = app.setProcState;
                 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
@@ -17701,7 +17739,7 @@
                     sb.append(" (");
                     sb.append((wtimeUsed*100)/realtimeSince);
                     sb.append("%)");
-                    Slog.i(TAG, sb.toString());
+                    Slog.i(TAG_POWER, sb.toString());
                     sb.setLength(0);
                     sb.append("CPU for ");
                     app.toShortString(sb);
@@ -17712,7 +17750,7 @@
                     sb.append(" (");
                     sb.append((cputimeUsed*100)/uptimeSince);
                     sb.append("%)");
-                    Slog.i(TAG, sb.toString());
+                    Slog.i(TAG_POWER, sb.toString());
                 }
                 // If a process has held a wake lock for more
                 // than 50% of the time during this period,
@@ -17811,8 +17849,8 @@
                 }
             }
         }
-        if (app.setProcState < 0 || ProcessList.procStatesDifferForMem(app.curProcState,
-                app.setProcState)) {
+        if (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT
+                || ProcessList.procStatesDifferForMem(app.curProcState, app.setProcState)) {
             if (false && mTestPssMode && app.setProcState >= 0 && app.lastStateTime <= (now-200)) {
                 // Experimental code to more aggressively collect pss while
                 // running test...  the problem is that this tends to collect
@@ -17829,7 +17867,7 @@
             app.lastStateTime = now;
             app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
                     mTestPssMode, isSleeping(), now);
-            if (DEBUG_PSS) Slog.d(TAG, "Process state change from "
+            if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from "
                     + ProcessList.makeProcStateString(app.setProcState) + " to "
                     + ProcessList.makeProcStateString(app.curProcState) + " next pss in "
                     + (app.nextPssTime-now) + ": " + app);
@@ -17840,9 +17878,8 @@
                 requestPssLocked(app, app.setProcState);
                 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
                         mTestPssMode, isSleeping(), now);
-            } else if (false && DEBUG_PSS) {
-                Slog.d(TAG, "Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
-            }
+            } else if (false && DEBUG_PSS) Slog.d(TAG_PSS,
+                    "Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
         }
         if (app.setProcState != app.curProcState) {
             if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
@@ -17863,6 +17900,10 @@
                 app.lastCpuTime = app.curCpuTime;
 
             }
+            // Inform UsageStats of important process state change
+            // Must be called before updating setProcState
+            maybeUpdateUsageStats(app);
+
             app.setProcState = app.curProcState;
             if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
                 app.notCachedSinceIdle = false;
@@ -17875,13 +17916,15 @@
         }
 
         if (changes != 0) {
-            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Changes in " + app + ": " + changes);
+            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                    "Changes in " + app + ": " + changes);
             int i = mPendingProcessChanges.size()-1;
             ProcessChangeItem item = null;
             while (i >= 0) {
                 item = mPendingProcessChanges.get(i);
                 if (item.pid == app.pid) {
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Re-using existing item: " + item);
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                            "Re-using existing item: " + item);
                     break;
                 }
                 i--;
@@ -17891,16 +17934,18 @@
                 final int NA = mAvailProcessChanges.size();
                 if (NA > 0) {
                     item = mAvailProcessChanges.remove(NA-1);
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Retreiving available item: " + item);
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                            "Retreiving available item: " + item);
                 } else {
                     item = new ProcessChangeItem();
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Allocating new item: " + item);
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                            "Allocating new item: " + item);
                 }
                 item.changes = 0;
                 item.pid = app.pid;
                 item.uid = app.info.uid;
                 if (mPendingProcessChanges.size() == 0) {
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG,
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
                             "*** Enqueueing dispatch processes changed!");
                     mHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED).sendToTarget();
                 }
@@ -17909,8 +17954,8 @@
             item.changes |= changes;
             item.processState = app.repProcState;
             item.foregroundActivities = app.repForegroundActivities;
-            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Item "
-                    + Integer.toHexString(System.identityHashCode(item))
+            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
+                    "Item " + Integer.toHexString(System.identityHashCode(item))
                     + " " + app.toShortString() + ": changes=" + item.changes
                     + " procState=" + item.processState
                     + " foreground=" + item.foregroundActivities
@@ -17921,6 +17966,28 @@
         return success;
     }
 
+    private void maybeUpdateUsageStats(ProcessRecord app) {
+        if (DEBUG_USAGE_STATS) {
+            Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList())
+                    + "] state changes: old = " + app.setProcState + ", new = "
+                    + app.curProcState);
+        }
+        if (mUsageStatsService == null) {
+            return;
+        }
+        if (app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+                && (app.setProcState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+                        || app.setProcState < 0)) {
+            String[] packages = app.getPackageList();
+            if (packages != null) {
+                for (int i = 0; i < packages.length; i++) {
+                    mUsageStatsService.reportEvent(packages[i], app.userId,
+                            UsageEvents.Event.INTERACTION);
+                }
+            }
+        }
+    }
+
     private final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) {
         if (proc.thread != null) {
             if (proc.baseProcessTracker != null) {
@@ -18640,15 +18707,38 @@
     }
 
     @Override
-    public void setDumpHeapDebugLimit(String processName, long maxMemSize) {
-        enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
-                "setDumpHeapDebugLimit()");
+    public void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize,
+            String reportPackage) {
+        if (processName != null) {
+            enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
+                    "setDumpHeapDebugLimit()");
+        } else {
+            if (!Build.IS_DEBUGGABLE) {
+                throw new SecurityException("Not running a debuggable build");
+            }
+            synchronized (mPidsSelfLocked) {
+                ProcessRecord proc = mPidsSelfLocked.get(Binder.getCallingPid());
+                if (proc == null) {
+                    throw new SecurityException("No process found for calling pid "
+                            + Binder.getCallingPid());
+                }
+                processName = proc.processName;
+                uid = proc.uid;
+                if (reportPackage != null && !proc.pkgList.containsKey(reportPackage)) {
+                    throw new SecurityException("Package " + reportPackage + " is not running in "
+                            + proc);
+                }
+            }
+        }
         synchronized (this) {
             if (maxMemSize > 0) {
-                mMemWatchProcesses.put(processName, maxMemSize);
-                mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG);
+                mMemWatchProcesses.put(processName, uid, new Pair(maxMemSize, reportPackage));
             } else {
-                mMemWatchProcesses.remove(processName);
+                if (uid != 0) {
+                    mMemWatchProcesses.remove(processName, uid);
+                } else {
+                    mMemWatchProcesses.getMap().remove(processName);
+                }
             }
         }
     }
@@ -18666,7 +18756,7 @@
                         + " does not match last path " + mMemWatchDumpFile);
                 return;
             }
-            if (DEBUG_PSS) Slog.d(TAG, "Dump heap finished for " + path);
+            if (true || DEBUG_PSS) Slog.d(TAG_PSS, "Dump heap finished for " + path);
             mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG);
         }
     }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index d34b33b..f3b18f5 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -17,8 +17,6 @@
 package com.android.server.am;
 
 import static com.android.server.am.ActivityManagerDebugConfig.*;
-import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
-import static com.android.server.am.ActivityManagerService.DEBUG_THUMBNAILS;
 import static com.android.server.am.TaskPersister.DEBUG_PERSISTER;
 import static com.android.server.am.TaskPersister.DEBUG_RESTORER;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
@@ -75,6 +73,8 @@
  */
 final class ActivityRecord {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM;
+    private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
+    private static final String TAG_THUMBNAILS = TAG + POSTFIX_THUMBNAILS;
 
     private static final boolean SHOW_ACTIVITY_START_TIME = true;
     static final boolean DEBUG_SAVED_STATE = ActivityStackSupervisor.DEBUG_SAVED_STATE;
@@ -354,7 +354,7 @@
             synchronized (mService) {
                 ActivityRecord r = tokenToActivityRecordLocked(this);
                 if (r != null) {
-                    if (DEBUG_SWITCH) Log.v(TAG, "windowsGone(): " + r);
+                    if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + r);
                     r.nowVisible = false;
                     return;
                 }
@@ -863,7 +863,7 @@
 
     void updateThumbnailLocked(Bitmap newThumbnail, CharSequence description) {
         if (newThumbnail != null) {
-            if (DEBUG_THUMBNAILS) Slog.i(TAG,
+            if (DEBUG_THUMBNAILS) Slog.i(TAG_THUMBNAILS,
                     "Setting thumbnail of " + this + " to " + newThumbnail);
             boolean thumbnailUpdated = task.setLastThumbnail(newThumbnail);
             if (thumbnailUpdated && isPersistable()) {
@@ -1014,7 +1014,7 @@
 
     void windowsVisibleLocked() {
         mStackSupervisor.reportActivityVisibleLocked(this);
-        if (DEBUG_SWITCH) Log.v(TAG, "windowsVisibleLocked(): " + this);
+        if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
         if (!nowVisible) {
             nowVisible = true;
             lastVisibleTime = SystemClock.uptimeMillis();
@@ -1030,7 +1030,7 @@
                 if (size > 0) {
                     for (int i = 0; i < size; i++) {
                         ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
-                        if (DEBUG_SWITCH) Log.v(TAG, "Was waiting for visible: " + r);
+                        if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r);
                     }
                     mStackSupervisor.mWaitingVisibleActivities.clear();
                     mStackSupervisor.scheduleIdleLocked();
@@ -1041,24 +1041,21 @@
     }
 
     ActivityRecord getWaitingHistoryRecordLocked() {
-        // First find the real culprit...  if we are waiting
-        // for another app to start, then we have paused dispatching
-        // for this activity.
-        ActivityRecord r = this;
-        if (mStackSupervisor.mWaitingVisibleActivities.contains(this)) {
+        // First find the real culprit...  if this activity is waiting for
+        // another activity to start or has stopped, then the key dispatching
+        // timeout should not be caused by this.
+        if (mStackSupervisor.mWaitingVisibleActivities.contains(this) || stopped) {
             final ActivityStack stack = mStackSupervisor.getFocusedStack();
-            // Hmmm, who might we be waiting for?
-            r = stack.mResumedActivity;
+            // Try to use the one which is closest to top.
+            ActivityRecord r = stack.mResumedActivity;
             if (r == null) {
                 r = stack.mPausingActivity;
             }
-            // Both of those null?  Fall back to 'this' again
-            if (r == null) {
-                r = this;
+            if (r != null) {
+                return r;
             }
         }
-
-        return r;
+        return this;
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index b102a07..ce510a9 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -16,15 +16,9 @@
 
 package com.android.server.am;
 
+import static android.content.pm.ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN;
+
 import static com.android.server.am.ActivityManagerDebugConfig.*;
-import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
-import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
-import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
-import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
-import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
-import static com.android.server.am.ActivityManagerService.DEBUG_TRANSITION;
-import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
-import static com.android.server.am.ActivityManagerService.DEBUG_VISBILITY;
 
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
@@ -96,6 +90,14 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_AM;
     private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
+    private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
+    private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
+    private static final String TAG_STACK = TAG + POSTFIX_STACK;
+    private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
+    private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
+    private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
+    private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
+    private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
 
     private static final boolean VALIDATE_TOKENS = false;
 
@@ -373,8 +375,7 @@
     }
 
     boolean okToShowLocked(ActivityRecord r) {
-        return isCurrentProfileLocked(r.userId)
-                || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
+        return isCurrentProfileLocked(r.userId) || (r.info.flags & FLAG_SHOW_ON_LOCK_SCREEN) != 0;
     }
 
     final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
@@ -538,23 +539,23 @@
         // If documentData is non-null then it must match the existing task data.
         Uri documentData = isDocument ? intent.getData() : null;
 
-        if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
+        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this);
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
             if (task.voiceSession != null) {
                 // We never match voice sessions; those always run independently.
-                if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": voice session");
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
                 continue;
             }
             if (task.userId != userId) {
                 // Looking for a different task.
-                if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": different user");
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
                 continue;
             }
             final ActivityRecord r = task.getTopActivity();
             if (r == null || r.finishing || r.userId != userId ||
                     r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
-                if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": mismatch root " + r);
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
                 continue;
             }
 
@@ -573,34 +574,32 @@
                 taskDocumentData = null;
             }
 
-            if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
+            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
                     + taskIntent.getComponent().flattenToShortString()
                     + "/aff=" + r.task.rootAffinity + " to new cls="
                     + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
             if (!isDocument && !taskIsDocument && task.rootAffinity != null) {
                 if (task.rootAffinity.equals(target.taskAffinity)) {
-                    if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
+                    if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity!");
                     return r;
                 }
             } else if (taskIntent != null && taskIntent.getComponent() != null &&
                     taskIntent.getComponent().compareTo(cls) == 0 &&
                     Objects.equals(documentData, taskDocumentData)) {
-                if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
                 //dump();
-                if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
-                        + r.intent);
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
+                        "For Intent " + intent + " bringing to top: " + r.intent);
                 return r;
             } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
                     affinityIntent.getComponent().compareTo(cls) == 0 &&
                     Objects.equals(documentData, taskDocumentData)) {
-                if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
                 //dump();
-                if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
-                        + r.intent);
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
+                        "For Intent " + intent + " bringing to top: " + r.intent);
                 return r;
-            } else if (DEBUG_TASKS) {
-                Slog.d(TAG, "Not a match: " + task);
-            }
+            } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
         }
 
         return null;
@@ -619,13 +618,15 @@
         final int userId = UserHandle.getUserId(info.applicationInfo.uid);
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
-            TaskRecord task = mTaskHistory.get(taskNdx);
-            if (!isCurrentProfileLocked(task.userId)) {
-                return null;
-            }
+            final TaskRecord task = mTaskHistory.get(taskNdx);
+            final boolean notCurrentUserTask = !isCurrentProfileLocked(task.userId);
             final ArrayList<ActivityRecord> activities = task.mActivities;
+
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                 ActivityRecord r = activities.get(activityNdx);
+                if (notCurrentUserTask && (r.info.flags & FLAG_SHOW_ON_LOCK_SCREEN) == 0) {
+                    return null;
+                }
                 if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId == userId) {
                     //Slog.i(TAG, "Found matching class!");
                     //dump();
@@ -650,9 +651,13 @@
         // Move userId's tasks to the top.
         int index = mTaskHistory.size();
         for (int i = 0; i < index; ) {
-            TaskRecord task = mTaskHistory.get(i);
-            if (isCurrentProfileLocked(task.userId)) {
-                if (DEBUG_TASKS) Slog.d(TAG, "switchUserLocked: stack=" + getStackId() +
+            final TaskRecord task = mTaskHistory.get(i);
+
+            // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
+            // okay to show the activity when locked.
+            if (isCurrentProfileLocked(task.userId)
+                    || task.topRunningActivityLocked(null) != null) {
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUserLocked: stack=" + getStackId() +
                         " moving " + task + " to top");
                 mTaskHistory.remove(i);
                 mTaskHistory.add(task);
@@ -739,14 +744,15 @@
     boolean checkReadyForSleepLocked() {
         if (mResumedActivity != null) {
             // Still have something resumed; can't sleep until it is paused.
-            if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
-            if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
+            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity);
+            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
+                    "Sleep => pause with userLeaving=false");
             startPausingLocked(false, true, false, false);
             return true;
         }
         if (mPausingActivity != null) {
             // Still waiting for something to pause; can't sleep yet.
-            if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
+            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity);
             return true;
         }
 
@@ -829,7 +835,7 @@
         }
 
         if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
-        else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
+        else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
         mResumedActivity = null;
         mPausingActivity = prev;
         mLastPausedActivity = prev;
@@ -847,7 +853,7 @@
         mService.updateCpuStats();
 
         if (prev.app != null && prev.app.thread != null) {
-            if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
+            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
             try {
                 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                         prev.userId, System.identityHashCode(prev),
@@ -881,8 +887,8 @@
             // key dispatch; the same activity will pick it up again on wakeup.
             if (!uiSleeping) {
                 prev.pauseKeyDispatchingLocked();
-            } else {
-                if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
+            } else if (DEBUG_PAUSE) {
+                 Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
             }
 
             if (dontWait) {
@@ -899,14 +905,14 @@
                 msg.obj = prev;
                 prev.pauseTime = SystemClock.uptimeMillis();
                 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
-                if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
+                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
                 return true;
             }
 
         } else {
             // This activity failed to schedule the
             // pause, so just treat it as being paused now.
-            if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
+            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
             if (!resuming) {
                 mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
             }
@@ -915,8 +921,8 @@
     }
 
     final void activityPausedLocked(IBinder token, boolean timeout) {
-        if (DEBUG_PAUSE) Slog.v(
-            TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
+        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
+            "Activity paused: token=" + token + ", timeout=" + timeout);
 
         final ActivityRecord r = isInStackLocked(token);
         if (r != null) {
@@ -977,18 +983,18 @@
 
     private void completePauseLocked(boolean resumeNext) {
         ActivityRecord prev = mPausingActivity;
-        if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
+        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
 
         if (prev != null) {
             prev.state = ActivityState.PAUSED;
             if (prev.finishing) {
-                if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
+                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
                 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
             } else if (prev.app != null) {
-                if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
+                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending stop: " + prev);
                 if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) {
-                    if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
-                            TAG, "Complete pause, no longer waiting: " + prev);
+                    if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
+                            "Complete pause, no longer waiting: " + prev);
                 }
                 if (prev.configDestroy) {
                     // The previous is being paused because the configuration
@@ -996,7 +1002,7 @@
                     // To juggle the fact that we are also starting a new
                     // instance right now, we need to first completely stop
                     // the current instance before starting the new one.
-                    if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
+                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Destroying after pause: " + prev);
                     destroyActivityLocked(prev, true, "pause-config");
                 } else if (!hasVisibleBehindActivity()) {
                     // If we were visible then resumeTopActivities will release resources before
@@ -1008,16 +1014,20 @@
                         // then give up on things going idle and start clearing
                         // them out. Or if r is the last of activity of the last task the stack
                         // will be empty and must be cleared immediately.
-                        if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
+                        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "To many pending stops, forcing idle");
                         mStackSupervisor.scheduleIdleLocked();
                     } else {
                         mStackSupervisor.checkReadyForSleepLocked();
                     }
                 }
             } else {
-                if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
+                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
                 prev = null;
             }
+            // It is possible the activity was freezing the screen before it was paused.
+            // In that case go ahead and remove the freeze this activity has on the screen
+            // since it is no longer visible.
+            prev.stopFreezingScreenLocked(true /*force*/);
             mPausingActivity = null;
         }
 
@@ -1112,7 +1122,7 @@
         }
     }
 
-    private void setVisibile(ActivityRecord r, boolean visible) {
+    private void setVisible(ActivityRecord r, boolean visible) {
         r.visible = visible;
         mWindowManager.setAppVisibility(r.appToken, visible);
         final ArrayList<ActivityContainer> containers = r.mChildContainers;
@@ -1242,8 +1252,8 @@
         if (top == null) {
             return;
         }
-        if (DEBUG_VISBILITY) Slog.v(
-                TAG, "ensureActivitiesVisible behind " + top
+        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                "ensureActivitiesVisible behind " + top
                 + " configChanges=0x" + Integer.toHexString(configChanges));
 
         if (mTranslucentActivityWaiting != top) {
@@ -1260,6 +1270,7 @@
         // make sure any activities under it are now visible.
         boolean aboveTop = true;
         boolean behindFullscreen = !isStackVisibleLocked();
+        boolean noStackActivityResumed = (isInStackLocked(starting) == null);
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
@@ -1276,8 +1287,8 @@
                 // mLaunchingBehind: Activities launching behind are at the back of the task stack
                 // but must be drawn initially for the animation as though they were visible.
                 if (!behindFullscreen || r.mLaunchTaskBehind) {
-                    if (DEBUG_VISBILITY) Slog.v(
-                            TAG, "Make visible? " + r + " finishing=" + r.finishing
+                    if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                            "Make visible? " + r + " finishing=" + r.finishing
                             + " state=" + r.state);
 
                     // First: if this is not the current activity being started, make
@@ -1287,26 +1298,29 @@
                     }
 
                     if (r.app == null || r.app.thread == null) {
-                        // This activity needs to be visible, but isn't even
-                        // running...  get it started, but don't resume it
-                        // at this point.
-                        if (DEBUG_VISBILITY) Slog.v(TAG, "Start and freeze screen for " + r);
+                        // This activity needs to be visible, but isn't even running...
+                        // get it started and resume if no other stack in this stack is resumed.
+                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                                "Start and freeze screen for " + r);
                         if (r != starting) {
                             r.startFreezingScreenLocked(r.app, configChanges);
                         }
                         if (!r.visible || r.mLaunchTaskBehind) {
-                            if (DEBUG_VISBILITY) Slog.v(
-                                    TAG, "Starting and making visible: " + r);
-                            setVisibile(r, true);
+                            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                                    "Starting and making visible: " + r);
+                            setVisible(r, true);
                         }
                         if (r != starting) {
-                            mStackSupervisor.startSpecificActivityLocked(r, false, false);
+                            mStackSupervisor.startSpecificActivityLocked(
+                                    r, noStackActivityResumed, false);
+                            noStackActivityResumed = false;
                         }
 
                     } else if (r.visible) {
                         // If this activity is already visible, then there is nothing
                         // else to do here.
-                        if (DEBUG_VISBILITY) Slog.v(TAG, "Skipping: already visible at " + r);
+                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                                "Skipping: already visible at " + r);
                         r.stopFreezingScreenLocked(false);
                         try {
                             if (r.returningOptions != null) {
@@ -1322,14 +1336,14 @@
                         if (r.state != ActivityState.RESUMED && r != starting) {
                             // If this activity is paused, tell it
                             // to now show its window.
-                            if (DEBUG_VISBILITY) Slog.v(
-                                    TAG, "Making visible and scheduling visibility: " + r);
+                            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                                    "Making visible and scheduling visibility: " + r);
                             try {
                                 if (mTranslucentActivityWaiting != null) {
                                     r.updateOptionsLocked(r.returningOptions);
                                     mUndrawnActivitiesBelowTopTranslucent.add(r);
                                 }
-                                setVisibile(r, true);
+                                setVisible(r, true);
                                 r.sleeping = false;
                                 r.app.pendingUiClean = true;
                                 r.app.thread.scheduleWindowVisibility(r.appToken, true);
@@ -1348,29 +1362,28 @@
 
                     if (r.fullscreen) {
                         // At this point, nothing else needs to be shown
-                        if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
+                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r);
                         behindFullscreen = true;
                     } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) {
-                        if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
+                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Showing home: at " + r);
                         behindFullscreen = true;
                     }
                 } else {
-                    if (DEBUG_VISBILITY) Slog.v(
-                        TAG, "Make invisible? " + r + " finishing=" + r.finishing
-                        + " state=" + r.state
-                        + " behindFullscreen=" + behindFullscreen);
+                    if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                        "Make invisible? " + r + " finishing=" + r.finishing
+                        + " state=" + r.state + " behindFullscreen=" + behindFullscreen);
                     // Now for any activities that aren't visible to the user, make
                     // sure they no longer are keeping the screen frozen.
                     if (r.visible) {
-                        if (DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
+                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r);
                         try {
-                            setVisibile(r, false);
+                            setVisible(r, false);
                             switch (r.state) {
                                 case STOPPING:
                                 case STOPPED:
                                     if (r.app != null && r.app.thread != null) {
-                                        if (DEBUG_VISBILITY) Slog.v(
-                                                TAG, "Scheduling invisibility: " + r);
+                                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                                                "Scheduling invisibility: " + r);
                                         r.app.thread.scheduleWindowVisibility(r.appToken, false);
                                     }
                                     break;
@@ -1401,7 +1414,7 @@
                                     + r.intent.getComponent(), e);
                         }
                     } else {
-                        if (DEBUG_VISBILITY) Slog.v(TAG, "Already invisible: " + r);
+                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + r);
                     }
                 }
             }
@@ -1471,7 +1484,8 @@
                 }
 
                 if (r.state == ActivityState.INITIALIZING && r.mStartingWindowShown) {
-                    if (DEBUG_VISBILITY) Slog.w(TAG, "Found orphaned starting window " + r);
+                    if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY,
+                            "Found orphaned starting window " + r);
                     r.mStartingWindowShown = false;
                     mWindowManager.removeAppStartingWindow(r.appToken);
                 }
@@ -1514,7 +1528,7 @@
     }
 
     private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
-        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
+        if (DEBUG_LOCKSCREEN) mService.logLockScreen("");
 
         if (!mService.mBooting && !mService.mBooted) {
             // Not ready yet!
@@ -1632,12 +1646,12 @@
         next.sleeping = false;
         mStackSupervisor.mWaitingVisibleActivities.remove(next);
 
-        if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
+        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
 
         // If we are currently pausing an activity, then don't do anything
         // until that is done.
         if (!mStackSupervisor.allPausedActivitiesComplete()) {
-            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG,
+            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                     "resumeTopActivityLocked: Skip resume: some activity pausing.");
             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
             return false;
@@ -1712,8 +1726,8 @@
             if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev)
                     && next != null && !next.nowVisible) {
                 mStackSupervisor.mWaitingVisibleActivities.add(prev);
-                if (DEBUG_SWITCH) Slog.v(
-                        TAG, "Resuming top, waiting visible to hide: " + prev);
+                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
+                        "Resuming top, waiting visible to hide: " + prev);
             } else {
                 // The next activity is already visible, so hide the previous
                 // activity's windows right now so we can show the new one ASAP.
@@ -1725,16 +1739,16 @@
                 // new one is found to be full-screen or not.
                 if (prev.finishing) {
                     mWindowManager.setAppVisibility(prev.appToken, false);
-                    if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
-                            + prev + ", waitingVisible="
+                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
+                            "Not waiting for visible to hide: " + prev + ", waitingVisible="
                             + mStackSupervisor.mWaitingVisibleActivities.contains(prev)
                             + ", nowVisible=" + next.nowVisible);
                 } else {
-                    if (DEBUG_SWITCH) Slog.v(TAG,
+                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                             "Previous already visible but still waiting to hide: " + prev
-                                    + ", waitingVisible="
-                                    + mStackSupervisor.mWaitingVisibleActivities.contains(prev)
-                                    + ", nowVisible=" + next.nowVisible);
+                            + ", waitingVisible="
+                            + mStackSupervisor.mWaitingVisibleActivities.contains(prev)
+                            + ", nowVisible=" + next.nowVisible);
                 }
             }
         }
@@ -1756,7 +1770,7 @@
         boolean anim = true;
         if (prev != null) {
             if (prev.finishing) {
-                if (DEBUG_TRANSITION) Slog.v(TAG,
+                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                         "Prepare close transition: prev=" + prev);
                 if (mNoAnimActivities.contains(prev)) {
                     anim = false;
@@ -1769,7 +1783,8 @@
                 mWindowManager.setAppWillBeHidden(prev.appToken);
                 mWindowManager.setAppVisibility(prev.appToken, false);
             } else {
-                if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev);
+                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
+                        "Prepare open transition: prev=" + prev);
                 if (mNoAnimActivities.contains(next)) {
                     anim = false;
                     mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
@@ -1786,7 +1801,7 @@
                 mWindowManager.setAppVisibility(prev.appToken, false);
             }
         } else {
-            if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous");
+            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
             if (mNoAnimActivities.contains(next)) {
                 anim = false;
                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
@@ -1808,7 +1823,7 @@
 
         ActivityStack lastStack = mStackSupervisor.getLastStack();
         if (next.app != null && next.app.thread != null) {
-            if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
+            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next);
 
             // This activity is now becoming visible.
             mWindowManager.setAppVisibility(next.appToken, true);
@@ -1873,9 +1888,8 @@
                 if (a != null) {
                     final int N = a.size();
                     if (!next.finishing && N > 0) {
-                        if (DEBUG_RESULTS) Slog.v(
-                                TAG, "Delivering results to " + next
-                                + ": " + a);
+                        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
+                                "Delivering results to " + next + ": " + a);
                         next.app.thread.scheduleSendResult(next.appToken, a);
                     }
                 }
@@ -1952,7 +1966,7 @@
                             next.labelRes, next.icon, next.logo, next.windowFlags,
                             null, true);
                 }
-                if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
+                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
             }
             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Restarting " + next);
             mStackSupervisor.startSpecificActivityLocked(next, true, true);
@@ -1976,7 +1990,7 @@
         return null;
     }
 
-    private void insertTaskAtTop(TaskRecord task) {
+    private void insertTaskAtTop(TaskRecord task, ActivityRecord newActivity) {
         // If the moving task is over home stack, transfer its return type to next task
         if (task.isOverHomeStack()) {
             final TaskRecord nextTask = getNextTask(task);
@@ -2004,10 +2018,15 @@
         mTaskHistory.remove(task);
         // Now put task at top.
         int taskNdx = mTaskHistory.size();
-        if (!isCurrentProfileLocked(task.userId)) {
+        final boolean notShownWhenLocked =
+                (newActivity != null && (newActivity.info.flags & FLAG_SHOW_ON_LOCK_SCREEN) == 0)
+                || (newActivity == null && task.topRunningActivityLocked(null) == null);
+        if (!isCurrentProfileLocked(task.userId) && notShownWhenLocked) {
             // Put non-current user tasks below current user tasks.
             while (--taskNdx >= 0) {
-                if (!isCurrentProfileLocked(mTaskHistory.get(taskNdx).userId)) {
+                final TaskRecord tmpTask = mTaskHistory.get(taskNdx);
+                if (!isCurrentProfileLocked(tmpTask.userId)
+                        || tmpTask.topRunningActivityLocked(null) == null) {
                     break;
                 }
             }
@@ -2026,7 +2045,7 @@
             // Last activity in task had been removed or ActivityManagerService is reusing task.
             // Insert or replace.
             // Might not even be in.
-            insertTaskAtTop(rTask);
+            insertTaskAtTop(rTask, r);
             mWindowManager.moveTaskToTop(taskId);
         }
         TaskRecord task = null;
@@ -2074,7 +2093,7 @@
         // activity
         if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
             mStackSupervisor.mUserLeaving = false;
-            if (DEBUG_USER_LEAVING) Slog.v(TAG,
+            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                     "startActivity() behind front, mUserLeaving=false");
         }
 
@@ -2099,9 +2118,9 @@
             if (proc == null || proc.thread == null) {
                 showStartingIcon = true;
             }
-            if (DEBUG_TRANSITION) Slog.v(TAG,
+            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                     "Prepare open transition: starting " + r);
-            if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
+            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
                 mNoAnimActivities.add(r);
             } else {
@@ -2271,13 +2290,13 @@
                     // same task affinity as the one we are moving,
                     // then merge it into the same task.
                     targetTask = bottom.task;
-                    if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
+                    if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
                             + " out to bottom task " + bottom.task);
                 } else {
                     targetTask = createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
                             null, null, null, false);
                     targetTask.affinityIntent = target.intent;
-                    if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
+                    if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
                             + " out to new task " + target.task);
                 }
 
@@ -2302,8 +2321,8 @@
                     if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing activity " + p + " from task="
                             + task + " adding to task=" + targetTask
                             + " Callers=" + Debug.getCallers(4));
-                    if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
-                            + " out to target's task " + target.task);
+                    if (DEBUG_TASKS) Slog.v(TAG_TASKS,
+                            "Pushing next activity " + p + " out to target's task " + target.task);
                     p.setTask(targetTask, null);
                     targetTask.addActivityAtBottom(p);
 
@@ -2345,7 +2364,7 @@
                             noOptions = false;
                         }
                     }
-                    if (DEBUG_TASKS) Slog.w(TAG,
+                    if (DEBUG_TASKS) Slog.w(TAG_TASKS,
                             "resetTaskIntendedTask: calling finishActivity on " + p);
                     if (finishActivityLocked(
                             p, Activity.RESULT_CANCELED, null, "reset-task", false)) {
@@ -2419,7 +2438,8 @@
                 // in a task that is not currently on top.)
                 if (forceReset || finishOnTaskLaunch) {
                     final int start = replyChainEnd >= 0 ? replyChainEnd : i;
-                    if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index " + start + " to " + i);
+                    if (DEBUG_TASKS) Slog.v(TAG_TASKS,
+                            "Finishing task at index " + start + " to " + i);
                     for (int srcPos = start; srcPos >= i; --srcPos) {
                         final ActivityRecord p = activities.get(srcPos);
                         if (p.finishing) {
@@ -2435,8 +2455,9 @@
                     }
 
                     final int start = replyChainEnd >= 0 ? replyChainEnd : i;
-                    if (DEBUG_TASKS) Slog.v(TAG, "Reparenting from task=" + affinityTask + ":"
-                            + start + "-" + i + " to task=" + task + ":" + taskInsertionPoint);
+                    if (DEBUG_TASKS) Slog.v(TAG_TASKS,
+                            "Reparenting from task=" + affinityTask + ":" + start + "-" + i
+                            + " to task=" + task + ":" + taskInsertionPoint);
                     for (int srcPos = start; srcPos >= i; --srcPos) {
                         final ActivityRecord p = activities.get(srcPos);
                         p.setTask(task, null);
@@ -2445,8 +2466,8 @@
                         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + p
                                 + " to stack at " + task,
                                 new RuntimeException("here").fillInStackTrace());
-                        if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p + " from " + srcPos
-                                + " in to resetting task " + task);
+                        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p
+                                + " from " + srcPos + " in to resetting task " + task);
                         mWindowManager.setAppTask(p.appToken, taskId);
                     }
                     mWindowManager.moveTaskToTop(taskId);
@@ -2604,7 +2625,7 @@
     }
 
     final void stopActivityLocked(ActivityRecord r) {
-        if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
+        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r);
         if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
             if (!r.finishing) {
@@ -2629,8 +2650,8 @@
                 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
                         + " (stop requested)");
                 r.state = ActivityState.STOPPING;
-                if (DEBUG_VISBILITY) Slog.v(
-                        TAG, "Stopping visible=" + r.visible + " for " + r);
+                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+                        "Stopping visible=" + r.visible + " for " + r);
                 if (!r.visible) {
                     mWindowManager.setAppVisibility(r.appToken, false);
                 }
@@ -2767,7 +2788,7 @@
         // send the result
         ActivityRecord resultTo = r.resultTo;
         if (resultTo != null) {
-            if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
+            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Adding result to " + resultTo
                     + " who=" + r.resultWho + " req=" + r.requestCode
                     + " res=" + resultCode + " data=" + resultData);
             if (resultTo.userId != r.userId) {
@@ -2784,7 +2805,7 @@
                                      resultData);
             r.resultTo = null;
         }
-        else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
+        else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r);
 
         // Make sure this HistoryRecord is not holding on to other resources,
         // because clients have remote IPC references to this object so we
@@ -2832,7 +2853,7 @@
 
         if (mResumedActivity == r) {
             boolean endTask = index <= 0;
-            if (DEBUG_VISBILITY || DEBUG_TRANSITION) Slog.v(TAG,
+            if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                     "Prepare close transition: finishing " + r);
             mWindowManager.prepareAppTransition(endTask
                     ? AppTransition.TRANSIT_TASK_CLOSE
@@ -2842,8 +2863,9 @@
             mWindowManager.setAppVisibility(r.appToken, false);
 
             if (mPausingActivity == null) {
-                if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
-                if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
+                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
+                if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
+                        "finish() => pause with userLeaving=false");
                 startPausingLocked(false, false, false, false);
             }
 
@@ -2853,10 +2875,10 @@
         } else if (r.state != ActivityState.PAUSING) {
             // If the activity is PAUSING, we will complete the finish once
             // it is done pausing; else we can just directly finish it here.
-            if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
+            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
             return finishCurrentActivityLocked(r, FINISH_AFTER_PAUSE, oomAdj) == null;
         } else {
-            if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
+            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
         }
 
         return false;
@@ -3151,7 +3173,7 @@
         }
         final TaskRecord task = r.task;
         if (task != null && task.removeActivity(r)) {
-            if (DEBUG_STACK) Slog.i(TAG,
+            if (DEBUG_STACK) Slog.i(TAG_STACK,
                     "removeActivityFromHistoryLocked: last activity removed from " + this);
             if (mStackSupervisor.isFrontStack(this) && task == topTask() &&
                     task.isOverHomeStack()) {
@@ -3204,7 +3226,7 @@
                     continue;
                 }
                 if (r.isDestroyable()) {
-                    if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
+                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.state
                             + " resumed=" + mResumedActivity
                             + " pausing=" + mPausingActivity + " for reason " + reason);
                     if (destroyActivityLocked(r, true, reason)) {
@@ -3220,8 +3242,8 @@
 
     final boolean safelyDestroyActivityLocked(ActivityRecord r, String reason) {
         if (r.isDestroyable()) {
-            if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
-                    + " resumed=" + mResumedActivity
+            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
+                    "Destroying " + r + " in state " + r.state + " resumed=" + mResumedActivity
                     + " pausing=" + mPausingActivity + " for reason " + reason);
             return destroyActivityLocked(r, true, reason);
         }
@@ -3279,9 +3301,9 @@
      * but then create a new client-side object for this same HistoryRecord.
      */
     final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
-        if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(
-            TAG, "Removing activity from " + reason + ": token=" + r
-              + ", app=" + (r.app != null ? r.app.processName : "(null)"));
+        if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(TAG_SWITCH,
+                "Removing activity from " + reason + ": token=" + r
+                + ", app=" + (r.app != null ? r.app.processName : "(null)"));
         EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
                 r.userId, System.identityHashCode(r),
                 r.task.taskId, r.shortComponentName, reason);
@@ -3313,7 +3335,7 @@
             boolean skipDestroy = false;
 
             try {
-                if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
+                if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
                 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
                         r.configChangeFlags);
             } catch (Exception e) {
@@ -3483,6 +3505,9 @@
                 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
                         "Record #" + i + " " + r + ": app=" + r.app);
                 if (r.app == app) {
+                    if (r.visible) {
+                        hasVisibleActivities = true;
+                    }
                     final boolean remove;
                     if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
                         // Don't currently have state for the activity, or
@@ -3522,9 +3547,6 @@
                         // it can be restarted later when needed.
                         if (DEBUG_ALL) Slog.v(
                             TAG, "Keeping entry, setting app to null");
-                        if (r.visible) {
-                            hasVisibleActivities = true;
-                        }
                         if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity "
                                 + r);
                         r.app = null;
@@ -3575,8 +3597,8 @@
         for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
             if (task.taskType == homeStackTaskType) {
-                if (DEBUG_TASKS || DEBUG_STACK)
-                    Slog.d(TAG, "moveHomeStackTaskToTop: moving " + task);
+                if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG_STACK,
+                        "moveHomeStackTaskToTop: moving " + task);
                 mTaskHistory.remove(taskNdx);
                 mTaskHistory.add(top, task);
                 updateTaskMovement(task, true);
@@ -3587,7 +3609,7 @@
 
     final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, Bundle options,
             String reason) {
-        if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
+        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
 
         final int numTasks = mTaskHistory.size();
         final int index = mTaskHistory.indexOf(tr);
@@ -3603,13 +3625,13 @@
 
         // Shift all activities with this task up to the top
         // of the stack, keeping them in the same internal order.
-        insertTaskAtTop(tr);
+        insertTaskAtTop(tr, null);
 
         // Set focus to the top running activity of this stack.
         ActivityRecord r = topRunningActivityLocked(null);
         mService.setFocusedActivityLocked(r, reason);
 
-        if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
+        if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
         if (noAnimation) {
             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
             if (r != null) {
@@ -3673,7 +3695,7 @@
             }
         }
 
-        if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to back transition: task=" + taskId);
+        if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task=" + taskId);
 
         boolean prevIsHome = false;
         if (tr.isOverHomeStack()) {
@@ -3896,16 +3918,15 @@
         return true;
     }
 
-    private boolean relaunchActivityLocked(ActivityRecord r,
-            int changes, boolean andResume) {
+    private boolean relaunchActivityLocked(ActivityRecord r, int changes, boolean andResume) {
         List<ResultInfo> results = null;
         List<ReferrerIntent> newIntents = null;
         if (andResume) {
             results = r.results;
             newIntents = r.newIntents;
         }
-        if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
-                + " with results=" + results + " newIntents=" + newIntents
+        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
+                "Relaunching: " + r + " with results=" + results + " newIntents=" + newIntents
                 + " andResume=" + andResume);
         EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
                 : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r),
@@ -3916,9 +3937,8 @@
         mStackSupervisor.removeChildActivityContainers(r);
 
         try {
-            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
-                    (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
-                    + r);
+            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
+                    "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + r);
             r.forceNewConfig = false;
             r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes,
                     !andResume, new Configuration(mService.mConfiguration),
@@ -3927,7 +3947,7 @@
             // the caller will only pass in 'andResume' if this activity is
             // currently resumed, which implies we aren't sleeping.
         } catch (RemoteException e) {
-            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
+            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
         }
 
         if (andResume) {
@@ -4028,16 +4048,18 @@
     }
 
     void getTasksLocked(List<RunningTaskInfo> list, int callingUid, boolean allowed) {
+        boolean focusedStack = mStackSupervisor.getFocusedStack() == this;
+        boolean topTask = true;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
+            if (task.getTopActivity() == null) {
+                continue;
+            }
             ActivityRecord r = null;
             ActivityRecord top = null;
             int numActivities = 0;
             int numRunning = 0;
             final ArrayList<ActivityRecord> activities = task.mActivities;
-            if (activities.isEmpty()) {
-                continue;
-            }
             if (!allowed && !task.isHomeTask() && task.effectiveUid != callingUid) {
                 continue;
             }
@@ -4066,22 +4088,25 @@
             ci.baseActivity = r.intent.getComponent();
             ci.topActivity = top.intent.getComponent();
             ci.lastActiveTime = task.lastActiveTime;
+            if (focusedStack && topTask) {
+                // Give the latest time to ensure foreground task can be sorted
+                // at the first, because lastActiveTime of creating task is 0.
+                ci.lastActiveTime = System.currentTimeMillis();
+                topTask = false;
+            }
 
             if (top.task != null) {
                 ci.description = top.task.lastDescription;
             }
             ci.numActivities = numActivities;
             ci.numRunning = numRunning;
-            //System.out.println(
-            //    "#" + maxNum + ": " + " descr=" + ci.description);
             list.add(ci);
         }
     }
 
     public void unhandledBackLocked() {
         final int top = mTaskHistory.size() - 1;
-        if (DEBUG_SWITCH) Slog.d(
-            TAG, "Performing unhandledBack(): top activity at " + top);
+        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top);
         if (top >= 0) {
             final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
             int activityTop = activities.size() - 1;
@@ -4099,7 +4124,7 @@
      */
     boolean handleAppDiedLocked(ProcessRecord app) {
         if (mPausingActivity != null && mPausingActivity.app == app) {
-            if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG,
+            if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
                     "App died while pausing: " + mPausingActivity);
             mPausingActivity = null;
         }
@@ -4198,14 +4223,22 @@
     }
 
     void removeTask(TaskRecord task, String reason) {
-        removeTask(task, reason, true);
+        removeTask(task, reason, true /* notMoving */);
     }
 
-    void removeTask(TaskRecord task, String reason, boolean removeFromWindowManager) {
-        mStackSupervisor.endLockTaskModeIfTaskEnding(task);
-        if (removeFromWindowManager) {
+    /**
+     * Removes the input task from this stack.
+     * @param task to remove.
+     * @param reason for removal.
+     * @param notMoving task to another stack. In the case we are moving we don't want to perform
+     *                  some operations on the task like removing it from window manager or recents.
+     */
+    void removeTask(TaskRecord task, String reason, boolean notMoving) {
+        if (notMoving) {
+            mStackSupervisor.endLockTaskModeIfTaskEnding(task);
             mWindowManager.removeTask(task.taskId);
         }
+
         final ActivityRecord r = mResumedActivity;
         if (r != null && r.task == task) {
             mResumedActivity = null;
@@ -4222,7 +4255,7 @@
         mTaskHistory.remove(task);
         updateTaskMovement(task, true);
 
-        if (task.mActivities.isEmpty()) {
+        if (notMoving && task.mActivities.isEmpty()) {
             final boolean isVoiceSession = task.voiceSession != null;
             if (isVoiceSession) {
                 try {
@@ -4239,7 +4272,7 @@
         }
 
         if (mTaskHistory.isEmpty()) {
-            if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack=" + this);
+            if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
             final boolean notHomeStack = !isHomeStack();
             if (isOnHomeDisplay()) {
                 String myReason = reason + " leftTaskHistoryEmpty";
@@ -4275,7 +4308,7 @@
     void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
         task.stack = this;
         if (toTop) {
-            insertTaskAtTop(task);
+            insertTaskAtTop(task, null);
         } else {
             mTaskHistory.add(0, task);
             updateTaskMovement(task, false);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index e9e6496..f8e9cbf 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -23,17 +23,11 @@
 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static com.android.server.am.ActivityManagerDebugConfig.*;
-import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
-import static com.android.server.am.ActivityManagerService.DEBUG_RECENTS;
-import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
-import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
-import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
-import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
-import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
 import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityStack.ActivityState.*;
 
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -120,6 +114,13 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
     private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
+    private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
+    private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
+    private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
+    private static final String TAG_STACK = TAG + POSTFIX_STACK;
+    private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
+    private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
+    private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
 
     static final boolean DEBUG = DEBUG_ALL || false;
     static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
@@ -273,8 +274,8 @@
      * until the task exits or #stopLockTaskMode() is called. */
     TaskRecord mLockTaskModeTask;
     /** Store the current lock task mode. Possible values:
-     * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActicityManager#LOCK_TASK_MODE_LOCKED},
-     * {@link ActicityManager#LOCK_TASK_MODE_PINNED}
+     * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
+     * {@link ActivityManager#LOCK_TASK_MODE_PINNED}
      */
     private int mLockTaskModeState;
     /**
@@ -381,7 +382,7 @@
     }
 
     void notifyActivityDrawnForKeyguard() {
-        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
+        if (DEBUG_LOCKSCREEN) mService.logLockScreen("");
         mWindowManager.notifyActivityDrawnForKeyguard();
     }
 
@@ -422,7 +423,7 @@
         // The home stack should either be at the top or bottom of the stack list.
         if ((toFront && (stacks.get(topNdx) != mHomeStack))
                 || (!toFront && (stacks.get(0) != mHomeStack))) {
-            if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: topStack old="
+            if (DEBUG_STACK) Slog.d(TAG_STACK, "moveHomeTask: topStack old="
                     + ((lastFocusedStack != null) ? lastFocusedStack : stacks.get(topNdx))
                     + " new=" + mFocusedStack);
             stacks.remove(mHomeStack);
@@ -510,10 +511,10 @@
         }
 
         // Don't give up! Look in recents.
-        if (DEBUG_RECENTS) Slog.v(TAG, "Looking for task id=" + id + " in recents");
+        if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
         TaskRecord task = mRecentTasks.taskForIdLocked(id);
         if (task == null) {
-            if (DEBUG_RECENTS) Slog.d(TAG, "\tDidn't find task id=" + id + " in recents");
+            if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
             return null;
         }
 
@@ -522,10 +523,11 @@
         }
 
         if (!restoreRecentTaskLocked(task)) {
-            if (DEBUG_RECENTS) Slog.w(TAG, "Couldn't restore task id=" + id + " found in recents");
+            if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
+                    "Couldn't restore task id=" + id + " found in recents");
             return null;
         }
-        if (DEBUG_RECENTS) Slog.w(TAG, "Restored task id=" + id + " from in recents");
+        if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents");
         return task;
     }
 
@@ -633,14 +635,14 @@
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (isFrontStack(stack)) {
                     final ActivityRecord r = stack.mResumedActivity;
-                    if (r != null && r.state != ActivityState.RESUMED) {
+                    if (r != null && r.state != RESUMED) {
                         return false;
                     }
                 }
             }
         }
         // TODO: Not sure if this should check if all Paused are complete too.
-        if (DEBUG_STACK) Slog.d(TAG,
+        if (DEBUG_STACK) Slog.d(TAG_STACK,
                 "allResumedActivitiesComplete: mLastFocusedStack changing from=" +
                 mLastFocusedStack + " to=" + mFocusedStack);
         mLastFocusedStack = mFocusedStack;
@@ -648,17 +650,21 @@
     }
 
     boolean allResumedActivitiesVisible() {
+        boolean foundResumed = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 final ActivityRecord r = stack.mResumedActivity;
-                if (r != null && (!r.nowVisible || mWaitingVisibleActivities.contains(r))) {
-                    return false;
+                if (r != null) {
+                    if (!r.nowVisible || mWaitingVisibleActivities.contains(r)) {
+                        return false;
+                    }
+                    foundResumed = true;
                 }
             }
         }
-        return true;
+        return foundResumed;
     }
 
     /**
@@ -690,9 +696,7 @@
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 final ActivityRecord r = stack.mPausingActivity;
-                if (r != null && r.state != ActivityState.PAUSED
-                        && r.state != ActivityState.STOPPED
-                        && r.state != ActivityState.STOPPING) {
+                if (r != null && r.state != PAUSED && r.state != STOPPED && r.state != STOPPING) {
                     if (DEBUG_STATES) {
                         Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
                         pausing = false;
@@ -897,7 +901,7 @@
         ActivityContainer container = (ActivityContainer)iContainer;
         synchronized (mService) {
             if (container != null && container.mParentActivity != null &&
-                    container.mParentActivity.state != ActivityState.RESUMED) {
+                    container.mParentActivity.state != RESUMED) {
                 // Cannot start a child activity if the parent is not resumed.
                 return ActivityManager.START_CANCELED;
             }
@@ -1027,7 +1031,7 @@
                     } while (!outResult.timeout && outResult.who == null);
                 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
                     ActivityRecord r = stack.topRunningActivityLocked(null);
-                    if (r.nowVisible && r.state == ActivityState.RESUMED) {
+                    if (r.nowVisible && r.state == RESUMED) {
                         outResult.timeout = false;
                         outResult.who = new ComponentName(r.info.packageName, r.info.name);
                         outResult.totalTime = 0;
@@ -1132,12 +1136,13 @@
             ProcessRecord app, boolean andResume, boolean checkConfig)
             throws RemoteException {
 
-        r.startFreezingScreenLocked(app, 0);
-        if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
-        mWindowManager.setAppVisibility(r.appToken, true);
+        if (andResume) {
+            r.startFreezingScreenLocked(app, 0);
+            mWindowManager.setAppVisibility(r.appToken, true);
 
-        // schedule launch ticks to collect information about slow apps.
-        r.startLaunchTickingLocked();
+            // schedule launch ticks to collect information about slow apps.
+            r.startLaunchTickingLocked();
+        }
 
         // Have the window manager re-evaluate the orientation of
         // the screen based on the new activity order.  Note that
@@ -1177,10 +1182,9 @@
                 results = r.results;
                 newIntents = r.newIntents;
             }
-            if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
-                    + " icicle=" + r.icicle
-                    + " with results=" + results + " newIntents=" + newIntents
-                    + " andResume=" + andResume);
+            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
+                    "Launching: " + r + " icicle=" + r.icicle + " with results=" + results
+                    + " newIntents=" + newIntents + " andResume=" + andResume);
             if (andResume) {
                 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
                         r.userId, System.identityHashCode(r),
@@ -1195,34 +1199,37 @@
             r.forceNewConfig = false;
             mService.showAskCompatModeDialogLocked(r);
             r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
-            String profileFile = null;
-            ParcelFileDescriptor profileFd = null;
+            ProfilerInfo profilerInfo = null;
             if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
                 if (mService.mProfileProc == null || mService.mProfileProc == app) {
                     mService.mProfileProc = app;
-                    profileFile = mService.mProfileFile;
-                    profileFd = mService.mProfileFd;
-                }
-            }
-            app.hasShownUi = true;
-            app.pendingUiClean = true;
-            if (profileFd != null) {
-                try {
-                    profileFd = profileFd.dup();
-                } catch (IOException e) {
-                    if (profileFd != null) {
-                        try {
-                            profileFd.close();
-                        } catch (IOException o) {
+                    final String profileFile = mService.mProfileFile;
+                    if (profileFile != null) {
+                        ParcelFileDescriptor profileFd = mService.mProfileFd;
+                        if (profileFd != null) {
+                            try {
+                                profileFd = profileFd.dup();
+                            } catch (IOException e) {
+                                if (profileFd != null) {
+                                    try {
+                                        profileFd.close();
+                                    } catch (IOException o) {
+                                    }
+                                    profileFd = null;
+                                }
+                            }
                         }
-                        profileFd = null;
+
+                        profilerInfo = new ProfilerInfo(profileFile, profileFd,
+                                mService.mSamplingInterval, mService.mAutoStopProfiler);
                     }
                 }
             }
 
-            ProfilerInfo profilerInfo = profileFile != null
-                    ? new ProfilerInfo(profileFile, profileFd, mService.mSamplingInterval,
-                    mService.mAutoStopProfiler) : null;
+            if (andResume) {
+                app.hasShownUi = true;
+                app.pendingUiClean = true;
+            }
             app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                     System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
@@ -1286,7 +1293,7 @@
             // other state.
             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
                     + " (starting in stopped state)");
-            r.state = ActivityState.STOPPED;
+            r.state = STOPPED;
             r.stopped = true;
         }
 
@@ -1377,8 +1384,8 @@
         ActivityRecord resultRecord = null;
         if (resultTo != null) {
             sourceRecord = isInAnyStackLocked(resultTo);
-            if (DEBUG_RESULTS) Slog.v(
-                TAG, "Will send result to " + resultTo + " " + sourceRecord);
+            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
+                    "Will send result to " + resultTo + " " + sourceRecord);
             if (sourceRecord != null) {
                 if (requestCode >= 0 && !sourceRecord.finishing) {
                     resultRecord = sourceRecord;
@@ -1722,7 +1729,8 @@
         // We'll invoke onUserLeaving before onPause only if the launching
         // activity did not explicitly state that this is an automated launch.
         mUserLeaving = (launchFlags & Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
-        if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
+        if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
+                "startActivity() => mUserLeaving=" + mUserLeaving);
 
         // If the caller has asked not to resume at this point, we make note
         // of this in the record so that we can skip it when trying to find
@@ -1929,7 +1937,7 @@
                         }
                     }
                     if (!movedToFront) {
-                        if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack
+                        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + targetStack
                                 + " from " + intentActivity);
                         targetStack.moveToFront("intentActivityFound");
                     }
@@ -2135,8 +2143,8 @@
                         newTaskIntent != null ? newTaskIntent : intent,
                         voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
                         taskToAffiliate);
-                if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
-                        r.task);
+                if (DEBUG_TASKS) Slog.v(TAG_TASKS,
+                        "Starting new activity " + r + " in new task " + r.task);
             } else {
                 r.setTask(reuseTask, taskToAffiliate);
             }
@@ -2203,7 +2211,7 @@
             // to keep the new one in the same task as the one that is starting
             // it.
             r.setTask(sourceTask, null);
-            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
                     + " in existing task " + r.task + " from source " + sourceRecord);
 
         } else if (inTask != null) {
@@ -2242,7 +2250,7 @@
             }
 
             r.setTask(inTask, null);
-            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
                     + " in explicit task " + r.task);
 
         } else {
@@ -2255,7 +2263,7 @@
             r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(),
                             r.info, intent, null, null, true), null);
             mWindowManager.moveTaskToTop(r.task.taskId);
-            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
                     + " in new guessed " + r.task);
         }
 
@@ -2595,8 +2603,8 @@
             return;
         }
         task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options, reason);
-        if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
-                + task.stack);
+        if (DEBUG_STACK) Slog.d(TAG_STACK,
+                "findTaskToMoveToFront: moved to front of stack=" + task.stack);
     }
 
     ActivityStack getStack(int stackId) {
@@ -2789,20 +2797,20 @@
             stack = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
             // Restore home stack to top.
             moveHomeStack(true, "restoreRecentTask");
-            if (DEBUG_RECENTS)
-                Slog.v(TAG, "Created stack=" + stack + " for recents restoration.");
+            if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
+                    "Created stack=" + stack + " for recents restoration.");
         }
 
         if (stack == null) {
             // What does this mean??? Not sure how we would get here...
-            if (DEBUG_RECENTS)
-                Slog.v(TAG, "Unable to find/create stack to restore recent task=" + task);
+            if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
+                    "Unable to find/create stack to restore recent task=" + task);
             return false;
         }
 
         stack.addTask(task, false, false);
-        if (DEBUG_RECENTS)
-            Slog.v(TAG, "Added restored task=" + task + " to stack=" + stack);
+        if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
+                "Added restored task=" + task + " to stack=" + stack);
         final ArrayList<ActivityRecord> activities = task.mActivities;
         for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
             final ActivityRecord r = activities.get(activityNdx);
@@ -2828,25 +2836,25 @@
         }
         mWindowManager.moveTaskToStack(taskId, stackId, toTop);
         if (task.stack != null) {
-            task.stack.removeTask(task, "moveTaskToStack", false);
+            task.stack.removeTask(task, "moveTaskToStack", false /* notMoving */);
         }
         stack.addTask(task, toTop, true);
         resumeTopActivitiesLocked();
     }
 
     ActivityRecord findTaskLocked(ActivityRecord r) {
-        if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + r);
+        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (!r.isApplicationActivity() && !stack.isHomeStack()) {
-                    if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: (home activity) " + stack);
+                    if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (home activity) " + stack);
                     continue;
                 }
                 if (!stack.mActivityContainer.isEligibleForNewTasks()) {
-                    if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: (new task not allowed) " +
-                            stack);
+                    if (DEBUG_TASKS) Slog.d(TAG_TASKS,
+                            "Skipping stack: (new task not allowed) " + stack);
                     continue;
                 }
                 final ActivityRecord ar = stack.findTaskLocked(r);
@@ -2855,7 +2863,7 @@
                 }
             }
         }
-        if (DEBUG_TASKS) Slog.d(TAG, "No task found");
+        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "No task found");
         return null;
     }
 
@@ -2964,7 +2972,7 @@
 
             if (mStoppingActivities.size() > 0) {
                 // Still need to tell some activities to stop; can't sleep yet.
-                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
+                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop "
                         + mStoppingActivities.size() + " activities");
                 scheduleIdleLocked();
                 dontSleep = true;
@@ -2972,7 +2980,7 @@
 
             if (mGoingToSleepActivities.size() > 0) {
                 // Still need to tell some activities to sleep; can't sleep yet.
-                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
+                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep "
                         + mGoingToSleepActivities.size() + " activities");
                 dontSleep = true;
             }
@@ -3123,16 +3131,14 @@
             // First, if we find an activity that is in the process of being destroyed,
             // then we just aren't going to do anything for now; we want things to settle
             // down before we try to prune more activities.
-            if (r.finishing || r.state == ActivityState.DESTROYING
-                    || r.state == ActivityState.DESTROYED) {
+            if (r.finishing || r.state == DESTROYING || r.state == DESTROYED) {
                 if (DEBUG_RELEASE) Slog.d(TAG, "Abort release; already destroying: " + r);
                 return;
             }
             // Don't consider any activies that are currently not in a state where they
             // can be destroyed.
-            if (r.visible || !r.stopped || !r.haveState
-                    || r.state == ActivityState.RESUMED || r.state == ActivityState.PAUSING
-                    || r.state == ActivityState.PAUSED || r.state == ActivityState.STOPPING) {
+            if (r.visible || !r.stopped || !r.haveState || r.state == RESUMED || r.state == PAUSING
+                    || r.state == PAUSED || r.state == STOPPING) {
                 if (DEBUG_RELEASE) Slog.d(TAG, "Not releasing in-use activity: " + r);
                 continue;
             }
@@ -3250,39 +3256,34 @@
     }
 
     void validateTopActivitiesLocked() {
-        // FIXME
-/*        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = stacks.get(stackNdx);
-            final ActivityRecord r = stack.topRunningActivityLocked(null);
-            final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
-            if (isFrontStack(stack)) {
-                if (r == null) {
-                    Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
+        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = stacks.get(stackNdx);
+                final ActivityRecord r = stack.topRunningActivityLocked(null);
+                final ActivityState state = r == null ? DESTROYED : r.state;
+                if (isFrontStack(stack)) {
+                    if (r == null) Slog.e(TAG,
+                            "validateTop...: null top activity, stack=" + stack);
+                    else {
+                        final ActivityRecord pausing = stack.mPausingActivity;
+                        if (pausing != null && pausing == r) Slog.e(TAG,
+                                "validateTop...: top stack has pausing activity r=" + r
+                                + " state=" + state);
+                        if (state != INITIALIZING && state != RESUMED) Slog.e(TAG,
+                                "validateTop...: activity in front not resumed r=" + r
+                                + " state=" + state);
+                    }
                 } else {
-                    final ActivityRecord pausing = stack.mPausingActivity;
-                    if (pausing != null && pausing == r) {
-                        Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
-                            " state=" + state);
-                    }
-                    if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
-                        Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
-                                " state=" + state);
-                    }
-                }
-            } else {
-                final ActivityRecord resumed = stack.mResumedActivity;
-                if (resumed != null && resumed == r) {
-                    Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
-                        " state=" + state);
-                }
-                if (r != null && (state == ActivityState.INITIALIZING
-                        || state == ActivityState.RESUMED)) {
-                    Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
-                            " state=" + state);
+                    final ActivityRecord resumed = stack.mResumedActivity;
+                    if (resumed != null && resumed == r) Slog.e(TAG,
+                            "validateTop...: back stack has resumed activity r=" + r
+                            + " state=" + state);
+                    if (r != null && (state == INITIALIZING || state == RESUMED)) Slog.e(TAG,
+                            "validateTop...: activity in back resumed r=" + r + " state=" + state);
                 }
             }
         }
-*/
     }
 
     public void dump(PrintWriter pw, String prefix) {
@@ -3508,7 +3509,7 @@
         mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0));
     }
 
-    public void handleDisplayAddedLocked(int displayId) {
+    private void handleDisplayAdded(int displayId) {
         boolean newDisplay;
         synchronized (mService) {
             newDisplay = mActivityDisplays.get(displayId) == null;
@@ -3526,7 +3527,7 @@
         }
     }
 
-    public void handleDisplayRemovedLocked(int displayId) {
+    private void handleDisplayRemoved(int displayId) {
         synchronized (mService) {
             ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
             if (activityDisplay != null) {
@@ -3540,7 +3541,7 @@
         mWindowManager.onDisplayRemoved(displayId);
     }
 
-    public void handleDisplayChangedLocked(int displayId) {
+    private void handleDisplayChanged(int displayId) {
         synchronized (mService) {
             ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
             if (activityDisplay != null) {
@@ -3550,7 +3551,7 @@
         mWindowManager.onDisplayChanged(displayId);
     }
 
-    StackInfo getStackInfo(ActivityStack stack) {
+    private StackInfo getStackInfoLocked(ActivityStack stack) {
         StackInfo info = new StackInfo();
         mWindowManager.getStackBounds(stack.mStackId, info.bounds);
         info.displayId = Display.DEFAULT_DISPLAY;
@@ -3576,7 +3577,7 @@
     StackInfo getStackInfoLocked(int stackId) {
         ActivityStack stack = getStack(stackId);
         if (stack != null) {
-            return getStackInfo(stack);
+            return getStackInfoLocked(stack);
         }
         return null;
     }
@@ -3586,7 +3587,7 @@
         for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
             ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) {
-                list.add(getStackInfo(stacks.get(ndx)));
+                list.add(getStackInfoLocked(stacks.get(ndx)));
             }
         }
         return list;
@@ -3706,13 +3707,13 @@
                     }
                 } break;
                 case HANDLE_DISPLAY_ADDED: {
-                    handleDisplayAddedLocked(msg.arg1);
+                    handleDisplayAdded(msg.arg1);
                 } break;
                 case HANDLE_DISPLAY_CHANGED: {
-                    handleDisplayChangedLocked(msg.arg1);
+                    handleDisplayChanged(msg.arg1);
                 } break;
                 case HANDLE_DISPLAY_REMOVED: {
-                    handleDisplayRemovedLocked(msg.arg1);
+                    handleDisplayRemoved(msg.arg1);
                 } break;
                 case CONTAINER_CALLBACK_VISIBILITY: {
                     final ActivityContainer container = (ActivityContainer) msg.obj;
@@ -3847,12 +3848,12 @@
                 mStackId = stackId;
                 mStack = new ActivityStack(this, mRecentTasks);
                 mIdString = "ActivtyContainer{" + mStackId + "}";
-                if (DEBUG_STACK) Slog.d(TAG, "Creating " + this);
+                if (DEBUG_STACK) Slog.d(TAG_STACK, "Creating " + this);
             }
         }
 
         void attachToDisplayLocked(ActivityDisplay activityDisplay) {
-            if (DEBUG_STACK) Slog.d(TAG, "attachToDisplayLocked: " + this
+            if (DEBUG_STACK) Slog.d(TAG_STACK, "attachToDisplayLocked: " + this
                     + " to display=" + activityDisplay);
             mActivityDisplay = activityDisplay;
             mStack.mDisplayId = activityDisplay.mDisplayId;
@@ -3930,7 +3931,7 @@
         }
 
         protected void detachLocked() {
-            if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display="
+            if (DEBUG_STACK) Slog.d(TAG_STACK, "detachLocked: " + this + " from display="
                     + mActivityDisplay + " Callers=" + Debug.getCallers(2));
             if (mActivityDisplay != null) {
                 mActivityDisplay.detachActivitiesLocked(mStack);
@@ -4107,8 +4108,8 @@
 
             setSurfaceIfReadyLocked();
 
-            if (DEBUG_STACK) Slog.d(TAG, "setSurface: " + this + " to display="
-                    + virtualActivityDisplay);
+            if (DEBUG_STACK) Slog.d(TAG_STACK,
+                    "setSurface: " + this + " to display=" + virtualActivityDisplay);
         }
 
         @Override
@@ -4131,7 +4132,7 @@
         }
 
         private void setSurfaceIfReadyLocked() {
-            if (DEBUG_STACK) Slog.v(TAG, "setSurfaceIfReadyLocked: mDrawn=" + mDrawn +
+            if (DEBUG_STACK) Slog.v(TAG_STACK, "setSurfaceIfReadyLocked: mDrawn=" + mDrawn +
                     " mContainerState=" + mContainerState + " mSurface=" + mSurface);
             if (mDrawn && mSurface != null && mContainerState == CONTAINER_STATE_NO_SURFACE) {
                 ((VirtualActivityDisplay) mActivityDisplay).setSurface(mSurface);
@@ -4174,13 +4175,13 @@
         }
 
         void attachActivities(ActivityStack stack) {
-            if (DEBUG_STACK) Slog.v(TAG, "attachActivities: attaching " + stack + " to displayId="
-                    + mDisplayId);
+            if (DEBUG_STACK) Slog.v(TAG_STACK,
+                    "attachActivities: attaching " + stack + " to displayId=" + mDisplayId);
             mStacks.add(stack);
         }
 
         void detachActivitiesLocked(ActivityStack stack) {
-            if (DEBUG_STACK) Slog.v(TAG, "detachActivitiesLocked: detaching " + stack
+            if (DEBUG_STACK) Slog.v(TAG_STACK, "detachActivitiesLocked: detaching " + stack
                     + " from displayId=" + mDisplayId);
             mStacks.remove(stack);
         }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 197b51d..c8db3be 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -16,20 +16,26 @@
 
 package com.android.server.am;
 
+import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.net.wifi.IWifiManager;
+import android.net.wifi.WifiActivityEnergyInfo;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManagerInternal;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -38,10 +44,12 @@
 import android.telephony.TelephonyManager;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.PowerProfile;
+import com.android.server.FgThread;
 import com.android.server.LocalServices;
 
 import java.io.File;
@@ -59,15 +67,52 @@
     static final String TAG = "BatteryStatsService";
 
     static IBatteryStats sService;
-    
     final BatteryStatsImpl mStats;
+    final BatteryStatsHandler mHandler;
     Context mContext;
     private boolean mBluetoothPendingStats;
     private BluetoothHeadset mBluetoothHeadset;
     PowerManagerInternal mPowerManagerInternal;
 
+    class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
+        public static final int MSG_SYNC_EXTERNAL_STATS = 1;
+        public static final int MSG_WRITE_TO_DISK = 2;
+
+        public BatteryStatsHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SYNC_EXTERNAL_STATS:
+                    updateExternalStats();
+                    break;
+
+                case MSG_WRITE_TO_DISK:
+                    updateExternalStats();
+                    synchronized (mStats) {
+                        mStats.writeAsyncLocked();
+                    }
+                    break;
+            }
+        }
+
+        @Override
+        public void scheduleSync() {
+            if (!hasMessages(MSG_SYNC_EXTERNAL_STATS)) {
+                sendEmptyMessage(MSG_SYNC_EXTERNAL_STATS);
+            }
+        }
+    }
+
     BatteryStatsService(File systemDir, Handler handler) {
-        mStats = new BatteryStatsImpl(systemDir, handler);
+        // Our handler here will be accessing the disk, use a different thread than
+        // what the ActivityManagerService gave us (no I/O on that one!).
+        mHandler = new BatteryStatsHandler(FgThread.getHandler().getLooper());
+
+        // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through.
+        mStats = new BatteryStatsImpl(systemDir, handler, mHandler);
     }
     
     public void publish(Context context) {
@@ -92,6 +137,8 @@
 
     public void shutdown() {
         Slog.w("BatteryStats", "Writing battery stats before shutdown...");
+
+        updateExternalStats();
         synchronized (mStats) {
             mStats.shutdownLocked();
         }
@@ -122,6 +169,14 @@
         return mStats;
     }
 
+    /**
+     * Schedules a write to disk to occur. This will cause the BatteryStatsImpl
+     * object to update with the latest info, then write to disk.
+     */
+    public void scheduleWriteToDisk() {
+        mHandler.sendEmptyMessage(BatteryStatsHandler.MSG_WRITE_TO_DISK);
+    }
+
     // These are for direct use by the activity manager...
 
     void addIsolatedUid(int isolatedUid, int appUid) {
@@ -174,7 +229,10 @@
         //Slog.i("foo", "SENDING BATTERY INFO:");
         //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
         Parcel out = Parcel.obtain();
-        mStats.writeToParcel(out, 0);
+        updateExternalStats();
+        synchronized (mStats) {
+            mStats.writeToParcel(out, 0);
+        }
         byte[] data = out.marshall();
         out.recycle();
         return data;
@@ -186,7 +244,10 @@
         //Slog.i("foo", "SENDING BATTERY INFO:");
         //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
         Parcel out = Parcel.obtain();
-        mStats.writeToParcel(out, 0);
+        updateExternalStats();
+        synchronized (mStats) {
+            mStats.writeToParcel(out, 0);
+        }
         byte[] data = out.marshall();
         out.recycle();
         try {
@@ -663,6 +724,7 @@
         }
     }
 
+    @Override
     public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
         enforceCallingPermission();
         synchronized (mStats) {
@@ -671,10 +733,10 @@
     }
 
     @Override
-    public void noteNetworkInterfaceType(String iface, int type) {
+    public void noteNetworkInterfaceType(String iface, int networkType) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteNetworkInterfaceTypeLocked(iface, type);
+            mStats.noteNetworkInterfaceTypeLocked(iface, networkType);
         }
     }
 
@@ -715,7 +777,22 @@
     public void setBatteryState(int status, int health, int plugType, int level,
             int temp, int volt) {
         enforceCallingPermission();
-        mStats.setBatteryState(status, health, plugType, level, temp, volt);
+        synchronized (mStats) {
+            final boolean onBattery = plugType == BatteryStatsImpl.BATTERY_PLUGGED_NONE;
+            if (mStats.isOnBattery() == onBattery) {
+                // The battery state has not changed, so we don't need to sync external
+                // stats immediately.
+                mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
+                return;
+            }
+        }
+
+        // Sync external stats first as the battery has changed states. If we don't sync
+        // immediately here, we may not collect the relevant data later.
+        updateExternalStats();
+        synchronized (mStats) {
+            mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
+        }
     }
     
     public long getAwakeTimeBattery() {
@@ -772,12 +849,11 @@
 
     private void dumpHelp(PrintWriter pw) {
         pw.println("Battery stats (batterystats) dump options:");
-        pw.println("  [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]");
+        pw.println("  [--checkin] [--history] [--history-start] [--charged] [-c]");
         pw.println("  [--daily] [--reset] [--write] [--new-daily] [--read-daily] [-h] [<package.name>]");
         pw.println("  --checkin: format output for a checkin report.");
         pw.println("  --history: show only history data.");
         pw.println("  --history-start <num>: show only history data starting at given time offset.");
-        pw.println("  --unplugged: only output data since last unplugged.");
         pw.println("  --charged: only output data since last charged.");
         pw.println("  --daily: only output full daily data.");
         pw.println("  --reset: reset the stats, clearing all current data.");
@@ -818,6 +894,7 @@
         return i;
     }
 
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -856,8 +933,6 @@
                 } else if ("-c".equals(arg)) {
                     useCheckinFormat = true;
                     flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
-                } else if ("--unplugged".equals(arg)) {
-                    flags |= BatteryStats.DUMP_UNPLUGGED_ONLY;
                 } else if ("--charged".equals(arg)) {
                     flags |= BatteryStats.DUMP_CHARGED_ONLY;
                 } else if ("--daily".equals(arg)) {
@@ -868,7 +943,9 @@
                         pw.println("Battery stats reset.");
                         noOutput = true;
                     }
+                    updateExternalStats();
                 } else if ("--write".equals(arg)) {
+                    updateExternalStats();
                     synchronized (mStats) {
                         mStats.writeSyncLocked();
                         pw.println("Battery stats written.");
@@ -931,13 +1008,16 @@
         if (reqUid >= 0) {
             // By default, if the caller is only interested in a specific package, then
             // we only dump the aggregated data since charged.
-            if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_UNPLUGGED_ONLY
-                    |BatteryStats.DUMP_CHARGED_ONLY)) == 0) {
+            if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_CHARGED_ONLY)) == 0) {
                 flags |= BatteryStats.DUMP_CHARGED_ONLY;
                 // Also if they are doing -c, we don't want history.
                 flags &= ~BatteryStats.DUMP_INCLUDE_HISTORY;
             }
         }
+
+        // Fetch data from external sources and update the BatteryStatsImpl object with them.
+        updateExternalStats();
+
         if (useCheckinFormat) {
             List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
             if (isRealCheckin) {
@@ -952,7 +1032,7 @@
                                 in.unmarshall(raw, 0, raw.length);
                                 in.setDataPosition(0);
                                 BatteryStatsImpl checkinStats = new BatteryStatsImpl(
-                                        null, mStats.mHandler);
+                                        null, mStats.mHandler, null);
                                 checkinStats.readSummaryFromParcel(in);
                                 in.recycle();
                                 checkinStats.dumpCheckinLocked(mContext, pw, apps, flags,
@@ -982,4 +1062,85 @@
             }
         }
     }
+
+    // Objects for extracting data from external sources.
+    private final Object mExternalStatsLock = new Object();
+
+    @GuardedBy("mExternalStatsLock")
+    private IWifiManager mWifiManager;
+
+    // WiFi keeps an accumulated total of stats, unlike Bluetooth.
+    // Keep the last WiFi stats so we can compute a delta.
+    @GuardedBy("mExternalStatsLock")
+    private WifiActivityEnergyInfo mLastInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
+
+    @GuardedBy("mExternalStatsLock")
+    private WifiActivityEnergyInfo pullWifiEnergyInfoLocked() {
+        if (mWifiManager == null) {
+            mWifiManager = IWifiManager.Stub.asInterface(
+                    ServiceManager.getService(Context.WIFI_SERVICE));
+            if (mWifiManager == null) {
+                return null;
+            }
+        }
+
+        try {
+            // We read the data even if we are not on battery. This is so that we keep the
+            // correct delta from when we should start reading (aka when we are on battery).
+            WifiActivityEnergyInfo info = mWifiManager.reportActivityInfo();
+            if (info != null && info.isValid()) {
+                // We will modify the last info object to be the delta, and store the new
+                // WifiActivityEnergyInfo object as our last one.
+                final WifiActivityEnergyInfo result = mLastInfo;
+                result.mTimestamp = info.getTimeStamp();
+                result.mStackState = info.getStackState();
+                result.mControllerTxTimeMs =
+                        info.getControllerTxTimeMillis()- mLastInfo.mControllerTxTimeMs;
+                result.mControllerRxTimeMs =
+                        info.getControllerRxTimeMillis() - mLastInfo.mControllerRxTimeMs;
+                result.mControllerIdleTimeMs =
+                        info.getControllerIdleTimeMillis() - mLastInfo.mControllerIdleTimeMs;
+                result.mControllerEnergyUsed =
+                        info.getControllerEnergyUsed() - mLastInfo.mControllerEnergyUsed;
+                mLastInfo = info;
+                return result;
+            }
+        } catch (RemoteException e) {
+            // Nothing to report, WiFi is dead.
+        }
+        return null;
+    }
+
+    @GuardedBy("mExternalStatsLock")
+    private BluetoothActivityEnergyInfo pullBluetoothEnergyInfoLocked() {
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if (adapter != null) {
+            BluetoothActivityEnergyInfo info = adapter.getControllerActivityEnergyInfo(
+                    BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED);
+            if (info != null && info.isValid()) {
+                return info;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Fetches data from external sources (WiFi controller, bluetooth chipset) and updates
+     * batterystats with that information.
+     *
+     * We first grab a lock specific to this method, then once all the data has been collected,
+     * we grab the mStats lock and update the data.
+     */
+    void updateExternalStats() {
+        synchronized (mExternalStatsLock) {
+            final WifiActivityEnergyInfo wifiEnergyInfo = pullWifiEnergyInfoLocked();
+            final BluetoothActivityEnergyInfo bluetoothEnergyInfo = pullBluetoothEnergyInfoLocked();
+            synchronized (mStats) {
+                mStats.updateKernelWakelocksLocked();
+                mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime());
+                mStats.updateWifiStateLocked(wifiEnergyInfo);
+                mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 7cf3b51..29e14f8 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
@@ -89,10 +90,10 @@
     int curSchedGroup;          // Currently desired scheduling class
     int setSchedGroup;          // Last set to background scheduling class
     int trimMemoryLevel;        // Last selected memory trimming level
-    int curProcState = -1;      // Currently computed process state: ActivityManager.PROCESS_STATE_*
-    int repProcState = -1;      // Last reported process state
-    int setProcState = -1;      // Last set process state in process tracker
-    int pssProcState = -1;      // The proc state we are currently requesting pss for
+    int curProcState = PROCESS_STATE_NONEXISTENT; // Currently computed process state
+    int repProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state
+    int setProcState = PROCESS_STATE_NONEXISTENT; // Last set process state in process tracker
+    int pssProcState = PROCESS_STATE_NONEXISTENT; // Currently requesting pss for
     boolean serviceb;           // Process currently is on the service B list
     boolean serviceHighRam;     // We are forcing to service B list due to its RAM use
     boolean setIsForeground;    // Running foreground UI when last set?
@@ -425,7 +426,7 @@
                         tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList);
                 origBase.makeInactive();
             }
-            baseProcessTracker = tracker.getProcessStateLocked(info.packageName, info.uid,
+            baseProcessTracker = tracker.getProcessStateLocked(info.packageName, uid,
                     info.versionCode, processName);
             baseProcessTracker.makeActive();
             for (int i=0; i<pkgList.size(); i++) {
@@ -433,7 +434,7 @@
                 if (holder.state != null && holder.state != origBase) {
                     holder.state.makeInactive();
                 }
-                holder.state = tracker.getProcessStateLocked(pkgList.keyAt(i), info.uid,
+                holder.state = tracker.getProcessStateLocked(pkgList.keyAt(i), uid,
                         info.versionCode, processName);
                 if (holder.state != baseProcessTracker) {
                     holder.state.makeActive();
@@ -623,7 +624,7 @@
                     versionCode);
             if (baseProcessTracker != null) {
                 holder.state = tracker.getProcessStateLocked(
-                        pkg, info.uid, versionCode, processName);
+                        pkg, uid, versionCode, processName);
                 pkgList.put(pkg, holder);
                 if (holder.state != baseProcessTracker) {
                     holder.state.makeActive();
@@ -670,7 +671,7 @@
                 }
                 pkgList.clear();
                 ProcessStats.ProcessState ps = tracker.getProcessStateLocked(
-                        info.packageName, info.uid, info.versionCode, processName);
+                        info.packageName, uid, info.versionCode, processName);
                 ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder(
                         info.versionCode);
                 holder.state = ps;
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 04912d0..3a20ded 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -16,10 +16,7 @@
 
 package com.android.server.am;
 
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityManagerService.DEBUG_RECENTS;
-import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
+import static com.android.server.am.ActivityManagerDebugConfig.*;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
 
 import android.app.ActivityManager;
@@ -44,6 +41,8 @@
  */
 class RecentTasks extends ArrayList<TaskRecord> {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "RecentTasks" : TAG_AM;
+    private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
+    private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
 
     // Maximum number recent bitmaps to keep in memory.
     private static final int MAX_RECENT_BITMAPS = 3;
@@ -83,8 +82,8 @@
         for (int i = size() - 1; i >= 0; --i) {
             TaskRecord tr = get(i);
             if (tr.userId == userId) {
-                if(DEBUG_TASKS) Slog.i(TAG, "remove RecentTask " + tr
-                        + " when finishing user" + userId);
+                if(DEBUG_TASKS) Slog.i(TAG_TASKS,
+                        "remove RecentTask " + tr + " when finishing user" + userId);
                 remove(i);
                 tr.removedFromRecents();
             }
@@ -170,21 +169,21 @@
                             continue;
                         } else {
                             // Otherwise just not available for now.
-                            if (DEBUG_RECENTS && task.isAvailable) Slog.d(TAG,
+                            if (DEBUG_RECENTS && task.isAvailable) Slog.d(TAG_RECENTS,
                                     "Making recent unavailable: " + task);
                             task.isAvailable = false;
                         }
                     } else {
                         if (!ai.enabled || !ai.applicationInfo.enabled
                                 || (ai.applicationInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
-                            if (DEBUG_RECENTS && task.isAvailable) Slog.d(TAG,
+                            if (DEBUG_RECENTS && task.isAvailable) Slog.d(TAG_RECENTS,
                                     "Making recent unavailable: " + task
                                     + " (enabled=" + ai.enabled + "/" + ai.applicationInfo.enabled
                                     + " flags=" + Integer.toHexString(ai.applicationInfo.flags)
                                     + ")");
                             task.isAvailable = false;
                         } else {
-                            if (DEBUG_RECENTS && !task.isAvailable) Slog.d(TAG,
+                            if (DEBUG_RECENTS && !task.isAvailable) Slog.d(TAG_RECENTS,
                                     "Making recent available: " + task);
                             task.isAvailable = true;
                         }
@@ -210,7 +209,7 @@
             top = top.mNextAffiliate;
             topIndex--;
         }
-        if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: adding affilliates starting at "
+        if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding affilliates starting at "
                 + topIndex + " from intial " + taskIndex);
         // Find the end of the chain, doing a sanity check along the way.
         boolean sane = top.mAffiliatedTaskId == task.mAffiliatedTaskId;
@@ -218,7 +217,7 @@
         TaskRecord prev = top;
         while (endIndex < recentsCount) {
             TaskRecord cur = get(endIndex);
-            if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: looking at next chain @"
+            if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: looking at next chain @"
                     + endIndex + " " + cur);
             if (cur == top) {
                 // Verify start of the chain.
@@ -249,7 +248,7 @@
                             + cur.mPrevAffiliate);
                     sane = false;
                 }
-                if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: end of chain @" + endIndex);
+                if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: end of chain @" + endIndex);
                 break;
             } else {
                 // Verify middle of the chain's prev points to a valid item.
@@ -290,12 +289,12 @@
             // All looks good, we can just move all of the affiliated tasks
             // to the top.
             for (int i=topIndex; i<=endIndex; i++) {
-                if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: moving affiliated " + task
+                if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving affiliated " + task
                         + " from " + i + " to " + (i-topIndex));
                 TaskRecord cur = remove(i);
                 add(i - topIndex, cur);
             }
-            if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: done moving tasks  " +  topIndex
+            if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: done moving tasks  " +  topIndex
                     + " to " + endIndex);
             return true;
         }
@@ -312,19 +311,20 @@
         int recentsCount = size();
         // Quick case: never add voice sessions.
         if (task.voiceSession != null) {
-            if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: not adding voice interaction " + task);
+            if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+                    "addRecent: not adding voice interaction " + task);
             return;
         }
         // Another quick case: check if the top-most recent task is the same.
         if (!isAffiliated && recentsCount > 0 && get(0) == task) {
-            if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: already at top: " + task);
+            if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: already at top: " + task);
             return;
         }
         // Another quick case: check if this is part of a set of affiliated
         // tasks that are at the top.
         if (isAffiliated && recentsCount > 0 && task.inRecents
                 && task.mAffiliatedTaskId == get(0).mAffiliatedTaskId) {
-            if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: affiliated " + get(0)
+            if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: affiliated " + get(0)
                     + " at top when adding " + task);
             return;
         }
@@ -341,7 +341,7 @@
                     remove(taskIndex);
                     add(0, task);
                     mService.notifyTaskPersisterLocked(task, false);
-                    if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: moving to top " + task
+                    if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving to top " + task
                             + " from " + taskIndex);
                     return;
                 } else {
@@ -361,7 +361,7 @@
             }
         }
 
-        if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: trimming tasks for " + task);
+        if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: trimming tasks for " + task);
         trimForTaskLocked(task, true);
 
         recentsCount = size();
@@ -376,7 +376,7 @@
             // If this is a simple non-affiliated task, or we had some failure trying to
             // handle it as part of an affilated task, then just place it at the top.
             add(0, task);
-            if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: adding " + task);
+            if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding " + task);
         } else if (isAffiliated) {
             // If this is a new affiliated task, then move all of the affiliated tasks
             // to the front and insert this new one.
@@ -398,8 +398,8 @@
                         // after us in the list, so add at their position.
                         taskIndex = otherIndex;
                     }
-                    if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: new affiliated task added at "
-                            + taskIndex + ": " + task);
+                    if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+                            "addRecent: new affiliated task added at " + taskIndex + ": " + task);
                     add(taskIndex, task);
 
                     // Now move everything to the front.
@@ -412,19 +412,19 @@
                     // everything and then go through our general path of adding a new task.
                     needAffiliationFix = true;
                 } else {
-                    if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: couldn't find other affiliation "
-                            + other);
+                    if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+                            "addRecent: couldn't find other affiliation " + other);
                     needAffiliationFix = true;
                 }
             } else {
-                if (DEBUG_RECENTS) Slog.d(TAG,
+                if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
                         "addRecent: adding affiliated task without next/prev:" + task);
                 needAffiliationFix = true;
             }
         }
 
         if (needAffiliationFix) {
-            if (DEBUG_RECENTS) Slog.d(TAG, "addRecent: regrouping affiliations");
+            if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: regrouping affiliations");
             cleanupLocked(task.userId);
         }
     }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index d8d361b..82e6d47 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -16,8 +16,9 @@
 
 package com.android.server.am;
 
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
+import static com.android.server.am.ActivityManagerDebugConfig.*;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
@@ -56,6 +57,8 @@
 
 final class TaskRecord {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
+    private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
+    private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
 
     static final String ATTR_TASKID = "task_id";
     private static final String TAG_INTENT = "intent";
@@ -310,8 +313,7 @@
                     _intent.setSourceBounds(null);
                 }
             }
-            if (ActivityManagerService.DEBUG_TASKS) Slog.v(TAG,
-                    "Setting Intent of " + this + " to " + _intent);
+            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
             intent = _intent;
             realActivity = _intent != null ? _intent.getComponent() : null;
             origActivity = null;
@@ -323,7 +325,7 @@
                 targetIntent.setComponent(targetComponent);
                 targetIntent.setSelector(null);
                 targetIntent.setSourceBounds(null);
-                if (ActivityManagerService.DEBUG_TASKS) Slog.v(TAG,
+                if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                         "Setting Intent of " + this + " to target " + targetIntent);
                 intent = targetIntent;
                 realActivity = targetComponent;
@@ -346,8 +348,8 @@
         if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
             // If the activity itself has requested auto-remove, then just always do it.
             autoRemoveRecents = true;
-        } else if ((intentFlags & (Intent.FLAG_ACTIVITY_NEW_DOCUMENT
-                | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS)) == Intent.FLAG_ACTIVITY_NEW_DOCUMENT) {
+        } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
+                == FLAG_ACTIVITY_NEW_DOCUMENT) {
             // If the caller has not asked for the document to be retained, then we may
             // want to turn on auto-remove, depending on whether the target has set its
             // own document launch mode.
@@ -819,7 +821,7 @@
     }
 
     void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
-        if (ActivityManagerService.DEBUG_RECENTS) Slog.i(TAG, "Saving task=" + this);
+        if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
 
         out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
         if (realActivity != null) {
@@ -879,7 +881,8 @@
         for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
             final ActivityRecord r = activities.get(activityNdx);
             if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
-                    ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) &&
+                    ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
+                            | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
                             activityNdx > 0) {
                 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
                 break;
@@ -1045,7 +1048,7 @@
             activities.get(activityNdx).task = task;
         }
 
-        if (ActivityManagerService.DEBUG_RECENTS) Slog.d(TAG, "Restored task=" + task);
+        if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
         return task;
     }
 
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 65b2ae2..1eddc8e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -234,9 +234,6 @@
     private final Object mSoundEffectsLock = new Object();
     private static final int NUM_SOUNDPOOL_CHANNELS = 4;
 
-    // Maximum volume adjust steps allowed in a single batch call.
-    private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4;
-
     /* Sound effect file names  */
     private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
     private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
@@ -988,6 +985,7 @@
         } else {
             streamType = getActiveStreamType(suggestedStreamType);
         }
+        ensureValidStreamType(streamType);
         final int resolvedStream = mStreamVolumeAlias[streamType];
 
         // Play sounds on STREAM_RING only.
@@ -1421,6 +1419,8 @@
     private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
         if (!isPlatformVoice() && (streamType == AudioSystem.STREAM_RING)) {
             streamType = AudioSystem.STREAM_NOTIFICATION;
+        } else {
+            streamType = mStreamVolumeAlias[streamType];
         }
 
         if (streamType == AudioSystem.STREAM_MUSIC) {
@@ -3131,12 +3131,6 @@
         }
     }
 
-    private void ensureValidSteps(int steps) {
-        if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) {
-            throw new IllegalArgumentException("Bad volume adjust steps " + steps);
-        }
-    }
-
     private void ensureValidStreamType(int streamType) {
         if (streamType < 0 || streamType >= mStreamStates.length) {
             throw new IllegalArgumentException("Bad stream type " + streamType);
@@ -3305,7 +3299,7 @@
     }
 
     private int getDeviceForStream(int stream) {
-        int device = AudioSystem.getDevicesForStream(stream);
+        int device = getDevicesForStream(stream);
         if ((device & (device - 1)) != 0) {
             // Multiple device selection is either:
             //  - speaker + one other device: give priority to speaker in this case.
@@ -3328,6 +3322,27 @@
         return device;
     }
 
+    private int getDevicesForStream(int stream) {
+        return getDevicesForStream(stream, true /*checkOthers*/);
+    }
+
+    private int getDevicesForStream(int stream, boolean checkOthers) {
+        ensureValidStreamType(stream);
+        synchronized (VolumeStreamState.class) {
+            return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
+        }
+    }
+
+    private void observeDevicesForStreams(int skipStream) {
+        synchronized (VolumeStreamState.class) {
+            for (int stream = 0; stream < mStreamStates.length; stream++) {
+                if (stream != skipStream) {
+                    mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
+                }
+            }
+        }
+    }
+
     /*
      * A class just for packaging up a set of connection parameters.
      */
@@ -3406,9 +3421,11 @@
 
         private boolean mIsMuted;
         private String mVolumeIndexSettingName;
+        private int mObservedDevices;
 
         private final SparseIntArray mIndexMap = new SparseIntArray(8);
         private final Intent mVolumeChanged;
+        private final Intent mStreamDevicesChanged;
 
         private VolumeStreamState(String settingName, int streamType) {
 
@@ -3422,6 +3439,29 @@
             readSettings();
             mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
             mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
+            mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
+            mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
+        }
+
+        public int observeDevicesForStream_syncVSS(boolean checkOthers) {
+            final int devices = AudioSystem.getDevicesForStream(mStreamType);
+            if (devices == mObservedDevices) {
+                return devices;
+            }
+            final int prevDevices = mObservedDevices;
+            mObservedDevices = devices;
+            if (checkOthers) {
+                // one stream's devices have changed, check the others
+                observeDevicesForStreams(mStreamType);
+            }
+            // log base stream changes to the event log
+            if (mStreamVolumeAlias[mStreamType] == mStreamType) {
+                EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
+            }
+            sendBroadcastToAll(mStreamDevicesChanged
+                    .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
+                    .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
+            return devices;
         }
 
         public String getSettingNameForDevice(int device) {
@@ -3716,7 +3756,7 @@
             }
             pw.println();
             pw.print("   Devices: ");
-            final int devices = AudioSystem.getDevicesForStream(mStreamType);
+            final int devices = getDevicesForStream(mStreamType);
             int device, i = 0, n = 0;
             // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
             // (the default device is not returned by getDevicesForStream)
@@ -4250,6 +4290,7 @@
                         }
                     }
                     mRoutesObservers.finishBroadcast();
+                    observeDevicesForStreams(-1);
                     break;
                 }
 
@@ -5348,7 +5389,7 @@
                                 on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
                                      AudioSystem.FORCE_NONE);
                     }
-                    device = AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
+                    device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index f05e6aa..4ccb5ad 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -63,8 +63,10 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.Stack;
+import java.text.DateFormat;
 
 /**
  * @hide
@@ -124,6 +126,8 @@
     }
 
     protected void dump(PrintWriter pw) {
+        pw.println("\nMediaFocusControl dump time: "
+                + DateFormat.getTimeInstance().format(new Date()));
         dumpFocusStack(pw);
         dumpRCStack(pw);
         dumpRCCStack(pw);
diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java
new file mode 100644
index 0000000..f9b17ed
--- /dev/null
+++ b/services/core/java/com/android/server/camera/CameraService.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 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.camera;
+
+import android.content.Context;
+import android.hardware.ICameraService;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.server.SystemService;
+
+/**
+ * CameraService is the system_server analog to the camera service running in mediaserver.
+ *
+ * @hide
+ */
+public class CameraService extends SystemService {
+
+    /**
+     * This must match the ICameraService.aidl definition
+     */
+    private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
+
+    // Event arguments to use with the camera service notifySystemEvent call:
+    public static final int NO_EVENT = 0; // NOOP
+    public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle
+
+    public CameraService(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void onStart() {}
+
+    @Override
+    public void onSwitchUser(int userHandle) {
+        super.onSwitchUser(userHandle);
+
+        /**
+         * Forward the user switch event to the native camera service running in mediaserver.
+         */
+        IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
+        if (cameraServiceBinder == null) {
+            return; // Camera service not active, there is no need to evict user clients.
+        }
+        ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
+        try {
+            cameraServiceRaw.notifySystemEvent(USER_SWITCHED, userHandle);
+        } catch (RemoteException e) {
+            // Do nothing, if camera service is dead, there is no need to evict user clients.
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 7f47678..0b430ea 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1021,6 +1021,14 @@
     public synchronized LegacyVpnInfo getLegacyVpnInfo() {
         // Check if the caller is authorized.
         enforceControlPermission();
+        return getLegacyVpnInfoPrivileged();
+    }
+
+    /**
+     * Return the information of the current ongoing legacy VPN.
+     * Callers are responsible for checking permissions if needed.
+     */
+    public synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() {
         if (mLegacyVpnRunner == null) return null;
 
         final LegacyVpnInfo info = new LegacyVpnInfo();
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index b398f41..fd75077 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -16,25 +16,30 @@
 
 package com.android.server.fingerprint;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.RemoteException;
-import android.service.fingerprint.FingerprintManager;
 import android.util.ArrayMap;
 import android.util.Slog;
 
 import com.android.server.SystemService;
 
-import android.service.fingerprint.FingerprintUtils;
-import android.service.fingerprint.IFingerprintService;
-import android.service.fingerprint.IFingerprintServiceReceiver;
+import android.hardware.fingerprint.FingerprintUtils;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.IFingerprintService;
+import android.hardware.fingerprint.IFingerprintServiceReceiver;
+
 import static android.Manifest.permission.MANAGE_FINGERPRINT;
 import static android.Manifest.permission.USE_FINGERPRINT;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A service to manage multiple clients that want to access the fingerprint HAL API.
@@ -50,11 +55,14 @@
 
     private static final int MSG_NOTIFY = 10;
 
+    private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute
+
     Handler mHandler = new Handler() {
         public void handleMessage(android.os.Message msg) {
             switch (msg.what) {
                 case MSG_NOTIFY:
-                    handleNotify(msg.arg1, msg.arg2, (Integer) msg.obj);
+                    FpHalMsg m = (FpHalMsg) msg.obj;
+                    handleNotify(m.type, m.arg1, m.arg2, m.arg3);
                     break;
 
                 default:
@@ -66,7 +74,7 @@
     private int mHalDeviceId;
 
     private static final int STATE_IDLE = 0;
-    private static final int STATE_LISTENING = 1;
+    private static final int STATE_AUTHENTICATING = 1;
     private static final int STATE_ENROLLING = 2;
     private static final int STATE_REMOVING = 3;
     private static final long MS_PER_SEC = 1000;
@@ -76,7 +84,10 @@
         int state;
         int userId;
         public TokenWatcher tokenWatcher;
-        IBinder getToken() { return tokenWatcher.getToken(); }
+
+        IBinder getToken() {
+            return tokenWatcher.getToken();
+        }
     }
 
     private class TokenWatcher implements IBinder.DeathRecipient {
@@ -86,7 +97,10 @@
             this.token = new WeakReference<IBinder>(token);
         }
 
-        IBinder getToken() { return token.get(); }
+        IBinder getToken() {
+            return token.get();
+        }
+
         public void binderDied() {
             mClients.remove(token);
             this.token = null;
@@ -112,21 +126,42 @@
 
     // TODO: Move these into separate process
     // JNI methods to communicate from FingerprintManagerService to HAL
-    static native int nativeEnroll(int timeout);
+    static native int nativeEnroll(int timeout, int groupId);
+
+    static native int nativeAuthenticate(long sessionId, int groupId);
+
     static native int nativeEnrollCancel();
-    static native int nativeRemove(int fingerprintId);
+
+    static native int nativeRemove(int fingerId, int groupId);
+
     static native int nativeOpenHal();
+
     static native int nativeCloseHal();
+
     static native void nativeInit(MessageQueue queue, FingerprintService service);
 
-    // JNI methods for communicating from HAL to clients
-    void notify(int msg, int arg1, int arg2) {
-        mHandler.obtainMessage(MSG_NOTIFY, msg, arg1, arg2).sendToTarget();
+    static final class FpHalMsg {
+        int type; // Type of the message. One of the constants in fingerprint.h
+        int arg1; // optional arguments
+        int arg2;
+        int arg3;
+
+        FpHalMsg(int type, int arg1, int arg2, int arg3) {
+            this.type = type;
+            this.arg1 = arg1;
+            this.arg2 = arg2;
+            this.arg3 = arg3;
+        }
     }
 
-    void handleNotify(int msg, int arg1, int arg2) {
-        Slog.v(TAG, "handleNotify(msg=" + msg + ", arg1=" + arg1 + ", arg2=" + arg2 + ")"
-                + ", " + mClients.size() + " clients");
+    // JNI methods for communicating from HAL to clients
+    void notify(int type, int arg1, int arg2, int arg3) {
+        mHandler.obtainMessage(MSG_NOTIFY, new FpHalMsg(type, arg1, arg2, arg3)).sendToTarget();
+    }
+
+    void handleNotify(int type, int arg1, int arg2, int arg3) {
+        Slog.v(TAG, "handleNotify(type=" + type + ", arg1=" + arg1 + ", arg2=" + arg2 + ")" + ", "
+                + mClients.size() + " clients");
         for (int i = 0; i < mClients.size(); i++) {
             if (DEBUG) Slog.v(TAG, "Client[" + i + "] binder token: " + mClients.keyAt(i));
             ClientData clientData = mClients.valueAt(i);
@@ -134,21 +169,20 @@
                 if (DEBUG) Slog.v(TAG, "clientData is invalid!!");
                 continue;
             }
-            switch (msg) {
+            ContentResolver contentResolver = mContext.getContentResolver();
+            switch (type) {
                 case FingerprintManager.FINGERPRINT_ERROR: {
-                    final int error = arg1;
                     try {
-                        clientData.receiver.onError(error);
+                        clientData.receiver.onError(mHalDeviceId, arg1 /* error */);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "can't send message to client. Did it die?", e);
                         mClients.remove(mClients.keyAt(i));
                     }
                 }
-                break;
+                    break;
                 case FingerprintManager.FINGERPRINT_ACQUIRED: {
-                    final int acquireInfo = arg1;
                     try {
-                        clientData.receiver.onAcquired(acquireInfo);
+                        clientData.receiver.onAcquired(mHalDeviceId, arg1 /* acquireInfo */);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "can't send message to client. Did it die?", e);
                         mClients.remove(mClients.keyAt(i));
@@ -156,9 +190,9 @@
                     break;
                 }
                 case FingerprintManager.FINGERPRINT_PROCESSED: {
-                    final int fingerId = arg1;
                     try {
-                        clientData.receiver.onProcessed(fingerId);
+                        clientData.receiver
+                                .onProcessed(mHalDeviceId, arg1 /* fingerId */, arg2 /* groupId */);
                     } catch (RemoteException e) {
                         Slog.e(TAG, "can't send message to client. Did it die?", e);
                         mClients.remove(mClients.keyAt(i));
@@ -167,11 +201,13 @@
                 }
                 case FingerprintManager.FINGERPRINT_TEMPLATE_ENROLLING: {
                     final int fingerId = arg1;
-                    final int remaining = arg2;
+                    final int groupId = arg2;
+                    final int remaining = arg3;
                     if (clientData.state == STATE_ENROLLING) {
                         // Only send enroll updates to clients that are actually enrolling
                         try {
-                            clientData.receiver.onEnrollResult(fingerId, remaining);
+                            clientData.receiver.onEnrollResult(mHalDeviceId, fingerId, groupId,
+                                    remaining);
                         } catch (RemoteException e) {
                             Slog.e(TAG, "can't send message to client. Did it die?", e);
                             mClients.remove(mClients.keyAt(i));
@@ -179,8 +215,8 @@
                         // Update the database with new finger id.
                         // TODO: move to client code (Settings)
                         if (remaining == 0) {
-                            FingerprintUtils.addFingerprintIdForUser(fingerId,
-                                    mContext.getContentResolver(), clientData.userId);
+                            FingerprintUtils.addFingerprintIdForUser(contentResolver, fingerId,
+                                    clientData.userId);
                             clientData.state = STATE_IDLE; // Nothing left to do
                         }
                     } else {
@@ -191,30 +227,50 @@
                 }
                 case FingerprintManager.FINGERPRINT_TEMPLATE_REMOVED: {
                     int fingerId = arg1;
-                    if (fingerId == 0) throw new IllegalStateException("Got illegal id from HAL");
-                    FingerprintUtils.removeFingerprintIdForUser(fingerId,
-                            mContext.getContentResolver(), clientData.userId);
+                    int groupId = arg2;
+                    if (fingerId == 0) {
+                        throw new IllegalStateException("Got illegal id from HAL");
+                    }
+                    FingerprintUtils.removeFingerprintIdForUser(fingerId, contentResolver,
+                            clientData.userId);
                     if (clientData.receiver != null) {
                         try {
-                            clientData.receiver.onRemoved(fingerId);
+                            clientData.receiver.onRemoved(mHalDeviceId, fingerId, groupId);
                         } catch (RemoteException e) {
                             Slog.e(TAG, "can't send message to client. Did it die?", e);
                             mClients.remove(mClients.keyAt(i));
                         }
                     }
-                    clientData.state = STATE_LISTENING;
+                    clientData.state = STATE_IDLE;
                 }
-                break;
+                    break;
             }
         }
     }
 
-    void startEnroll(IBinder token, long timeout, int userId) {
+    void startEnroll(IBinder token, int groupId, int flags) {
         ClientData clientData = mClients.get(token);
         if (clientData != null) {
-            if (clientData.userId != userId) throw new IllegalStateException("Bad user");
+            if (clientData.userId != groupId) {
+                throw new IllegalStateException("Bad user");
+            }
             clientData.state = STATE_ENROLLING;
-            nativeEnroll((int) (timeout / MS_PER_SEC));
+            final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
+            nativeEnroll(timeout, groupId);
+        } else {
+            Slog.w(TAG, "enroll(): No listener registered");
+        }
+    }
+
+    void startAuthenticate(IBinder token, long sessionId, int groupId, int flags) {
+        ClientData clientData = mClients.get(token);
+        if (clientData != null) {
+            if (clientData.userId != groupId) {
+                throw new IllegalStateException("Bad user");
+            }
+            clientData.state = STATE_AUTHENTICATING;
+            final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
+            nativeAuthenticate(sessionId, groupId);
         } else {
             Slog.w(TAG, "enroll(): No listener registered");
         }
@@ -224,7 +280,7 @@
         ClientData clientData = mClients.get(token);
         if (clientData != null) {
             if (clientData.userId != userId) throw new IllegalStateException("Bad user");
-            clientData.state = STATE_LISTENING;
+            clientData.state = STATE_IDLE;
             nativeEnrollCancel();
         } else {
             Slog.w(TAG, "enrollCancel(): No listener registered");
@@ -238,7 +294,7 @@
             if (clientData.userId != userId) throw new IllegalStateException("Bad user");
             clientData.state = STATE_REMOVING;
             // The fingerprint id will be removed when we get confirmation from the HAL
-            int result = nativeRemove(fingerId);
+            int result = nativeRemove(fingerId, userId);
             if (result != 0) {
                 Slog.w(TAG, "Error removing fingerprint with id = " + fingerId);
             }
@@ -251,7 +307,7 @@
         if (DEBUG) Slog.v(TAG, "startListening(" + receiver + ")");
         if (mClients.get(token) == null) {
             ClientData clientData = new ClientData();
-            clientData.state = STATE_LISTENING;
+            clientData.state = STATE_IDLE;
             clientData.receiver = receiver;
             clientData.userId = userId;
             clientData.tokenWatcher = new TokenWatcher(token);
@@ -266,7 +322,7 @@
         }
     }
 
-    void removeListener(IBinder token, int userId) {
+    void removeListener(IBinder token, IFingerprintServiceReceiver receiver) {
         if (DEBUG) Slog.v(TAG, "stopListening(" + token + ")");
         ClientData clientData = mClients.get(token);
         if (clientData != null) {
@@ -278,61 +334,91 @@
         mClients.remove(token);
     }
 
+    public List<Fingerprint> getEnrolledFingerprints(int groupId) {
+        ContentResolver resolver = mContext.getContentResolver();
+        int[] ids = FingerprintUtils.getFingerprintIdsForUser(resolver, groupId);
+        List<Fingerprint> result = new ArrayList<Fingerprint>();
+        for (int i = 0; i < ids.length; i++) {
+            // TODO: persist names in Settings
+            CharSequence name = "Finger" + ids[i];
+            final int group = 0; // TODO
+            final int fingerId = ids[i];
+            final long deviceId = 0; // TODO
+            Fingerprint item = new Fingerprint(name, 0, ids[i], 0);
+            result.add(item);
+        }
+        return result;
+    }
+
     void checkPermission(String permission) {
-        getContext().enforceCallingOrSelfPermission(permission, "Must have "
-                + permission + " permission.");
+        getContext().enforceCallingOrSelfPermission(permission,
+                "Must have " + permission + " permission.");
     }
 
     private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
-        @Override // Binder call
-        public void enroll(IBinder token, long timeout, int userId) {
+        @Override
+        // Binder call
+        public void enroll(IBinder token, int groupId, int flags) {
             checkPermission(MANAGE_FINGERPRINT);
-            startEnroll(token, timeout, userId);
-        }
-
-        @Override // Binder call
-        public void enrollCancel(IBinder token,int userId) {
-            checkPermission(MANAGE_FINGERPRINT);
-            startEnrollCancel(token, userId);
-        }
-
-        @Override // Binder call
-        public void remove(IBinder token, int fingerprintId, int userId) {
-            checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
-            startRemove(token, fingerprintId, userId);
-        }
-
-        @Override // Binder call
-        public void startListening(IBinder token, IFingerprintServiceReceiver receiver, int userId)
-        {
-            checkPermission(USE_FINGERPRINT);
-            addListener(token, receiver, userId);
-        }
-
-        @Override // Binder call
-        public void stopListening(IBinder token, int userId) {
-            checkPermission(USE_FINGERPRINT);
-            removeListener(token, userId);
-        }
-
-        @Override // Binder call
-        public boolean isHardwareDetected() {
-            checkPermission(USE_FINGERPRINT);
-            return mHalDeviceId != 0;
+            startEnroll(token, groupId, flags);
         }
 
         @Override
-        public void rename(int fpId, String name) {
+        // Binder call
+        public void authenticate(IBinder token, long sessionId, int groupId, int flags) {
+            checkPermission(USE_FINGERPRINT);
+            startAuthenticate(token, sessionId, groupId, flags);
+        }
+
+        @Override
+        // Binder call
+        public void remove(IBinder token, int fingerId, int groupId) {
+            checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
+            startRemove(token, fingerId, groupId);
+        }
+
+        @Override
+        // Binder call
+        public void addListener(IBinder token, IFingerprintServiceReceiver receiver, int userId) {
+            checkPermission(USE_FINGERPRINT);
+            FingerprintService.this.addListener(token, receiver, userId);
+        }
+
+        @Override
+        // Binder call
+        public void removeListener(IBinder token, IFingerprintServiceReceiver receiver) {
+            checkPermission(USE_FINGERPRINT);
+            FingerprintService.this.removeListener(token, receiver);
+        }
+
+        @Override
+        // Binder call
+        public boolean isHardwareDetected(long deviceId) {
+            checkPermission(USE_FINGERPRINT);
+            return mHalDeviceId != 0; // TODO
+        }
+
+        @Override
+        // Binder call
+        public void rename(int fingerId, int groupId, String name) {
             checkPermission(MANAGE_FINGERPRINT);
+            Slog.w(TAG, "rename id=" + fingerId + ",gid=" + groupId + ",name=" + name);
             // TODO
         }
+
+        @Override
+        // Binder call
+        public List<Fingerprint> getEnrolledFingerprints(int groupId) {
+            checkPermission(USE_FINGERPRINT);
+            return FingerprintService.this.getEnrolledFingerprints(groupId);
+        }
     }
 
     @Override
     public void onStart() {
-       publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
-       mHalDeviceId = nativeOpenHal();
-       if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
+        publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
+        mHalDeviceId = nativeOpenHal();
+        if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
     }
 
 }
diff --git a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
index 7f48768..01547c1 100644
--- a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
+++ b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
@@ -68,8 +68,12 @@
         }
 
         if (!tv.isProhibitMode()) {
+            ActiveSource old = ActiveSource.of(tv.getActiveSource());
             tv.updateActiveSource(newActive);
             boolean notifyInputChange = (mCallback == null);
+            if (!old.equals(newActive)) {
+                tv.setPrevPortId(tv.getActivePortId());
+            }
             tv.updateActiveInput(newActive.physicalAddress, notifyInputChange);
             invokeCallback(HdmiControlManager.RESULT_SUCCESS);
         } else {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index d17e9b3..b24bc65 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -71,6 +71,9 @@
             logicalAddress = logical;
             physicalAddress = physical;
         }
+        public static ActiveSource of(ActiveSource source) {
+            return new ActiveSource(source.logicalAddress, source.physicalAddress);
+        }
         public static ActiveSource of(int logical, int physical) {
             return new ActiveSource(logical, physical);
         }
@@ -102,10 +105,10 @@
             StringBuffer s = new StringBuffer();
             String logicalAddressString = (logicalAddress == Constants.ADDR_INVALID)
                     ? "invalid" : String.format("0x%02x", logicalAddress);
-            s.append("logical_address: ").append(logicalAddressString);
+            s.append("(").append(logicalAddressString);
             String physicalAddressString = (physicalAddress == Constants.INVALID_PHYSICAL_ADDRESS)
                     ? "invalid" : String.format("0x%04x", physicalAddress);
-            s.append(", physical_address: ").append(physicalAddressString);
+            s.append(", ").append(physicalAddressString).append(")");
             return s.toString();
         }
     }
@@ -636,7 +639,7 @@
     void addAndStartAction(final HdmiCecFeatureAction action) {
         assertRunOnServiceThread();
         mActions.add(action);
-        if (mService.isPowerStandbyOrTransient()) {
+        if (mService.isPowerStandby()) {
             Slog.i(TAG, "Not ready to start action. Queued for deferred start:" + action);
             return;
         }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 70fa441..89ffe45 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -192,6 +192,13 @@
         }
     }
 
+    @ServiceThreadOnly
+    protected boolean handleUserControlPressed(HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        wakeUpIfActiveSource();
+        return super.handleUserControlPressed(message);
+    }
+
     @Override
     @ServiceThreadOnly
     protected boolean handleSetStreamPath(HdmiCecMessage message) {
@@ -229,7 +236,12 @@
     }
 
     private void wakeUpIfActiveSource() {
-        if (mIsActiveSource && mService.isPowerStandbyOrTransient()) {
+        if (!mIsActiveSource) {
+            return;
+        }
+        // Wake up the device if the power is in standby mode, or its screen is off -
+        // which can happen if the device is holding a partial lock.
+        if (mService.isPowerStandbyOrTransient() || !mService.getPowerManager().isScreenOn()) {
             mService.wakeUp();
         }
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 7c93e56..4ac2b48 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -45,6 +45,7 @@
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
@@ -71,9 +72,8 @@
     @ServiceThreadOnly
     private boolean mArcEstablished = false;
 
-    // Whether ARC feature is enabled or not. The default value is true.
-    // TODO: once adding system setting for it, read the value to it.
-    private boolean mArcFeatureEnabled = true;
+    // Stores whether ARC feature is enabled per port. True by default for all the ARC-enabled ports.
+    private final SparseBooleanArray mArcFeatureEnabled = new SparseBooleanArray();
 
     // Whether System audio mode is activated or not.
     // This becomes true only when all system audio sequences are finished.
@@ -190,6 +190,10 @@
     @ServiceThreadOnly
     protected void onAddressAllocated(int logicalAddress, int reason) {
         assertRunOnServiceThread();
+        List<HdmiPortInfo> ports = mService.getPortInfo();
+        for (HdmiPortInfo port : ports) {
+            mArcFeatureEnabled.put(port.getId(), port.isArcSupported());
+        }
         mService.registerTvInputCallback(mTvInputCallback);
         mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
                 mAddress, mService.getPhysicalAddress(), mDeviceType));
@@ -251,7 +255,9 @@
         }
         int targetAddress = targetDevice.getLogicalAddress();
         ActiveSource active = getActiveSource();
-        if (active.isValid() && targetAddress == active.logicalAddress) {
+        if (targetDevice.getDevicePowerStatus() == HdmiControlManager.POWER_STATUS_ON
+                && active.isValid()
+                && targetAddress == active.logicalAddress) {
             invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS);
             return;
         }
@@ -341,7 +347,6 @@
     void updateActiveInput(int path, boolean notifyInputChange) {
         assertRunOnServiceThread();
         // Seq #15
-        setPrevPortId(getActivePortId());
         setActivePath(path);
         // TODO: Handle PAP/PIP case.
         // Show OSD port change banner
@@ -780,6 +785,8 @@
                         HdmiDeviceInfo avr = getAvrDeviceInfo();
                         if (avr != null) {
                             onNewAvrAdded(avr);
+                        } else {
+                            setSystemAudioMode(false, true);
                         }
                     }
                 });
@@ -792,7 +799,8 @@
         if (getSystemAudioModeSetting() && !isSystemAudioActivated()) {
             addAndStartAction(new SystemAudioAutoInitiationAction(this, avr.getLogicalAddress()));
         }
-        if (isArcFeatureEnabled() && !hasAction(SetArcTransmissionStateAction.class)) {
+        if (isArcFeatureEnabled(avr.getPortId())
+                && !hasAction(SetArcTransmissionStateAction.class)) {
             startArcAction(true);
         }
     }
@@ -901,7 +909,7 @@
         // Should not activate ARC if +5V status is false.
         HdmiPortInfo portInfo = mService.getPortInfo(portId);
         if (portInfo.isArcSupported()) {
-            changeArcFeatureEnabled(isConnected);
+            changeArcFeatureEnabled(portId, isConnected);
         }
     }
 
@@ -913,20 +921,25 @@
     }
 
     /**
-     * Returns whether ARC is enabled or not.
+     * Returns true if ARC is currently established on a certain port.
      */
     @ServiceThreadOnly
-    boolean isArcEstabilished() {
+    boolean isArcEstablished() {
         assertRunOnServiceThread();
-        return mArcFeatureEnabled && mArcEstablished;
+        if (mArcEstablished) {
+            for (int i = 0; i < mArcFeatureEnabled.size(); i++) {
+                if (mArcFeatureEnabled.valueAt(i)) return true;
+            }
+        }
+        return false;
     }
 
     @ServiceThreadOnly
-    void changeArcFeatureEnabled(boolean enabled) {
+    void changeArcFeatureEnabled(int portId, boolean enabled) {
         assertRunOnServiceThread();
 
-        if (mArcFeatureEnabled != enabled) {
-            mArcFeatureEnabled = enabled;
+        if (mArcFeatureEnabled.get(portId) != enabled) {
+            mArcFeatureEnabled.put(portId, enabled);
             if (enabled) {
                 if (!mArcEstablished) {
                     startArcAction(true);
@@ -940,9 +953,9 @@
     }
 
     @ServiceThreadOnly
-    boolean isArcFeatureEnabled() {
+    boolean isArcFeatureEnabled(int portId) {
         assertRunOnServiceThread();
-        return mArcFeatureEnabled;
+        return mArcFeatureEnabled.get(portId);
     }
 
     @ServiceThreadOnly
@@ -1077,7 +1090,7 @@
                 && isConnectedToArcPort(avr.getPhysicalAddress())
                 && isDirectConnectAddress(avr.getPhysicalAddress())) {
             if (shouldCheckArcFeatureEnabled) {
-                return isArcFeatureEnabled();
+                return isArcFeatureEnabled(avr.getPortId());
             } else {
                 return true;
             }
@@ -1570,7 +1583,6 @@
     @Override
     @ServiceThreadOnly
     protected void disableDevice(boolean initiatedByCec, PendingActionClearedCallback callback) {
-        super.disableDevice(initiatedByCec, callback);
         assertRunOnServiceThread();
         mService.unregisterTvInputCallback(mTvInputCallback);
         // Remove any repeated working actions.
@@ -1586,6 +1598,8 @@
 
         disableSystemAudioIfExist();
         disableArcIfExist();
+
+        super.disableDevice(initiatedByCec, callback);
         clearDeviceInfoList();
         checkIfPendingActionsCleared();
     }
@@ -1603,10 +1617,6 @@
         removeAction(SystemAudioAutoInitiationAction.class);
         removeAction(SystemAudioStatusAction.class);
         removeAction(VolumeControlAction.class);
-
-        // Turn off the mode but do not write it the settings, so that the next time TV powers on
-        // the system audio mode setting can be restored automatically.
-        setSystemAudioMode(false, false);
     }
 
     @ServiceThreadOnly
@@ -1619,7 +1629,7 @@
 
         // Seq #44.
         removeAction(RequestArcInitiationAction.class);
-        if (!hasAction(RequestArcTerminationAction.class) && isArcEstabilished()) {
+        if (!hasAction(RequestArcTerminationAction.class) && isArcEstablished()) {
             addAndStartAction(new RequestArcTerminationAction(this, avr.getLogicalAddress()));
         }
     }
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index f7555e9..a944a27 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -261,7 +261,7 @@
 
         // Turn off system audio mode and update settings.
         tv().setSystemAudioMode(false, true);
-        if (tv().isArcEstabilished()) {
+        if (tv().isArcEstablished()) {
             tv().setAudioReturnChannel(false);
             addAndStartAction(new RequestArcTerminationAction(localDevice(), address));
         }
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
index cbbf91b..75a79cb 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -58,14 +58,16 @@
             // received without <Request ARC Initiation> or <Request ARC Termination>.
             case Constants.MESSAGE_FEATURE_ABORT:
                 int originalOpcode = cmd.getParams()[0] & 0xFF;
-                if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_INITIATION
-                        || originalOpcode == Constants.MESSAGE_REQUEST_ARC_TERMINATION) {
+                if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_TERMINATION) {
                     disableArcTransmission();
                     finish();
                     return true;
-                } else {
-                    return false;
+                } else if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_INITIATION) {
+                    tv().setArcStatus(false);
+                    finish();
+                    return true;
                 }
+                return false;
         }
         return false;
     }
@@ -82,7 +84,7 @@
         if (mState != state || state != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE) {
             return;
         }
-        HdmiLogger.debug("[T]RequestArcAction.");
+        HdmiLogger.debug("[T] RequestArcAction.");
         disableArcTransmission();
         finish();
     }
diff --git a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
index d9e1f24..f69f975 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
@@ -35,6 +35,7 @@
 
     @Override
     boolean start() {
+        // Seq #38
         mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
         addTimer(mState, HdmiConfig.TIMEOUT_MS);
 
@@ -44,9 +45,8 @@
             @Override
             public void onSendCompleted(int error) {
                 if (error != Constants.SEND_RESULT_SUCCESS) {
-                    // If failed to send <Request ARC Initiation>, start "Disabled"
-                    // ARC transmission action.
-                    disableArcTransmission();
+                    // Turn off ARC status if <Request ARC Initiation> fails.
+                    tv().setArcStatus(false);
                     finish();
                 }
             }
diff --git a/services/core/java/com/android/server/hdmi/RoutingControlAction.java b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
index ce5b9ab7..6c8694e 100644
--- a/services/core/java/com/android/server/hdmi/RoutingControlAction.java
+++ b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
@@ -119,7 +119,7 @@
 
     private void handleReportPowerStatus(int devicePowerStatus) {
         if (isPowerOnOrTransient(getTvPowerStatus())) {
-            tv().updateActiveInput(mCurrentRoutingPath, mNotifyInputChange);
+            updateActiveInput();
             if (isPowerOnOrTransient(devicePowerStatus)) {
                 sendSetStreamPath();
             }
@@ -127,6 +127,12 @@
         finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
     }
 
+    private void updateActiveInput() {
+        HdmiCecLocalDeviceTv tv = tv();
+        tv.setPrevPortId(tv.getActivePortId());
+        tv.updateActiveInput(mCurrentRoutingPath, mNotifyInputChange);
+    }
+
     private int getTvPowerStatus() {
         return tv().getPowerStatus();
     }
@@ -165,13 +171,13 @@
                         }
                     });
                 } else {
-                    tv().updateActiveInput(mCurrentRoutingPath, mNotifyInputChange);
+                    updateActiveInput();
                     finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
                 }
                 return;
             case STATE_WAIT_FOR_REPORT_POWER_STATUS:
                 if (isPowerOnOrTransient(getTvPowerStatus())) {
-                    tv().updateActiveInput(mCurrentRoutingPath, mNotifyInputChange);
+                    updateActiveInput();
                     sendSetStreamPath();
                 }
                 finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
@@ -189,7 +195,7 @@
             mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
             addTimer(mState, TIMEOUT_REPORT_POWER_STATUS_MS);
         } else {
-            tv().updateActiveInput(mCurrentRoutingPath, mNotifyInputChange);
+            updateActiveInput();
             sendSetStreamPath();
             finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
         }
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index bffa854..d200d35 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -52,6 +52,7 @@
 
     @Override
     boolean start() {
+        // Seq #37.
         if (mEnabled) {
             // Enable ARC status immediately after sending <Report Arc Initiated>.
             // If AVR responds with <Feature Abort>, disable ARC status again.
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index fe1260d..ecda36a 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -41,6 +41,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
@@ -50,6 +51,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.app.IBatteryStats;
+import com.android.server.job.controllers.AppIdleController;
 import com.android.server.job.controllers.BatteryController;
 import com.android.server.job.controllers.ConnectivityController;
 import com.android.server.job.controllers.IdleController;
@@ -109,21 +111,22 @@
      * Track Services that have currently active or pending jobs. The index is provided by
      * {@link JobStatus#getServiceToken()}
      */
-    final List<JobServiceContext> mActiveServices = new ArrayList<JobServiceContext>();
+    final List<JobServiceContext> mActiveServices = new ArrayList<>();
     /** List of controllers that will notify this service of updates to jobs. */
     List<StateController> mControllers;
     /**
      * Queue of pending jobs. The JobServiceContext class will receive jobs from this list
      * when ready to execute them.
      */
-    final ArrayList<JobStatus> mPendingJobs = new ArrayList<JobStatus>();
+    final ArrayList<JobStatus> mPendingJobs = new ArrayList<>();
 
-    final ArrayList<Integer> mStartedUsers = new ArrayList();
+    final ArrayList<Integer> mStartedUsers = new ArrayList<>();
 
     final JobHandler mHandler;
     final JobSchedulerStub mJobSchedulerStub;
 
     IBatteryStats mBatteryStats;
+    PowerManager mPowerManager;
 
     /**
      * Set to true once we are allowed to run third party apps.
@@ -131,6 +134,11 @@
     boolean mReadyToRock;
 
     /**
+     * True when in device idle mode, so we don't want to schedule any jobs.
+     */
+    boolean mDeviceIdleMode;
+
+    /**
      * Cleans up outstanding jobs when a package is removed. Even if it's being replaced later we
      * still clean up. On reinstall the package will have a new uid.
      */
@@ -154,6 +162,8 @@
                     Slog.d(TAG, "Removing jobs for user: " + userId);
                 }
                 cancelJobsForUser(userId);
+            } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
+                updateIdleMode(mPowerManager != null ? mPowerManager.isDeviceIdleMode() : false);
             }
         }
     };
@@ -199,7 +209,7 @@
         return outList;
     }
 
-    private void cancelJobsForUser(int userHandle) {
+    void cancelJobsForUser(int userHandle) {
         List<JobStatus> jobsForUser;
         synchronized (mJobs) {
             jobsForUser = mJobs.getJobsByUser(userHandle);
@@ -257,6 +267,40 @@
         }
     }
 
+    void updateIdleMode(boolean enabled) {
+        boolean changed = false;
+        boolean rocking;
+        synchronized (mJobs) {
+            if (mDeviceIdleMode != enabled) {
+                changed = true;
+            }
+            rocking = mReadyToRock;
+        }
+        if (changed) {
+            if (rocking) {
+                for (int i=0; i<mControllers.size(); i++) {
+                    mControllers.get(i).deviceIdleModeChanged(enabled);
+                }
+            }
+            synchronized (mJobs) {
+                mDeviceIdleMode = enabled;
+                if (enabled) {
+                    // When becoming idle, make sure no jobs are actively running.
+                    for (int i=0; i<mActiveServices.size(); i++) {
+                        JobServiceContext jsc = mActiveServices.get(i);
+                        final JobStatus executing = jsc.getRunningJob();
+                        if (executing != null) {
+                            jsc.cancelExecutingJob();
+                        }
+                    }
+                } else {
+                    // When coming out of idle, allow thing to start back up.
+                    mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+                }
+            }
+        }
+    }
+
     /**
      * Initializes the system service.
      * <p>
@@ -274,6 +318,7 @@
         mControllers.add(TimeController.get(this));
         mControllers.add(IdleController.get(this));
         mControllers.add(BatteryController.get(this));
+        mControllers.add(AppIdleController.get(this));
 
         mHandler = new JobHandler(context.getMainLooper());
         mJobSchedulerStub = new JobSchedulerStub();
@@ -294,8 +339,10 @@
             getContext().registerReceiverAsUser(
                     mBroadcastReceiver, UserHandle.ALL, filter, null, null);
             final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+            userFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
             getContext().registerReceiverAsUser(
                     mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
+            mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE);
         } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
             synchronized (mJobs) {
                 // Let's go!
@@ -313,6 +360,7 @@
                 for (int i=0; i<jobs.size(); i++) {
                     JobStatus job = jobs.valueAt(i);
                     for (int controller=0; controller<mControllers.size(); controller++) {
+                        mControllers.get(controller).deviceIdleModeChanged(mDeviceIdleMode);
                         mControllers.get(controller).maybeStartTrackingJob(job);
                     }
                 }
@@ -642,7 +690,6 @@
             final boolean jobPending = mPendingJobs.contains(job);
             final boolean jobActive = isCurrentlyActiveLocked(job);
             final boolean userRunning = mStartedUsers.contains(job.getUserId());
-
             if (DEBUG) {
                 Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString()
                         + " ready=" + jobReady + " pending=" + jobPending
@@ -667,6 +714,10 @@
          */
         private void maybeRunPendingJobsH() {
             synchronized (mJobs) {
+                if (mDeviceIdleMode) {
+                    // If device is idle, we will not schedule jobs to run.
+                    return;
+                }
                 Iterator<JobStatus> it = mPendingJobs.iterator();
                 if (DEBUG) {
                     Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
@@ -688,6 +739,10 @@
                         }
                     }
                     if (availableContext != null) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "About to run job "
+                                    + nextPending.getJob().getService().toString());
+                        }
                         if (!availableContext.executeRunnableJob(nextPending)) {
                             if (DEBUG) {
                                 Slog.d(TAG, "Error executing " + nextPending);
@@ -878,6 +933,7 @@
             }
             pw.println();
             pw.print("mReadyToRock="); pw.println(mReadyToRock);
+            pw.print("mDeviceIdleMode="); pw.println(mDeviceIdleMode);
         }
         pw.println();
     }
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 63c8d92..53ceb2e 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -153,8 +153,9 @@
             }
 
             mRunningJob = job;
-            mParams = new JobParameters(this, job.getJobId(), job.getExtras(),
-                    !job.isConstraintsSatisfied());
+            final boolean isDeadlineExpired =
+                    job.getLatestRunTimeElapsed() >= SystemClock.elapsedRealtime();
+            mParams = new JobParameters(this, job.getJobId(), job.getExtras(), isDeadlineExpired);
             mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();
 
             mVerb = VERB_BINDING;
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
new file mode 100644
index 0000000..8a9f3e1
--- /dev/null
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -0,0 +1,174 @@
+/*
+ * 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.job.controllers;
+
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
+import android.util.Slog;
+
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateChangedListener;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Controls when apps are considered idle and if jobs pertaining to those apps should
+ * be executed. Apps that haven't been actively launched or accessed from a foreground app
+ * for a certain amount of time (maybe hours or days) are considered idle. When the app comes
+ * out of idle state, it will be allowed to run scheduled jobs.
+ */
+public class AppIdleController extends StateController
+        implements UsageStatsManagerInternal.AppIdleStateChangeListener {
+
+    private static final String LOG_TAG = "AppIdleController";
+    private static final boolean DEBUG = false;
+
+    // Singleton factory
+    private static Object sCreationLock = new Object();
+    private static volatile AppIdleController sController;
+    final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
+    private final UsageStatsManagerInternal mUsageStatsInternal;
+    private final BatteryManagerInternal mBatteryManagerInternal;
+    private boolean mPluggedIn;
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
+                int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
+                // TODO: Allow any charger type
+                onPluggedIn((plugged & BatteryManager.BATTERY_PLUGGED_AC) != 0);
+            }
+        }
+    };
+
+    public static AppIdleController get(JobSchedulerService service) {
+        synchronized (sCreationLock) {
+            if (sController == null) {
+                sController = new AppIdleController(service, service.getContext());
+            }
+            return sController;
+        }
+    }
+
+    private AppIdleController(StateChangedListener stateChangedListener, Context context) {
+        super(stateChangedListener, context);
+        mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class);
+        mBatteryManagerInternal = LocalServices.getService(BatteryManagerInternal.class);
+        mPluggedIn = isPowered();
+        mUsageStatsInternal.addAppIdleStateChangeListener(this);
+        registerReceivers();
+    }
+
+    private void registerReceivers() {
+        // Monitor battery charging state
+        IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+        mContext.registerReceiver(mReceiver, filter);
+    }
+
+    private boolean isPowered() {
+        // TODO: Allow any charger type
+        return mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_AC);
+    }
+
+    @Override
+    public void maybeStartTrackingJob(JobStatus jobStatus) {
+        synchronized (mTrackedTasks) {
+            mTrackedTasks.add(jobStatus);
+            String packageName = jobStatus.job.getService().getPackageName();
+            final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName,
+                    jobStatus.getUserId());
+            if (DEBUG) {
+                Slog.d(LOG_TAG, "Start tracking, setting idle state of "
+                        + packageName + " to " + appIdle);
+            }
+            jobStatus.appNotIdleConstraintSatisfied.set(!appIdle);
+        }
+    }
+
+    @Override
+    public void maybeStopTrackingJob(JobStatus jobStatus) {
+        synchronized (mTrackedTasks) {
+            mTrackedTasks.remove(jobStatus);
+        }
+    }
+
+    @Override
+    public void dumpControllerState(PrintWriter pw) {
+        // TODO:
+    }
+
+    @Override
+    public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
+        boolean changed = false;
+        synchronized (mTrackedTasks) {
+            // If currently plugged in, we don't care about app idle state
+            if (mPluggedIn) {
+                return;
+            }
+            for (JobStatus task : mTrackedTasks) {
+                if (task.job.getService().getPackageName().equals(packageName)
+                        && task.getUserId() == userId) {
+                    if (task.appNotIdleConstraintSatisfied.get() != !idle) {
+                        if (DEBUG) {
+                            Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
+                                    + packageName + " to " + idle);
+                        }
+                        task.appNotIdleConstraintSatisfied.set(!idle);
+                        changed = true;
+                    }
+                }
+            }
+        }
+        if (changed) {
+            mStateChangedListener.onControllerStateChanged();
+        }
+    }
+
+    void onPluggedIn(boolean pluggedIn) {
+        // Flag if any app's idle state has changed
+        boolean changed = false;
+        synchronized (mTrackedTasks) {
+            if (mPluggedIn == pluggedIn) {
+                return;
+            }
+            mPluggedIn = pluggedIn;
+            for (JobStatus task : mTrackedTasks) {
+                String packageName = task.job.getService().getPackageName();
+                final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName,
+                        task.getUserId());
+                if (DEBUG) {
+                    Slog.d(LOG_TAG, "Plugged in " + pluggedIn + ", setting idle state of "
+                            + packageName + " to " + appIdle);
+                }
+                if (task.appNotIdleConstraintSatisfied.get() == appIdle) {
+                    task.appNotIdleConstraintSatisfied.set(!appIdle);
+                    changed = true;
+                }
+            }
+        }
+        if (changed) {
+            mStateChangedListener.onControllerStateChanged();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index e3c55b6..69c63f3 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -54,6 +54,7 @@
     final AtomicBoolean idleConstraintSatisfied = new AtomicBoolean();
     final AtomicBoolean unmeteredConstraintSatisfied = new AtomicBoolean();
     final AtomicBoolean connectivityConstraintSatisfied = new AtomicBoolean();
+    final AtomicBoolean appNotIdleConstraintSatisfied = new AtomicBoolean();
 
     /**
      * Earliest point in the future at which this job will be eligible to run. A value of 0
@@ -199,8 +200,11 @@
      * the constraints are satisfied <strong>or</strong> the deadline on the job has expired.
      */
     public synchronized boolean isReady() {
-        return isConstraintsSatisfied()
-                || (hasDeadlineConstraint() && deadlineConstraintSatisfied.get());
+        // Deadline constraint trumps other constraints
+        // AppNotIdle implicit constraint trumps all!
+        return (isConstraintsSatisfied()
+                    || (hasDeadlineConstraint() && deadlineConstraintSatisfied.get()))
+                && appNotIdleConstraintSatisfied.get();
     }
 
     /**
@@ -229,6 +233,7 @@
                 + ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging()
                 + ",I=" + job.isRequireDeviceIdle() + ",F=" + numFailures
                 + ",P=" + job.isPersisted()
+                + ",ANI=" + appNotIdleConstraintSatisfied.get()
                 + (isReady() ? "(READY)" : "")
                 + "]";
     }
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index 7d76fc0..cda7c32 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -31,15 +31,20 @@
     protected static final boolean DEBUG = false;
     protected Context mContext;
     protected StateChangedListener mStateChangedListener;
+    protected boolean mDeviceIdleMode;
 
     public StateController(StateChangedListener stateChangedListener, Context context) {
         mStateChangedListener = stateChangedListener;
         mContext = context;
     }
 
+    public void deviceIdleModeChanged(boolean enabled) {
+        mDeviceIdleMode = enabled;
+    }
+
     /**
      * Implement the logic here to decide whether a job should be tracked by this controller.
-     * This logic is put here so the JobManger can be completely agnostic of Controller logic.
+     * This logic is put here so the JobManager can be completely agnostic of Controller logic.
      * Also called when updating a task, so implementing controllers have to be aware of
      * preexisting tasks.
      */
@@ -50,5 +55,4 @@
     public abstract void maybeStopTrackingJob(JobStatus jobStatus);
 
     public abstract void dumpControllerState(PrintWriter pw);
-
 }
diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java
index 4c6cb17..b3d7287 100644
--- a/services/core/java/com/android/server/job/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -91,14 +91,20 @@
     public synchronized void maybeStartTrackingJob(JobStatus job) {
         if (job.hasTimingDelayConstraint() || job.hasDeadlineConstraint()) {
             maybeStopTrackingJob(job);
+            boolean isInsert = false;
             ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size());
             while (it.hasPrevious()) {
                 JobStatus ts = it.previous();
                 if (ts.getLatestRunTimeElapsed() < job.getLatestRunTimeElapsed()) {
                     // Insert
+                    isInsert = true;
                     break;
                 }
             }
+            if(isInsert)
+            {
+                it.next();
+            }
             it.add(job);
             maybeUpdateAlarms(
                     job.hasTimingDelayConstraint() ? job.getEarliestRunTime() : Long.MAX_VALUE,
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index b5036db..09d0501 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -40,6 +40,7 @@
 import android.media.session.ParcelableVolumeInfo;
 import android.media.session.PlaybackState;
 import android.media.AudioAttributes;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.DeadObjectException;
@@ -887,6 +888,14 @@
             }
         }
 
+        public void playFromUri(Uri uri, Bundle extras) {
+            try {
+                mCb.onPlayFromUri(uri, extras);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in playFromUri.", e);
+            }
+        }
+
         public void skipToTrack(long id) {
             try {
                 mCb.onSkipToTrack(id);
@@ -1103,6 +1112,11 @@
         }
 
         @Override
+        public void playFromUri(Uri uri, Bundle extras) throws RemoteException {
+            mSessionCb.playFromUri(uri, extras);
+        }
+
+        @Override
         public void skipToQueueItem(long id) {
             mSessionCb.skipToTrack(id);
         }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 8d46775..5de7d42 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -71,7 +71,9 @@
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
+import android.Manifest;
 import android.app.ActivityManager;
+import android.app.AppGlobals;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
 import android.app.IProcessObserver;
@@ -83,6 +85,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
@@ -2021,6 +2024,17 @@
     void updateRulesForUidLocked(int uid) {
         if (!isUidValidForRules(uid)) return;
 
+        // quick check: if this uid doesn't have INTERNET permission, it doesn't have
+        // network access anyway, so it is a waste to mess with it here.
+        final IPackageManager ipm = AppGlobals.getPackageManager();
+        try {
+            if (ipm.checkUidPermission(Manifest.permission.INTERNET, uid)
+                    != PackageManager.PERMISSION_GRANTED) {
+                return;
+            }
+        } catch (RemoteException e) {
+        }
+
         final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
         final boolean uidForeground = isUidForegroundLocked(uid);
 
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 20f5f97..15b68c7 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -22,21 +22,28 @@
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.TrafficStats.UID_REMOVED;
+import static android.net.TrafficStats.UID_TETHERING;
+import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 import static android.text.format.DateUtils.WEEK_IN_MILLIS;
 
+import android.net.ConnectivityManager;
 import android.net.NetworkIdentity;
 import android.net.NetworkStats;
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
 import android.net.TrafficStats;
+import android.os.Binder;
+import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
+import android.util.IntArray;
 
 import libcore.io.IoUtils;
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
+
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
@@ -129,6 +136,23 @@
         return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE;
     }
 
+    public int[] getRelevantUids() {
+        final int callerUid = Binder.getCallingUid();
+        IntArray uids = new IntArray();
+        for (int i = 0; i < mStats.size(); i++) {
+            final Key key = mStats.keyAt(i);
+            if (isAccessibleToUser(key.uid, callerUid)) {
+                int j = uids.binarySearch(key.uid);
+
+                if (j < 0) {
+                    j = ~j;
+                    uids.add(j, key.uid);
+                }
+            }
+        }
+        return uids.toArray();
+    }
+
     /**
      * Combine all {@link NetworkStatsHistory} in this collection which match
      * the requested parameters.
@@ -144,12 +168,21 @@
      */
     public NetworkStatsHistory getHistory(
             NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end) {
+        final int callerUid = Binder.getCallingUid();
+        if (!isAccessibleToUser(uid, callerUid)) {
+            throw new SecurityException("Network stats history of uid " + uid
+                    + " is forbidden for caller " + callerUid);
+        }
+
         final NetworkStatsHistory combined = new NetworkStatsHistory(
-                mBucketDuration, estimateBuckets(), fields);
+                mBucketDuration, start == end ? 1 : estimateBuckets(), fields);
+
+        // shortcut when we know stats will be empty
+        if (start == end) return combined;
+
         for (int i = 0; i < mStats.size(); i++) {
             final Key key = mStats.keyAt(i);
-            final boolean setMatches = set == SET_ALL || key.set == set;
-            if (key.uid == uid && setMatches && key.tag == tag
+            if (key.uid == uid && NetworkStats.setMatches(set, key.set) && key.tag == tag
                     && templateMatches(template, key.ident)) {
                 final NetworkStatsHistory value = mStats.valueAt(i);
                 combined.recordHistory(value, start, end);
@@ -166,15 +199,17 @@
         final long now = System.currentTimeMillis();
 
         final NetworkStats stats = new NetworkStats(end - start, 24);
-        final NetworkStats.Entry entry = new NetworkStats.Entry();
-        NetworkStatsHistory.Entry historyEntry = null;
-
         // shortcut when we know stats will be empty
         if (start == end) return stats;
 
+        final NetworkStats.Entry entry = new NetworkStats.Entry();
+        NetworkStatsHistory.Entry historyEntry = null;
+
+        final int callerUid = Binder.getCallingUid();
         for (int i = 0; i < mStats.size(); i++) {
             final Key key = mStats.keyAt(i);
-            if (templateMatches(template, key.ident)) {
+            if (templateMatches(template, key.ident) && isAccessibleToUser(key.uid, callerUid)
+                    && key.set < NetworkStats.SET_DEBUG_START) {
                 final NetworkStatsHistory value = mStats.valueAt(i);
                 historyEntry = value.getValues(start, end, now, historyEntry);
 
@@ -507,6 +542,7 @@
             final NetworkStatsHistory value = mStats.valueAt(i);
 
             if (!templateMatches(groupTemplate, key.ident)) continue;
+            if (key.set >= NetworkStats.SET_DEBUG_START) continue;
 
             final Key groupKey = new Key(null, key.uid, key.set, key.tag);
             NetworkStatsHistory groupHistory = grouped.get(groupKey);
@@ -534,6 +570,12 @@
         }
     }
 
+    private static boolean isAccessibleToUser(int uid, int callerUid) {
+        return UserHandle.getAppId(callerUid) == android.os.Process.SYSTEM_UID ||
+                uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED || uid == UID_TETHERING
+                || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
+    }
+
     /**
      * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
      * in the given {@link NetworkIdentitySet}.
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 0b596aa..50e03a2 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -62,9 +62,13 @@
 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
 
+import android.Manifest;
 import android.app.AlarmManager;
+import android.app.AppOpsManager;
 import android.app.IAlarmManager;
 import android.app.PendingIntent;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -93,7 +97,9 @@
 import android.os.INetworkManagementService;
 import android.os.Message;
 import android.os.PowerManager;
+import android.os.Process;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -116,6 +122,7 @@
 import com.android.internal.util.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
 import com.android.server.connectivity.Tethering;
 
 import java.io.File;
@@ -429,7 +436,11 @@
 
     @Override
     public INetworkStatsSession openSession() {
-        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+        return openSessionForUsageStats(null);
+    }
+
+    @Override
+    public INetworkStatsSession openSessionForUsageStats(final String callingPackage) {
         assertBandwidthControlEnabled();
 
         // return an IBinder which holds strong references to any loaded stats
@@ -438,6 +449,7 @@
         return new INetworkStatsSession.Stub() {
             private NetworkStatsCollection mUidComplete;
             private NetworkStatsCollection mUidTagComplete;
+            private String mCallingPackage = callingPackage;
 
             private NetworkStatsCollection getUidComplete() {
                 synchronized (mStatsLock) {
@@ -458,8 +470,29 @@
             }
 
             @Override
+            public int[] getRelevantUids() {
+                enforcePermissionForManagedAdmin(mCallingPackage);
+                return getUidComplete().getRelevantUids();
+            }
+
+            @Override
+            public NetworkStats getDeviceSummaryForNetwork(NetworkTemplate template, long start,
+                    long end) {
+                enforcePermission(mCallingPackage);
+                NetworkStats result = new NetworkStats(end - start, 1);
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    result.combineAllValues(internalGetSummaryForNetwork(template, start, end));
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+                return result;
+            }
+
+            @Override
             public NetworkStats getSummaryForNetwork(
                     NetworkTemplate template, long start, long end) {
+                enforcePermission(mCallingPackage);
                 return internalGetSummaryForNetwork(template, start, end);
             }
 
@@ -471,6 +504,7 @@
             @Override
             public NetworkStats getSummaryForAllUid(
                     NetworkTemplate template, long start, long end, boolean includeTags) {
+                enforcePermissionForManagedAdmin(mCallingPackage);
                 final NetworkStats stats = getUidComplete().getSummary(template, start, end);
                 if (includeTags) {
                     final NetworkStats tagStats = getUidTagComplete()
@@ -483,6 +517,7 @@
             @Override
             public NetworkStatsHistory getHistoryForUid(
                     NetworkTemplate template, int uid, int set, int tag, int fields) {
+                enforcePermissionForManagedAdmin(mCallingPackage);
                 if (tag == TAG_NONE) {
                     return getUidComplete().getHistory(template, uid, set, tag, fields);
                 } else {
@@ -498,6 +533,53 @@
         };
     }
 
+    private boolean hasAppOpsPermission(String callingPackage) {
+        final int callingUid = Binder.getCallingUid();
+        boolean appOpsAllow = false;
+        if (callingPackage != null) {
+            AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
+                    Context.APP_OPS_SERVICE);
+
+            final int mode = appOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
+                    callingUid, callingPackage);
+            if (mode == AppOpsManager.MODE_DEFAULT) {
+                // The default behavior here is to check if PackageManager has given the app
+                // permission.
+                final int permissionCheck = mContext.checkCallingPermission(
+                        Manifest.permission.PACKAGE_USAGE_STATS);
+                appOpsAllow = permissionCheck == PackageManager.PERMISSION_GRANTED;
+            }
+            appOpsAllow = (mode == AppOpsManager.MODE_ALLOWED);
+        }
+        return appOpsAllow;
+    }
+
+    private void enforcePermissionForManagedAdmin(String callingPackage) {
+        boolean hasPermission = hasAppOpsPermission(callingPackage);
+        if (!hasPermission) {
+            // Profile and device owners are exempt from permission checking.
+            final int callingUid = Binder.getCallingUid();
+            final DevicePolicyManagerInternal dpmi = LocalServices.getService(
+                    DevicePolicyManagerInternal.class);
+            if (dpmi.isActiveAdminWithPolicy(callingUid, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER)
+                    || dpmi.isActiveAdminWithPolicy(callingUid,
+                            DeviceAdminInfo.USES_POLICY_DEVICE_OWNER)) {
+                return;
+            }
+        }
+        if (!hasPermission) {
+            mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+        }
+    }
+
+    private void enforcePermission(String callingPackage) {
+        boolean appOpsAllow = hasAppOpsPermission(callingPackage);
+        if (!appOpsAllow) {
+            mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+        }
+    }
+
+
     /**
      * Return network summary, splicing between DEV and XT stats when
      * appropriate.
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index 1fc967f..1e318ef 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -172,6 +172,7 @@
         switch (zenMode) {
             case Global.ZEN_MODE_OFF: return "off";
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return "important_interruptions";
+            case Global.ZEN_MODE_ALARMS: return "alarms";
             case Global.ZEN_MODE_NO_INTERRUPTIONS: return "no_interruptions";
             default: return "unknown";
         }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index a985b01..1775df2 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -128,6 +128,8 @@
                 return NotificationListenerService.INTERRUPTION_FILTER_ALL;
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
                 return NotificationListenerService.INTERRUPTION_FILTER_PRIORITY;
+            case Global.ZEN_MODE_ALARMS:
+                return NotificationListenerService.INTERRUPTION_FILTER_ALARMS;
             case Global.ZEN_MODE_NO_INTERRUPTIONS:
                 return NotificationListenerService.INTERRUPTION_FILTER_NONE;
             default:
@@ -142,6 +144,8 @@
                 return Global.ZEN_MODE_OFF;
             case NotificationListenerService.INTERRUPTION_FILTER_PRIORITY:
                 return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+            case NotificationListenerService.INTERRUPTION_FILTER_ALARMS:
+                return Global.ZEN_MODE_ALARMS;
             case NotificationListenerService.INTERRUPTION_FILTER_NONE:
                 return Global.ZEN_MODE_NO_INTERRUPTIONS;
             default:
@@ -171,6 +175,13 @@
                 // #notevenalarms
                 ZenLog.traceIntercepted(record, "none");
                 return true;
+            case Global.ZEN_MODE_ALARMS:
+                if (isAlarm(record)) {
+                    // Alarms only
+                    return false;
+                }
+                ZenLog.traceIntercepted(record, "alarmsOnly");
+                return true;
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
                 if (isAlarm(record)) {
                     // Alarms are always priority
@@ -202,6 +213,13 @@
                     }
                     return false;
                 }
+                if (isReminder(record)) {
+                    if (!mConfig.allowReminders) {
+                        ZenLog.traceIntercepted(record, "!allowReminders");
+                        return true;
+                    }
+                    return false;
+                }
                 ZenLog.traceIntercepted(record, "!priority");
                 return true;
             default:
@@ -314,6 +332,7 @@
         int newRingerModeInternal = ringerModeInternal;
         switch (mZenMode) {
             case Global.ZEN_MODE_NO_INTERRUPTIONS:
+            case Global.ZEN_MODE_ALARMS:
                 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
                     mPreviousRingerMode = ringerModeInternal;
                     newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
@@ -344,7 +363,8 @@
         switch (ringerModeNew) {
             case AudioManager.RINGER_MODE_SILENT:
                 if (isChange && policy.doNotDisturbWhenSilent) {
-                    if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS) {
+                    if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS
+                            && mZenMode != Global.ZEN_MODE_ALARMS) {
                         newZen = Global.ZEN_MODE_NO_INTERRUPTIONS;
                     }
                 }
@@ -352,7 +372,8 @@
             case AudioManager.RINGER_MODE_VIBRATE:
             case AudioManager.RINGER_MODE_NORMAL:
                 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
-                        && mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+                        && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
+                                || mZenMode == Global.ZEN_MODE_ALARMS)) {
                     newZen = Global.ZEN_MODE_OFF;
                 } else if (mZenMode != Global.ZEN_MODE_OFF) {
                     ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
@@ -432,6 +453,10 @@
         return record.isCategory(Notification.CATEGORY_EVENT);
     }
 
+    private static boolean isReminder(NotificationRecord record) {
+        return record.isCategory(Notification.CATEGORY_REMINDER);
+    }
+
     public boolean isCall(NotificationRecord record) {
         return record != null && (isDefaultPhoneApp(record.sbn.getPackageName())
                 || record.isCategory(Notification.CATEGORY_CALL));
@@ -470,6 +495,7 @@
             ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
         final int zen = mZenMode;
         if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) return false; // nothing gets through
+        if (zen == Global.ZEN_MODE_ALARMS) return false; // not an alarm
         if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
             if (!mConfig.allowCalls) return false; // no calls get through
             if (validator != null) {
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 5cde8ea..b4a44a6 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.PackageStats;
 import android.os.Build;
@@ -83,14 +84,15 @@
     }
 
     public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
-            String instructionSet, boolean vmSafeMode, boolean debuggable) {
+            String instructionSet, boolean vmSafeMode, boolean debuggable,
+            @Nullable String outputPath) {
         if (!isValidInstructionSet(instructionSet)) {
             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
             return -1;
         }
 
         return mInstaller.dexopt(apkPath, uid, isPublic, pkgName, instructionSet, vmSafeMode,
-                debuggable);
+                debuggable, outputPath);
     }
 
     public int idmap(String targetApkPath, String overlayApkPath, int uid) {
@@ -134,6 +136,16 @@
         return mInstaller.execute(builder.toString());
     }
 
+    /**
+     * Removes packageDir or its subdirectory
+     */
+    public int rmPackageDir(String packageDir) {
+        StringBuilder builder = new StringBuilder("rmpackagedir");
+        builder.append(' ');
+        builder.append(packageDir);
+        return mInstaller.execute(builder.toString());
+    }
+
     public int remove(String name, int userId) {
         StringBuilder builder = new StringBuilder("remove");
         builder.append(' ');
@@ -331,6 +343,15 @@
         return (mInstaller.execute(builder.toString()) == 0);
     }
 
+    public int createOatDir(String oatDir, String dexInstructionSet) {
+        StringBuilder builder = new StringBuilder("createoatdir");
+        builder.append(' ');
+        builder.append(oatDir);
+        builder.append(' ');
+        builder.append(dexInstructionSet);
+        return mInstaller.execute(builder.toString());
+    }
+
     /**
      * Returns true iff. {@code instructionSet} is a valid instruction set.
      */
diff --git a/services/core/java/com/android/server/pm/InstructionSets.java b/services/core/java/com/android/server/pm/InstructionSets.java
index 79e7a20..5092ebf 100644
--- a/services/core/java/com/android/server/pm/InstructionSets.java
+++ b/services/core/java/com/android/server/pm/InstructionSets.java
@@ -74,6 +74,7 @@
      * a native bridge this might be different than the one shared libraries use.
      */
     public static String getDexCodeInstructionSet(String sharedLibraryIsa) {
+        // TODO b/19550105 Build mapping once instead of querying each time
         String dexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + sharedLibraryIsa);
         return TextUtils.isEmpty(dexCodeIsa) ? sharedLibraryIsa : dexCodeIsa;
     }
@@ -111,4 +112,13 @@
 
         return allInstructionSets;
     }
+
+    public static String getPrimaryInstructionSet(ApplicationInfo info) {
+        if (info.primaryCpuAbi == null) {
+            return getPreferredInstructionSet();
+        }
+
+        return VMRuntime.getInstructionSet(info.primaryCpuAbi);
+    }
+
 }
diff --git a/services/core/java/com/android/server/pm/IntentFilterVerificationKey.java b/services/core/java/com/android/server/pm/IntentFilterVerificationKey.java
new file mode 100644
index 0000000..399b03c
--- /dev/null
+++ b/services/core/java/com/android/server/pm/IntentFilterVerificationKey.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.server.pm;
+
+import java.util.Arrays;
+
+/**
+ * This is the key for the map of {@link android.content.pm.IntentFilterVerificationInfo}s
+ * maintained by the  {@link com.android.server.pm.PackageManagerService}
+ */
+class IntentFilterVerificationKey {
+    public String domains;
+    public String packageName;
+    public String className;
+
+    public IntentFilterVerificationKey(String[] domains, String packageName, String className) {
+        StringBuilder sb = new StringBuilder();
+        for (String host : domains) {
+            sb.append(host);
+        }
+        this.domains = sb.toString();
+        this.packageName = packageName;
+        this.className = className;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        IntentFilterVerificationKey that = (IntentFilterVerificationKey) o;
+
+        if (domains != null ? !domains.equals(that.domains) : that.domains != null) return false;
+        if (className != null ? !className.equals(that.className) : that.className != null)
+            return false;
+        if (packageName != null ? !packageName.equals(that.packageName) : that.packageName != null)
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = domains != null ? domains.hashCode() : 0;
+        result = 31 * result + (packageName != null ? packageName.hashCode() : 0);
+        result = 31 * result + (className != null ? className.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/services/core/java/com/android/server/pm/IntentFilterVerificationResponse.java b/services/core/java/com/android/server/pm/IntentFilterVerificationResponse.java
new file mode 100644
index 0000000..ead399b
--- /dev/null
+++ b/services/core/java/com/android/server/pm/IntentFilterVerificationResponse.java
@@ -0,0 +1,43 @@
+/*
+ * 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.pm;
+
+
+import java.util.List;
+
+/* package private */ class IntentFilterVerificationResponse {
+    public final int callerUid;
+    public final int code;
+    public final List<String> failedDomains;
+
+    public IntentFilterVerificationResponse(int callerUid, int code, List<String> failedDomains) {
+        this.callerUid = callerUid;
+        this.code = code;
+        this.failedDomains = failedDomains;
+    }
+
+    public String getFailedDomainsString() {
+        StringBuilder sb = new StringBuilder();
+        for (String domain : failedDomains) {
+            if (sb.length() > 0) {
+                sb.append(" ");
+            }
+            sb.append(domain);
+        }
+        return sb.toString();
+    }
+}
diff --git a/services/core/java/com/android/server/pm/IntentFilterVerificationState.java b/services/core/java/com/android/server/pm/IntentFilterVerificationState.java
new file mode 100644
index 0000000..c09d6ae
--- /dev/null
+++ b/services/core/java/com/android/server/pm/IntentFilterVerificationState.java
@@ -0,0 +1,125 @@
+/*
+ * 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.pm;
+
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+public class IntentFilterVerificationState {
+    static final String TAG = IntentFilterVerificationState.class.getName();
+
+    public final static int STATE_UNDEFINED = 0;
+    public final static int STATE_VERIFICATION_PENDING = 1;
+    public final static int STATE_VERIFICATION_SUCCESS = 2;
+    public final static int STATE_VERIFICATION_FAILURE = 3;
+
+    private int mRequiredVerifierUid = 0;
+
+    private int mState;
+
+    private ArrayList<PackageParser.ActivityIntentInfo> mFilters = new ArrayList<>();
+    private ArraySet<String> mHosts = new ArraySet<>();
+    private int mUserId;
+
+    private String mPackageName;
+    private boolean mVerificationComplete;
+
+    public IntentFilterVerificationState(int verifierUid, int userId, String packageName) {
+        mRequiredVerifierUid = verifierUid;
+        mUserId = userId;
+        mPackageName = packageName;
+        mState = STATE_UNDEFINED;
+        mVerificationComplete = false;
+    }
+
+    public void setState(int state) {
+        if (state > STATE_VERIFICATION_FAILURE || state < STATE_UNDEFINED) {
+            mState = STATE_UNDEFINED;
+        } else {
+            mState = state;
+        }
+    }
+
+    public int getState() {
+        return mState;
+    }
+
+    public void setPendingState() {
+        setState(STATE_VERIFICATION_PENDING);
+    }
+
+    public ArrayList<PackageParser.ActivityIntentInfo> getFilters() {
+        return mFilters;
+    }
+
+    public boolean isVerificationComplete() {
+        return mVerificationComplete;
+    }
+
+    public boolean isVerified() {
+        if (mVerificationComplete) {
+            return (mState == STATE_VERIFICATION_SUCCESS);
+        }
+        return false;
+    }
+
+    public int getUserId() {
+        return mUserId;
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public String getHostsString() {
+        StringBuilder sb = new StringBuilder();
+        final int count = mHosts.size();
+        for (int i=0; i<count; i++) {
+            if (i > 0) {
+                sb.append(" ");
+            }
+            sb.append(mHosts.valueAt(i));
+        }
+        return sb.toString();
+    }
+
+    public boolean setVerifierResponse(int callerUid, int code) {
+        if (mRequiredVerifierUid == callerUid) {
+            int state = STATE_UNDEFINED;
+            if (code == PackageManager.INTENT_FILTER_VERIFICATION_SUCCESS) {
+                state = STATE_VERIFICATION_SUCCESS;
+            } else if (code == PackageManager.INTENT_FILTER_VERIFICATION_FAILURE) {
+                state = STATE_VERIFICATION_FAILURE;
+            }
+            mVerificationComplete = true;
+            setState(state);
+            return true;
+        }
+        Log.d(TAG, "Cannot set verifier response with callerUid:" + callerUid + " and code:" +
+                code + " as required verifierUid is:" + mRequiredVerifierUid);
+        return false;
+    }
+
+    public void addFilter(PackageParser.ActivityIntentInfo filter) {
+        mFilters.add(filter);
+        mHosts.addAll(filter.getHostsList());
+    }
+}
diff --git a/services/core/java/com/android/server/pm/KeySetHandle.java b/services/core/java/com/android/server/pm/KeySetHandle.java
index 640feb3..f34bd60 100644
--- a/services/core/java/com/android/server/pm/KeySetHandle.java
+++ b/services/core/java/com/android/server/pm/KeySetHandle.java
@@ -18,5 +18,46 @@
 
 import android.os.Binder;
 
-public class KeySetHandle extends Binder {
-}
\ No newline at end of file
+class KeySetHandle extends Binder{
+    private final long mId;
+    private int mRefCount;
+
+    protected KeySetHandle(long id) {
+        mId = id;
+        mRefCount = 1;
+    }
+
+    /*
+     * Only used when reading state from packages.xml
+     */
+    protected KeySetHandle(long id, int refCount) {
+        mId = id;
+        mRefCount = refCount;
+    }
+
+    public long getId() {
+        return mId;
+    }
+
+    protected int getRefCountLPr() {
+        return mRefCount;
+    }
+
+    /*
+     * Only used when reading state from packages.xml
+     */
+    protected void setRefCountLPw(int newCount) {
+         mRefCount = newCount;
+         return;
+    }
+
+    protected void incrRefCountLPw() {
+        mRefCount++;
+        return;
+    }
+
+    protected int decrRefCountLPw() {
+        mRefCount--;
+        return mRefCount;
+    }
+}
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index aa63932..db3ae91 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.pm;
 
 import android.content.pm.PackageParser;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Base64;
 import android.util.Slog;
@@ -25,7 +26,6 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.security.PublicKey;
-import java.util.Map;
 import java.util.Set;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -52,19 +52,61 @@
 
     private final LongSparseArray<KeySetHandle> mKeySets;
 
-    private final LongSparseArray<PublicKey> mPublicKeys;
+    private final LongSparseArray<PublicKeyHandle> mPublicKeys;
 
     protected final LongSparseArray<ArraySet<Long>> mKeySetMapping;
 
-    private final Map<String, PackageSetting> mPackages;
+    private final ArrayMap<String, PackageSetting> mPackages;
 
     private static long lastIssuedKeySetId = 0;
 
     private static long lastIssuedKeyId = 0;
 
-    public KeySetManagerService(Map<String, PackageSetting> packages) {
+    class PublicKeyHandle {
+        private final PublicKey mKey;
+        private final long mId;
+        private int mRefCount;
+
+        public PublicKeyHandle(long id, PublicKey key) {
+            mId = id;
+            mRefCount = 1;
+            mKey = key;
+        }
+
+        /*
+         * Only used when reading state from packages.xml
+         */
+        private PublicKeyHandle(long id, int refCount, PublicKey key) {
+            mId = id;
+            mRefCount = refCount;
+            mKey = key;
+        }
+
+        public long getId() {
+            return mId;
+        }
+
+        public PublicKey getKey() {
+            return mKey;
+        }
+
+        public int getRefCountLPr() {
+            return mRefCount;
+        }
+
+        public void incrRefCountLPw() {
+            mRefCount++;
+            return;
+        }
+        public long decrRefCountLPw() {
+            mRefCount--;
+            return mRefCount;
+        }
+    }
+
+    public KeySetManagerService(ArrayMap<String, PackageSetting> packages) {
         mKeySets = new LongSparseArray<KeySetHandle>();
-        mPublicKeys = new LongSparseArray<PublicKey>();
+        mPublicKeys = new LongSparseArray<PublicKeyHandle>();
         mKeySetMapping = new LongSparseArray<ArraySet<Long>>();
         mPackages = packages;
     }
@@ -92,7 +134,9 @@
         if (id == KEYSET_NOT_FOUND) {
                 return false;
         }
-        return pkg.keySetData.packageIsSignedBy(id);
+        ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet());
+        ArraySet<Long> testKeys = mKeySetMapping.get(id);
+        return pkgKeys.containsAll(testKeys);
     }
 
     /**
@@ -113,81 +157,45 @@
             || pkg.keySetData.getProperSigningKeySet()
             == PackageKeySetData.KEYSET_UNASSIGNED) {
             throw new NullPointerException("Package has no KeySet data");
-        }
+         }
         long id = getIdByKeySetLPr(ks);
-        return pkg.keySetData.getProperSigningKeySet() == id;
+        if (id == KEYSET_NOT_FOUND) {
+                return false;
+        }
+        ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet());
+        ArraySet<Long> testKeys = mKeySetMapping.get(id);
+        return pkgKeys.equals(testKeys);
     }
 
     /**
-     * This informs the system that the given package has defined a KeySet
-     * in its manifest that a) contains the given keys and b) is named
-     * alias by that package.
-     */
-    public void addDefinedKeySetToPackageLPw(String packageName,
-            ArraySet<PublicKey> keys, String alias) {
-        if ((packageName == null) || (keys == null) || (alias == null)) {
-            Slog.w(TAG, "Got null argument for a defined keyset, ignoring!");
-            return;
-        }
-        PackageSetting pkg = mPackages.get(packageName);
-        if (pkg == null) {
-            throw new NullPointerException("Unknown package");
-        }
-        // Add to KeySets, then to package
-        KeySetHandle ks = addKeySetLPw(keys);
-        long id = getIdByKeySetLPr(ks);
-        pkg.keySetData.addDefinedKeySet(id, alias);
-    }
-
-    /**
-     * This informs the system that the given package has defined a KeySet
-     * alias in its manifest to be an upgradeKeySet.  This must be called
-     * after all of the defined KeySets have been added.
-     */
-    public void addUpgradeKeySetToPackageLPw(String packageName, String alias) {
-        if ((packageName == null) || (alias == null)) {
-            Slog.w(TAG, "Got null argument for a defined keyset, ignoring!");
-            return;
-        }
-        PackageSetting pkg = mPackages.get(packageName);
-        if (pkg == null) {
-            throw new NullPointerException("Unknown package");
-        }
-        pkg.keySetData.addUpgradeKeySet(alias);
-    }
-
-    /**
-     * Similar to the above, this informs the system that the given package
-     * was signed by the provided KeySet.
+     * Informs the system that the given package was signed by the provided KeySet.
      */
     public void addSigningKeySetToPackageLPw(String packageName,
             ArraySet<PublicKey> signingKeys) {
-        if ((packageName == null) || (signingKeys == null)) {
-            Slog.w(TAG, "Got null argument for a signing keyset, ignoring!");
-            return;
-        }
-        // add the signing KeySet
-        KeySetHandle ks = addKeySetLPw(signingKeys);
-        long id = getIdByKeySetLPr(ks);
-        ArraySet<Long> publicKeyIds = mKeySetMapping.get(id);
-        if (publicKeyIds == null) {
-            throw new NullPointerException("Got invalid KeySet id");
-        }
-        // attach it to the package
+
+        /* check existing keyset for reuse or removal */
         PackageSetting pkg = mPackages.get(packageName);
-        if (pkg == null) {
-            throw new NullPointerException("No such package!");
-        }
-        pkg.keySetData.setProperSigningKeySet(id);
-        // for each KeySet which is a subset of the one above, add the
-        // KeySet id to the package's signing KeySets
-        for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
-            long keySetID = mKeySets.keyAt(keySetIndex);
-            ArraySet<Long> definedKeys = mKeySetMapping.get(keySetID);
-            if (publicKeyIds.containsAll(definedKeys)) {
-                pkg.keySetData.addSigningKeySet(keySetID);
+        long signingKeySetId = pkg.keySetData.getProperSigningKeySet();
+
+        if (signingKeySetId != PackageKeySetData.KEYSET_UNASSIGNED) {
+            ArraySet<PublicKey> existingKeys = getPublicKeysFromKeySetLPr(signingKeySetId);
+            if (existingKeys.equals(signingKeys)) {
+
+                /* no change in signing keys, leave PackageSetting alone */
+                return;
+            } else {
+
+                /* old keyset no longer valid, remove ref */
+                KeySetHandle ksh = mKeySets.get(signingKeySetId);
+                decrementKeySetLPw(signingKeySetId);
             }
         }
+
+        /* create and add a new keyset */
+        KeySetHandle ks = addKeySetLPw(signingKeys);
+        long id = ks.getId();
+        pkg.keySetData.setProperSigningKeySet(id);
+        return;
     }
 
     /**
@@ -204,25 +212,63 @@
         return KEYSET_NOT_FOUND;
     }
 
-    /**
-     * Fetches the KeySet corresponding to the given stable identifier.
-     *
-     * Returns {@link #KEYSET_NOT_FOUND} if the identifier doesn't
-     * identify a {@link KeySet}.
+    /*
+     * Inform the system that the given package defines the given KeySets.
+     * Remove any KeySets the package no longer defines.
      */
-    public KeySetHandle getKeySetByIdLPr(long id) {
-        return mKeySets.get(id);
+    public void addDefinedKeySetsToPackageLPw(String packageName,
+            ArrayMap<String, ArraySet<PublicKey>> definedMapping) {
+        PackageSetting pkg = mPackages.get(packageName);
+        ArrayMap<String, Long> prevDefinedKeySets = pkg.keySetData.getAliases();
+
+        /* add all of the newly defined KeySets */
+        ArrayMap<String, Long> newKeySetAliases = new ArrayMap<String, Long>();
+        final int defMapSize = definedMapping.size();
+        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) {
+                KeySetHandle ks = addKeySetLPw(pubKeys);
+                newKeySetAliases.put(alias, ks.getId());
+            }
+        }
+
+        /* remove each of the old references */
+        final int prevDefSize = prevDefinedKeySets.size();
+        for (int i = 0; i < prevDefSize; i++) {
+            decrementKeySetLPw(prevDefinedKeySets.valueAt(i));
+        }
+        pkg.keySetData.removeAllUpgradeKeySets();
+
+        /* switch to the just-added */
+        pkg.keySetData.setAliases(newKeySetAliases);
+        return;
     }
 
     /**
-     * Fetches the {@link KeySetHandle} that a given package refers to by the
-     * provided alias. Returns null if the package is unknown or does not have a
+     * This informs the system that the given package has defined a KeySet
+     * alias in its manifest to be an upgradeKeySet.  This must be called
+     * after all of the defined KeySets have been added.
+     */
+    public void addUpgradeKeySetsToPackageLPw(String packageName,
+        ArraySet<String> upgradeAliases) {
+        PackageSetting pkg = mPackages.get(packageName);
+        final int uaSize = upgradeAliases.size();
+        for (int i = 0; i < uaSize; i++) {
+            pkg.keySetData.addUpgradeKeySet(upgradeAliases.valueAt(i));
+        }
+        return;
+    }
+
+    /**
+     * Fetched the {@link KeySetHandle} that a given package refers to by the
+     * provided alias.  Returns null if the package is unknown or does not have a
      * KeySet corresponding to that alias.
      */
     public KeySetHandle getKeySetByAliasAndPackageNameLPr(String packageName, String alias) {
         PackageSetting p = mPackages.get(packageName);
         if (p == null || p.keySetData == null) {
-                return null;
+            return null;
         }
         Long keySetId = p.keySetData.getAliases().get(alias);
         if (keySetId == null) {
@@ -243,8 +289,10 @@
             return null;
         }
         ArraySet<PublicKey> mPubKeys = new ArraySet<PublicKey>();
-        for (long pkId : mKeySetMapping.get(id)) {
-            mPubKeys.add(mPublicKeys.get(pkId));
+        ArraySet<Long> pkIds = mKeySetMapping.get(id);
+        final int pkSize = pkIds.size();
+        for (int i = 0; i < pkSize; i++) {
+            mPubKeys.add(mPublicKeys.get(pkIds.valueAt(i)).getKey());
         }
         return mPubKeys;
     }
@@ -254,7 +302,7 @@
      * package.
      *
      * @throws IllegalArgumentException if the package has no keyset data.
-     * @throws NullPointerException if the package is unknown.
+     * @throws NullPointerException if the packgae is unknown.
      */
     public KeySetHandle  getSigningKeySetByPackageNameLPr(String packageName) {
         PackageSetting p = mPackages.get(packageName);
@@ -268,99 +316,100 @@
     }
 
     /**
-     * Fetches all the known {@link KeySetHandle KeySets} that may upgrade the given
-     * package.
-     *
-     * @throws IllegalArgumentException if the package has no keyset data.
-     * @throws NullPointerException if the package is unknown.
-     */
-    public ArraySet<KeySetHandle> getUpgradeKeySetsByPackageNameLPr(String packageName) {
-        ArraySet<KeySetHandle> upgradeKeySets = new ArraySet<KeySetHandle>();
-        PackageSetting p = mPackages.get(packageName);
-        if (p == null) {
-            throw new NullPointerException("Unknown package");
-        }
-        if (p.keySetData == null) {
-            throw new IllegalArgumentException("Package has no keySet data");
-        }
-        if (p.keySetData.isUsingUpgradeKeySets()) {
-            for (long l : p.keySetData.getUpgradeKeySets()) {
-                upgradeKeySets.add(mKeySets.get(l));
-            }
-        }
-        return upgradeKeySets;
-    }
-
-    /**
      * Creates a new KeySet corresponding to the given keys.
      *
      * If the {@link PublicKey PublicKeys} aren't known to the system, this
-     * adds them. Otherwise, they're deduped.
+     * adds them. Otherwise, they're deduped and the reference count
+     * incremented.
      *
      * If the KeySet isn't known to the system, this adds that and creates the
-     * mapping to the PublicKeys. If it is known, then it's deduped.
-     *
-     * If the KeySet isn't known to the system, this adds it to all appropriate
-     * signingKeySets
+     * mapping to the PublicKeys. If it is known, then it's deduped and the
+     * reference count is incremented.
      *
      * Throws if the provided set is {@code null}.
      */
     private KeySetHandle addKeySetLPw(ArraySet<PublicKey> keys) {
-        if (keys == null) {
-            throw new NullPointerException("Provided keys cannot be null");
+        if (keys == null || keys.size() == 0) {
+            throw new IllegalArgumentException("Cannot add an empty set of keys!");
         }
-        // add each of the keys in the provided set
+
+        /* add each of the keys in the provided set */
         ArraySet<Long> addedKeyIds = new ArraySet<Long>(keys.size());
-        for (PublicKey k : keys) {
-            long id = addPublicKeyLPw(k);
+        final int kSize = keys.size();
+        for (int i = 0; i < kSize; i++) {
+            long id = addPublicKeyLPw(keys.valueAt(i));
             addedKeyIds.add(id);
         }
 
-        // check to see if the resulting keyset is new
+        /* check to see if the resulting keyset is new */
         long existingKeySetId = getIdFromKeyIdsLPr(addedKeyIds);
         if (existingKeySetId != KEYSET_NOT_FOUND) {
-            return mKeySets.get(existingKeySetId);
+
+            /* public keys were incremented, but we aren't adding a new keyset: undo */
+            for (int i = 0; i < kSize; i++) {
+                decrementPublicKeyLPw(addedKeyIds.valueAt(i));
+            }
+            KeySetHandle ks = mKeySets.get(existingKeySetId);
+            ks.incrRefCountLPw();
+            return ks;
         }
 
-        // create the KeySet object
-        KeySetHandle ks = new KeySetHandle();
-        // get the first unoccupied slot in mKeySets
+        // get the next keyset id
         long id = getFreeKeySetIDLPw();
-        // add the KeySet object to it
+
+        // create the KeySet object and add to mKeySets and mapping
+        KeySetHandle ks = new KeySetHandle(id);
         mKeySets.put(id, ks);
-        // add the stable key ids to the mapping
         mKeySetMapping.put(id, addedKeyIds);
-        // add this KeySet id to all packages which are signed by it
-        for (String pkgName : mPackages.keySet()) {
-            PackageSetting p = mPackages.get(pkgName);
-            if (p.keySetData != null) {
-                long pProperSigning = p.keySetData.getProperSigningKeySet();
-                if (pProperSigning != PackageKeySetData.KEYSET_UNASSIGNED) {
-                    ArraySet<Long> pSigningKeys = mKeySetMapping.get(pProperSigning);
-                    if (pSigningKeys.containsAll(addedKeyIds)) {
-                        p.keySetData.addSigningKeySet(id);
-                    }
-                }
-            }
-        }
-        // go home
         return ks;
     }
 
+    /*
+     * Decrements the reference to KeySet represented by the given id.  If this
+     * drops to zero, then also decrement the reference to each public key it
+     * contains and remove the KeySet.
+     */
+    private void decrementKeySetLPw(long id) {
+        KeySetHandle ks = mKeySets.get(id);
+        if (ks.decrRefCountLPw() <= 0) {
+            ArraySet<Long> pubKeys = mKeySetMapping.get(id);
+            final int pkSize = pubKeys.size();
+            for (int i = 0; i < pkSize; i++) {
+                decrementPublicKeyLPw(pubKeys.valueAt(i));
+            }
+            mKeySets.delete(id);
+            mKeySetMapping.delete(id);
+        }
+        return;
+    }
+
+    /*
+     * Decrements the reference to PublicKey represented by the given id.  If
+     * this drops to zero, then remove it.
+     */
+    private void decrementPublicKeyLPw(long id) {
+        PublicKeyHandle pk = mPublicKeys.get(id);
+        if (pk.decrRefCountLPw() <= 0) {
+            mPublicKeys.delete(id);
+        }
+        return;
+    }
+
     /**
      * Adds the given PublicKey to the system, deduping as it goes.
      */
     private long addPublicKeyLPw(PublicKey key) {
-        // check if the public key is new
-        long existingKeyId = getIdForPublicKeyLPr(key);
-        if (existingKeyId != PUBLIC_KEY_NOT_FOUND) {
-            return existingKeyId;
+        long id = getIdForPublicKeyLPr(key);
+        if (id != PUBLIC_KEY_NOT_FOUND) {
+
+            /* We already know about this key, increment its ref count and ret */
+            mPublicKeys.get(id).incrRefCountLPw();
+            return id;
         }
-        // if it's new find the first unoccupied slot in the public keys
-        long id = getFreePublicKeyIdLPw();
-        // add the public key to it
-        mPublicKeys.put(id, key);
-        // return the stable identifier
+
+        /* if it's new find the first unoccupied slot in the public keys */
+        id = getFreePublicKeyIdLPw();
+        mPublicKeys.put(id, new PublicKeyHandle(id, key));
         return id;
     }
 
@@ -385,7 +434,7 @@
     private long getIdForPublicKeyLPr(PublicKey k) {
         String encodedPublicKey = new String(k.getEncoded());
         for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) {
-            PublicKey value = mPublicKeys.valueAt(publicKeyIndex);
+            PublicKey value = mPublicKeys.valueAt(publicKeyIndex).getKey();
             String encodedExistingKey = new String(value.getEncoded());
             if (encodedPublicKey.equals(encodedExistingKey)) {
                 return mPublicKeys.keyAt(publicKeyIndex);
@@ -410,83 +459,32 @@
         return lastIssuedKeyId;
     }
 
+    /*
+     * This package is being removed from the system, so we need to
+     * remove its keyset and public key references, then remove its
+     * keyset data.
+     */
     public void removeAppKeySetDataLPw(String packageName) {
-        // Get the package's known keys and KeySets
-        ArraySet<Long> deletableKeySets = getOriginalKeySetsByPackageNameLPr(packageName);
-        ArraySet<Long> deletableKeys = new ArraySet<Long>();
-        final int origDksSize = deletableKeySets.size();
-        for (int i = 0; i < origDksSize; i++) {
-            ArraySet<Long> knownKeys = mKeySetMapping.get(deletableKeySets.valueAt(i));
-            if (knownKeys != null) {
-                deletableKeys.addAll(knownKeys);
-            }
+
+        /* remove refs from common keysets and public keys */
+        PackageSetting pkg = mPackages.get(packageName);
+        long signingKeySetId = pkg.keySetData.getProperSigningKeySet();
+        decrementKeySetLPw(signingKeySetId);
+        ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases();
+        for (int i = 0; i < definedKeySets.size(); i++) {
+            decrementKeySetLPw(definedKeySets.valueAt(i));
         }
 
-        // Now remove the keys and KeySets on which any other package relies
-        for (String pkgName : mPackages.keySet()) {
-            if (pkgName.equals(packageName)) {
-                continue;
-            }
-            ArraySet<Long> knownKeySets = getOriginalKeySetsByPackageNameLPr(pkgName);
-            deletableKeySets.removeAll(knownKeySets);
-            final int kksSize = knownKeySets.size();
-            for (int i = 0; i < kksSize; i++) {
-                ArraySet<Long> knownKeys = mKeySetMapping.get(knownKeySets.valueAt(i));
-                if (knownKeys != null) {
-                    deletableKeys.removeAll(knownKeys);
-                }
-            }
-        }
-
-        // The remaining keys and KeySets are not relied on by any other
-        // application and so can be safely deleted.
-        final int dksSize = deletableKeySets.size();
-        for (int i = 0; i < dksSize; i++) {
-            Long ks = deletableKeySets.valueAt(i);
-            mKeySets.delete(ks);
-            mKeySetMapping.delete(ks);
-        }
-        final int dkSize = deletableKeys.size();
-        for (int i = 0; i < dkSize; i++) {
-            mPublicKeys.delete(deletableKeys.valueAt(i));
-        }
-
-        // Now remove the deleted KeySets from each package's signingKeySets
-        for (String pkgName : mPackages.keySet()) {
-            PackageSetting p = mPackages.get(pkgName);
-            for (int i = 0; i < dksSize; i++) {
-                Long ks = deletableKeySets.valueAt(i);
-                p.keySetData.removeSigningKeySet(ks);
-            }
-        }
-        // Finally, remove all KeySets from the original package
-        PackageSetting p = mPackages.get(packageName);
-        clearPackageKeySetDataLPw(p);
-    }
-
-    private void clearPackageKeySetDataLPw(PackageSetting p) {
-        p.keySetData.removeAllSigningKeySets();
-        p.keySetData.removeAllUpgradeKeySets();
-        p.keySetData.removeAllDefinedKeySets();
+        /* remove from package */
+        clearPackageKeySetDataLPw(pkg);
         return;
     }
 
-    private ArraySet<Long> getOriginalKeySetsByPackageNameLPr(String packageName) {
-        PackageSetting p = mPackages.get(packageName);
-        if (p == null) {
-            throw new NullPointerException("Unknown package");
-        }
-        if (p.keySetData == null) {
-            throw new IllegalArgumentException("Package has no keySet data");
-        }
-        ArraySet<Long> knownKeySets = new ArraySet<Long>();
-        knownKeySets.add(p.keySetData.getProperSigningKeySet());
-        if (p.keySetData.isUsingDefinedKeySets()) {
-            for (long ks : p.keySetData.getDefinedKeySets()) {
-                knownKeySets.add(ks);
-            }
-        }
-        return knownKeySets;
+    private void clearPackageKeySetDataLPw(PackageSetting pkg) {
+        pkg.keySetData.setProperSigningKeySet(PackageKeySetData.KEYSET_UNASSIGNED);
+        pkg.keySetData.removeAllDefinedKeySets();
+        pkg.keySetData.removeAllUpgradeKeySets();
+        return;
     }
 
     public String encodePublicKey(PublicKey k) throws IOException {
@@ -496,7 +494,7 @@
     public void dumpLPr(PrintWriter pw, String packageName,
                         PackageManagerService.DumpState dumpState) {
         boolean printedHeader = false;
-        for (Map.Entry<String, PackageSetting> e : mPackages.entrySet()) {
+        for (ArrayMap.Entry<String, PackageSetting> e : mPackages.entrySet()) {
             String keySetPackage = e.getKey();
             if (packageName != null && !packageName.equals(keySetPackage)) {
                 continue;
@@ -511,7 +509,7 @@
             pw.print("  ["); pw.print(keySetPackage); pw.println("]");
             if (pkg.keySetData != null) {
                 boolean printedLabel = false;
-                for (Map.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) {
+                for (ArrayMap.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) {
                     if (!printedLabel) {
                         pw.print("      KeySets Aliases: ");
                         printedLabel = true;
@@ -527,36 +525,26 @@
                 }
                 printedLabel = false;
                 if (pkg.keySetData.isUsingDefinedKeySets()) {
-                    for (long keySetId : pkg.keySetData.getDefinedKeySets()) {
+                    ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases();
+                    final int dksSize = definedKeySets.size();
+                    for (int i = 0; i < dksSize; i++) {
                         if (!printedLabel) {
                             pw.print("      Defined KeySets: ");
                             printedLabel = true;
                         } else {
                             pw.print(", ");
                         }
-                        pw.print(Long.toString(keySetId));
+                        pw.print(Long.toString(definedKeySets.valueAt(i)));
                     }
                 }
                 if (printedLabel) {
                     pw.println("");
                 }
                 printedLabel = false;
-                final long[] signingKeySets = pkg.keySetData.getSigningKeySets();
-                if (signingKeySets != null) {
-                    for (long keySetId : signingKeySets) {
-                        if (!printedLabel) {
-                            pw.print("      Signing KeySets: ");
-                            printedLabel = true;
-                        } else {
-                            pw.print(", ");
-                        }
-                        pw.print(Long.toString(keySetId));
-                    }
-                }
-                if (printedLabel) {
-                    pw.println("");
-                }
-                printedLabel = false;
+                final long signingKeySet = pkg.keySetData.getProperSigningKeySet();
+                pw.print("      Signing KeySets: ");
+                pw.print(Long.toString(signingKeySet));
+                pw.println("");
                 if (pkg.keySetData.isUsingUpgradeKeySets()) {
                     for (long keySetId : pkg.keySetData.getUpgradeKeySets()) {
                         if (!printedLabel) {
@@ -593,8 +581,8 @@
         serializer.startTag(null, "keys");
         for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) {
             long id = mPublicKeys.keyAt(pKeyIndex);
-            PublicKey key = mPublicKeys.valueAt(pKeyIndex);
-            String encodedKey = encodePublicKey(key);
+            PublicKeyHandle pkh = mPublicKeys.valueAt(pKeyIndex);
+            String encodedKey = encodePublicKey(pkh.getKey());
             serializer.startTag(null, "public-key");
             serializer.attribute(null, "identifier", Long.toString(id));
             serializer.attribute(null, "value", encodedKey);
@@ -620,17 +608,17 @@
         serializer.endTag(null, "keysets");
     }
 
-    void readKeySetsLPw(XmlPullParser parser)
+    void readKeySetsLPw(XmlPullParser parser, ArrayMap<Long, Integer> keySetRefCounts)
             throws XmlPullParserException, IOException {
         int type;
         long currentKeySetId = 0;
         int outerDepth = parser.getDepth();
-        String recordedVersion = parser.getAttributeValue(null, "version");
-        if (recordedVersion == null || Integer.parseInt(recordedVersion) != CURRENT_VERSION) {
+        String recordedVersionStr = parser.getAttributeValue(null, "version");
+        if (recordedVersionStr == null) {
+            // The keyset information comes from pre-versioned devices, and
+            // is inaccurate, don't collect any of it.
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-                // Our version is different than the one which generated the old keyset data.
-                // We don't want any of the old data, but we must advance the parser
                 continue;
             }
             // The KeySet information read previously from packages.xml is invalid.
@@ -640,6 +628,7 @@
             }
             return;
         }
+        int recordedVersion = Integer.parseInt(recordedVersionStr);
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
@@ -656,6 +645,8 @@
                 lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value"));
             }
         }
+
+        addRefCountsFromSavedPackagesLPw(keySetRefCounts);
     }
 
     void readKeysLPw(XmlPullParser parser)
@@ -686,29 +677,49 @@
             }
             final String tagName = parser.getName();
             if (tagName.equals("keyset")) {
-                currentKeySetId = readIdentifierLPw(parser);
-                mKeySets.put(currentKeySetId, new KeySetHandle());
+                String encodedID = parser.getAttributeValue(null, "identifier");
+                currentKeySetId = Long.parseLong(encodedID);
+                int refCount = 0;
+                mKeySets.put(currentKeySetId, new KeySetHandle(currentKeySetId, refCount));
                 mKeySetMapping.put(currentKeySetId, new ArraySet<Long>());
             } else if (tagName.equals("key-id")) {
-                long id = readIdentifierLPw(parser);
+                String encodedID = parser.getAttributeValue(null, "identifier");
+                long id = Long.parseLong(encodedID);
                 mKeySetMapping.get(currentKeySetId).add(id);
             }
         }
     }
 
-    long readIdentifierLPw(XmlPullParser parser)
-            throws XmlPullParserException {
-        return Long.parseLong(parser.getAttributeValue(null, "identifier"));
-    }
-
     void readPublicKeyLPw(XmlPullParser parser)
             throws XmlPullParserException {
         String encodedID = parser.getAttributeValue(null, "identifier");
         long identifier = Long.parseLong(encodedID);
+        int refCount = 0;
         String encodedPublicKey = parser.getAttributeValue(null, "value");
         PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey);
         if (pub != null) {
-            mPublicKeys.put(identifier, pub);
+            PublicKeyHandle pkh = new PublicKeyHandle(identifier, refCount, pub);
+            mPublicKeys.put(identifier, pkh);
+        }
+    }
+
+    /*
+     * Set each KeySet ref count.  Also increment all public keys in each keyset.
+     */
+    private void addRefCountsFromSavedPackagesLPw(ArrayMap<Long, Integer> keySetRefCounts) {
+        final int numRefCounts = keySetRefCounts.size();
+        for (int i = 0; i < numRefCounts; i++) {
+            KeySetHandle ks = mKeySets.get(keySetRefCounts.keyAt(i));
+            ks.setRefCountLPw(keySetRefCounts.valueAt(i));
+        }
+
+        final int numKeySets = mKeySets.size();
+        for (int i = 0; i < numKeySets; i++) {
+            ArraySet<Long> pubKeys = mKeySetMapping.valueAt(i);
+            final int pkSize = pubKeys.size();
+            for (int j = 0; j < pkSize; j++) {
+                mPublicKeys.get(pubKeys.valueAt(j)).incrRefCountLPw();
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 2dbce0a..680ec4b 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import android.annotation.Nullable;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageParser;
 import android.os.UserHandle;
@@ -23,6 +24,7 @@
 import android.util.Log;
 import android.util.Slog;
 
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -38,7 +40,9 @@
  * Helper class for running dexopt command on packages.
  */
 final class PackageDexOptimizer {
-    static final String TAG = "PackageManager.DexOptimizer";
+    private static final String TAG = "PackageManager.DexOptimizer";
+    static final String OAT_DIR_NAME = "oat";
+    // TODO b/19550105 Remove error codes and use exceptions
     static final int DEX_OPT_SKIPPED = 0;
     static final int DEX_OPT_PERFORMED = 1;
     static final int DEX_OPT_DEFERRED = 2;
@@ -117,19 +121,30 @@
                     final byte isDexOptNeeded = DexFile.isDexOptNeededInternal(path,
                             pkg.packageName, dexCodeInstructionSet, defer);
                     if (forceDex || (!defer && isDexOptNeeded == DexFile.DEXOPT_NEEDED)) {
+                        File oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
                         Log.i(TAG, "Running dexopt on: " + path + " pkg="
                                 + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
-                                + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable);
+                                + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
+                                + " oatDir = " + oatDir);
                         final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
-                        final int ret = mPackageManagerService.mInstaller.dexopt(path, sharedGid,
-                                !pkg.isForwardLocked(), pkg.packageName, dexCodeInstructionSet,
-                                vmSafeMode, debuggable);
 
-                        if (ret < 0) {
-                            // Don't bother running dexopt again if we failed, it will probably
-                            // just result in an error again. Also, don't bother dexopting for other
-                            // paths & ISAs.
-                            return DEX_OPT_FAILED;
+                        if (oatDir != null) {
+                            int ret = mPackageManagerService.mInstaller.dexopt(
+                                    path, sharedGid, !pkg.isForwardLocked(), pkg.packageName,
+                                    dexCodeInstructionSet, vmSafeMode, debuggable,
+                                    oatDir.getAbsolutePath());
+                            if (ret < 0) {
+                                return DEX_OPT_FAILED;
+                            }
+                        } else {
+                            final int ret = mPackageManagerService.mInstaller
+                                    .dexopt(path, sharedGid,
+                                            !pkg.isForwardLocked(), pkg.packageName,
+                                            dexCodeInstructionSet,
+                                            vmSafeMode, debuggable, null);
+                            if (ret < 0) {
+                                return DEX_OPT_FAILED;
+                            }
                         }
 
                         performedDexOpt = true;
@@ -186,6 +201,36 @@
         return performedDexOpt ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
     }
 
+    /**
+     * Creates oat dir for the specified package. In certain cases oat directory
+     * <strong>cannot</strong> be created:
+     * <ul>
+     *      <li>{@code pkg} is a system app, which is not updated.</li>
+     *      <li>Package location is not a directory, i.e. monolithic install.</li>
+     * </ul>
+     *
+     * @return oat directory or null, if oat directory cannot be created.
+     */
+    @Nullable
+    private File createOatDirIfSupported(PackageParser.Package pkg, String dexInstructionSet)
+            throws IOException {
+        if (pkg.isSystemApp() && !pkg.isUpdatedSystemApp()) {
+            return null;
+        }
+        File codePath = new File(pkg.codePath);
+        if (codePath.isDirectory()) {
+            File oatDir = getOatDir(codePath);
+            mPackageManagerService.mInstaller.createOatDir(oatDir.getAbsolutePath(),
+                    dexInstructionSet);
+            return oatDir;
+        }
+        return null;
+    }
+
+    static File getOatDir(File codePath) {
+        return new File(codePath, OAT_DIR_NAME);
+    }
+
     private void performDexOptLibsLI(ArrayList<String> libs, String[] instructionSets,
             boolean forceDex, boolean defer, ArraySet<String> done) {
         for (String libName : libs) {
@@ -209,7 +254,7 @@
 
     public void addPackageForDeferredDexopt(PackageParser.Package pkg) {
         if (mDeferredDexOpt == null) {
-            mDeferredDexOpt = new ArraySet<PackageParser.Package>();
+            mDeferredDexOpt = new ArraySet<>();
         }
         mDeferredDexOpt.add(pkg);
     }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 2150e9a..591dbee 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -31,16 +31,22 @@
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
 import android.app.ActivityManager;
+import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.NotificationManager;
 import android.app.PackageDeleteObserver;
 import android.app.PackageInstallObserver;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageInstaller;
 import android.content.pm.IPackageInstallerCallback;
 import android.content.pm.IPackageInstallerSession;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageInstaller.SessionParams;
@@ -53,7 +59,6 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
-import android.os.FileUtils;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -64,6 +69,8 @@
 import android.os.SELinux;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.text.TextUtils;
@@ -76,15 +83,17 @@
 import android.util.SparseBooleanArray;
 import android.util.Xml;
 
+import libcore.io.IoUtils;
+
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageHelper;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.ImageUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.IoThread;
 import com.google.android.collect.Sets;
 
-import libcore.io.IoUtils;
-
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -132,6 +141,7 @@
     private static final String ATTR_ORIGINATING_URI = "originatingUri";
     private static final String ATTR_REFERRER_URI = "referrerUri";
     private static final String ATTR_ABI_OVERRIDE = "abiOverride";
+    private static final String ATTR_VOLUME_UUID = "volumeUuid";
 
     /** Automatically destroy sessions older than this */
     private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS;
@@ -142,9 +152,10 @@
 
     private final Context mContext;
     private final PackageManagerService mPm;
-    private final AppOpsManager mAppOps;
 
-    private final File mStagingDir;
+    private AppOpsManager mAppOps;
+    private StorageManager mStorage;
+
     private final HandlerThread mInstallThread;
     private final Handler mInstallHandler;
 
@@ -187,12 +198,9 @@
         }
     };
 
-    public PackageInstallerService(Context context, PackageManagerService pm, File stagingDir) {
+    public PackageInstallerService(Context context, PackageManagerService pm) {
         mContext = context;
         mPm = pm;
-        mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
-
-        mStagingDir = stagingDir;
 
         mInstallThread = new HandlerThread(TAG);
         mInstallThread.start();
@@ -209,8 +217,9 @@
         synchronized (mSessions) {
             readSessionsLocked();
 
+            final File internalStagingDir = buildInternalStagingDir();
             final ArraySet<File> unclaimedStages = Sets.newArraySet(
-                    mStagingDir.listFiles(sStageFilter));
+                    internalStagingDir.listFiles(sStageFilter));
             final ArraySet<File> unclaimedIcons = Sets.newArraySet(
                     mSessionsDir.listFiles());
 
@@ -225,9 +234,10 @@
             for (File stage : unclaimedStages) {
                 Slog.w(TAG, "Deleting orphan stage " + stage);
                 if (stage.isDirectory()) {
-                    FileUtils.deleteContents(stage);
+                    mPm.mInstaller.rmPackageDir(stage.getAbsolutePath());
+                } else {
+                    stage.delete();
                 }
-                stage.delete();
             }
 
             // Clean up orphaned icons
@@ -238,6 +248,11 @@
         }
     }
 
+    public void systemReady() {
+        mAppOps = mContext.getSystemService(AppOpsManager.class);
+        mStorage = mContext.getSystemService(StorageManager.class);
+    }
+
     public void onSecureContainersAvailable() {
         synchronized (mSessions) {
             final ArraySet<String> unclaimed = new ArraySet<>();
@@ -275,13 +290,13 @@
     }
 
     @Deprecated
-    public File allocateInternalStageDirLegacy() throws IOException {
+    public File allocateStageDirLegacy(String volumeUuid) throws IOException {
         synchronized (mSessions) {
             try {
                 final int sessionId = allocateSessionIdLocked();
                 mLegacySessions.put(sessionId, true);
-                final File stageDir = buildInternalStageDir(sessionId);
-                prepareInternalStageDir(stageDir);
+                final File stageDir = buildStageDir(volumeUuid, sessionId);
+                prepareStageDir(stageDir);
                 return stageDir;
             } catch (IllegalStateException e) {
                 throw new IOException(e);
@@ -322,11 +337,6 @@
                             Slog.w(TAG, "Abandoning old session first created at "
                                     + session.createdMillis);
                             valid = false;
-                        } else if (session.stageDir != null
-                                && !session.stageDir.exists()) {
-                            Slog.w(TAG, "Abandoning internal session with missing stage "
-                                    + session.stageDir);
-                            valid = false;
                         } else {
                             valid = true;
                         }
@@ -378,6 +388,7 @@
         params.originatingUri = readUriAttribute(in, ATTR_ORIGINATING_URI);
         params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI);
         params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE);
+        params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
 
         final File appIconFile = buildAppIconFile(sessionId);
         if (appIconFile.exists()) {
@@ -448,6 +459,7 @@
         writeUriAttribute(out, ATTR_ORIGINATING_URI, params.originatingUri);
         writeUriAttribute(out, ATTR_REFERRER_URI, params.referrerUri);
         writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride);
+        writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid);
 
         // Persist app icon if changed since last written
         final File appIconFile = buildAppIconFile(session.sessionId);
@@ -528,28 +540,40 @@
             }
         }
 
-        if (params.mode == SessionParams.MODE_FULL_INSTALL
-                || params.mode == SessionParams.MODE_INHERIT_EXISTING) {
+        switch (params.mode) {
+            case SessionParams.MODE_FULL_INSTALL:
+            case SessionParams.MODE_INHERIT_EXISTING:
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid install mode: " + params.mode);
+        }
+
+        // If caller requested explicit location, sanity check it, otherwise
+        // resolve the best internal or adopted location.
+        if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+            if (!PackageHelper.fitsOnInternal(mContext, params.sizeBytes)) {
+                throw new IOException("No suitable internal storage available");
+            }
+
+        } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+            if (!PackageHelper.fitsOnExternal(mContext, params.sizeBytes)) {
+                throw new IOException("No suitable external storage available");
+            }
+
+        } else {
+            // For now, installs to adopted media are treated as internal from
+            // an install flag point-of-view.
+            params.setInstallFlagsInternal();
+
             // Resolve best location for install, based on combination of
             // requested install flags, delta size, and manifest settings.
             final long ident = Binder.clearCallingIdentity();
             try {
-                final int resolved = PackageHelper.resolveInstallLocation(mContext,
-                        params.appPackageName, params.installLocation, params.sizeBytes,
-                        params.installFlags);
-
-                if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) {
-                    params.setInstallFlagsInternal();
-                } else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
-                    params.setInstallFlagsExternal();
-                } else {
-                    throw new IOException("No storage with enough free space; res=" + resolved);
-                }
+                params.volumeUuid = PackageHelper.resolveInstallVolume(mContext,
+                        params.appPackageName, params.installLocation, params.sizeBytes);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
-        } else {
-            throw new IllegalArgumentException("Invalid install mode: " + params.mode);
         }
 
         final int sessionId;
@@ -574,7 +598,7 @@
             File stageDir = null;
             String stageCid = null;
             if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
-                stageDir = buildInternalStageDir(sessionId);
+                stageDir = buildStageDir(params.volumeUuid, sessionId);
             } else {
                 stageCid = buildExternalStageCid(sessionId);
             }
@@ -673,11 +697,30 @@
         throw new IllegalStateException("Failed to allocate session ID");
     }
 
-    private File buildInternalStageDir(int sessionId) {
-        return new File(mStagingDir, "vmdl" + sessionId + ".tmp");
+    private File buildInternalStagingDir() {
+        return new File(Environment.getDataDirectory(), "app");
     }
 
-    static void prepareInternalStageDir(File stageDir) throws IOException {
+    private File buildStagingDir(String volumeUuid) throws FileNotFoundException {
+        if (volumeUuid == null) {
+            return buildInternalStagingDir();
+        } else {
+            final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
+            if (vol != null && vol.type == VolumeInfo.TYPE_PRIVATE
+                    && vol.state == VolumeInfo.STATE_MOUNTED) {
+                return new File(vol.path, "app");
+            } else {
+                throw new FileNotFoundException("Failed to find volume for UUID " + volumeUuid);
+            }
+        }
+    }
+
+    private File buildStageDir(String volumeUuid, int sessionId) throws FileNotFoundException {
+        final File stagingDir = buildStagingDir(volumeUuid);
+        return new File(stagingDir, "vmdl" + sessionId + ".tmp");
+    }
+
+    static void prepareStageDir(File stageDir) throws IOException {
         if (stageDir.exists()) {
             throw new IOException("Session dir already exists: " + stageDir);
         }
@@ -749,16 +792,34 @@
     }
 
     @Override
-    public void uninstall(String packageName, int flags, IntentSender statusReceiver, int userId) {
-        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, true, "uninstall");
+    public void uninstall(String packageName, String callerPackageName, int flags,
+                IntentSender statusReceiver, int userId) {
+        final int callingUid = Binder.getCallingUid();
+        mPm.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall");
+        if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) {
+            mAppOps.checkPackage(callingUid, callerPackageName);
+        }
+
+        // Check whether the caller is device owner
+        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        boolean isDeviceOwner = (dpm != null) && dpm.isDeviceOwnerApp(callerPackageName);
 
         final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
-                statusReceiver, packageName);
+                statusReceiver, packageName, isDeviceOwner, userId);
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
                 == PackageManager.PERMISSION_GRANTED) {
             // Sweet, call straight through!
             mPm.deletePackage(packageName, adapter.getBinder(), userId, flags);
-
+        } else if (isDeviceOwner) {
+            // Allow the DeviceOwner to silently delete packages
+            // Need to clear the calling identity to get DELETE_PACKAGES permission
+            long ident = Binder.clearCallingIdentity();
+            try {
+                mPm.deletePackage(packageName, adapter.getBinder(), userId, flags);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
         } else {
             // Take a short detour to confirm with user
             final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
@@ -814,12 +875,21 @@
         private final Context mContext;
         private final IntentSender mTarget;
         private final String mPackageName;
+        private final Notification mNotification;
 
         public PackageDeleteObserverAdapter(Context context, IntentSender target,
-                String packageName) {
+                String packageName, boolean showNotification, int userId) {
             mContext = context;
             mTarget = target;
             mPackageName = packageName;
+            if (showNotification) {
+                mNotification = buildSuccessNotification(mContext,
+                        mContext.getResources().getString(R.string.package_deleted_device_owner),
+                        packageName,
+                        userId);
+            } else {
+                mNotification = null;
+            }
         }
 
         @Override
@@ -837,6 +907,11 @@
 
         @Override
         public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
+            if (PackageManager.DELETE_SUCCEEDED == returnCode && mNotification != null) {
+                NotificationManager notificationManager = (NotificationManager)
+                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+                notificationManager.notify(basePackageName, 0, mNotification);
+            }
             final Intent fillIn = new Intent();
             fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, mPackageName);
             fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
@@ -855,11 +930,16 @@
         private final Context mContext;
         private final IntentSender mTarget;
         private final int mSessionId;
+        private final boolean mShowNotification;
+        private final int mUserId;
 
-        public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId) {
+        public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId,
+                boolean showNotification, int userId) {
             mContext = context;
             mTarget = target;
             mSessionId = sessionId;
+            mShowNotification = showNotification;
+            mUserId = userId;
         }
 
         @Override
@@ -878,6 +958,17 @@
         @Override
         public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                 Bundle extras) {
+            if (PackageManager.INSTALL_SUCCEEDED == returnCode && mShowNotification) {
+                Notification notification = buildSuccessNotification(mContext,
+                        mContext.getResources().getString(R.string.package_installed_device_owner),
+                        basePackageName,
+                        mUserId);
+                if (notification != null) {
+                    NotificationManager notificationManager = (NotificationManager)
+                            mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+                    notificationManager.notify(basePackageName, 0, notification);
+                }
+            }
             final Intent fillIn = new Intent();
             fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
             fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
@@ -899,6 +990,40 @@
         }
     }
 
+    /**
+     * Build a notification for package installation / deletion by device owners that is shown if
+     * the operation succeeds.
+     */
+    private static Notification buildSuccessNotification(Context context, String contentText,
+            String basePackageName, int userId) {
+        PackageInfo packageInfo = null;
+        try {
+            packageInfo = AppGlobals.getPackageManager().getPackageInfo(
+                    basePackageName, 0, userId);
+        } catch (RemoteException ignored) {
+        }
+        if (packageInfo == null || packageInfo.applicationInfo == null) {
+            Slog.w(TAG, "Notification not built for package: " + basePackageName);
+            return null;
+        }
+        PackageManager pm = context.getPackageManager();
+        Bitmap packageIcon = ImageUtils.buildScaledBitmap(
+                packageInfo.applicationInfo.loadIcon(pm),
+                context.getResources().getDimensionPixelSize(
+                        android.R.dimen.notification_large_icon_width),
+                context.getResources().getDimensionPixelSize(
+                        android.R.dimen.notification_large_icon_height));
+        CharSequence packageLabel = packageInfo.applicationInfo.loadLabel(pm);
+        return new Notification.Builder(context)
+                .setSmallIcon(R.drawable.ic_check_circle_24px)
+                .setColor(context.getResources().getColor(
+                        R.color.system_notification_accent_color))
+                .setContentTitle(packageLabel)
+                .setContentText(contentText)
+                .setLargeIcon(packageIcon)
+                .build();
+    }
+
     private static class Callbacks extends Handler {
         private static final int MSG_SESSION_CREATED = 1;
         private static final int MSG_SESSION_BADGING_CHANGED = 2;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index cc1b3ad..46db2d8 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -25,8 +25,9 @@
 import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_WRONLY;
 import static com.android.server.pm.PackageInstallerService.prepareExternalStageCid;
-import static com.android.server.pm.PackageInstallerService.prepareInternalStageDir;
+import static com.android.server.pm.PackageInstallerService.prepareStageDir;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -61,6 +62,9 @@
 import android.util.MathUtils;
 import android.util.Slog;
 
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.NativeLibraryHelper;
 import com.android.internal.content.PackageHelper;
@@ -69,9 +73,6 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
 
-import libcore.io.IoUtils;
-import libcore.io.Libcore;
-
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -92,6 +93,7 @@
     private final Context mContext;
     private final PackageManagerService mPm;
     private final Handler mHandler;
+    private final boolean mIsInstallerDeviceOwner;
 
     final int sessionId;
     final int userId;
@@ -208,8 +210,15 @@
         mPrepared = prepared;
         mSealed = sealed;
 
+        // Device owners are allowed to silently install packages, so the permission check is
+        // waived if the installer is the device owner.
+        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        mIsInstallerDeviceOwner = (dpm != null) && dpm.isDeviceOwnerApp(installerPackageName);
         if ((mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES, installerUid)
-                == PackageManager.PERMISSION_GRANTED) || (installerUid == Process.ROOT_UID)) {
+                == PackageManager.PERMISSION_GRANTED)
+                || (installerUid == Process.ROOT_UID)
+                || mIsInstallerDeviceOwner) {
             mPermissionsAccepted = true;
         } else {
             mPermissionsAccepted = false;
@@ -440,7 +449,7 @@
         mActiveCount.incrementAndGet();
 
         final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
-                statusReceiver, sessionId);
+                statusReceiver, sessionId, mIsInstallerDeviceOwner, userId);
         mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
     }
 
@@ -892,7 +901,7 @@
         synchronized (mLock) {
             if (!mPrepared) {
                 if (stageDir != null) {
-                    prepareInternalStageDir(stageDir);
+                    prepareStageDir(stageDir);
                 } else if (stageCid != null) {
                     prepareExternalStageCid(stageCid, params.sizeBytes);
 
diff --git a/services/core/java/com/android/server/pm/PackageKeySetData.java b/services/core/java/com/android/server/pm/PackageKeySetData.java
index 8f12c03..a9126c0 100644
--- a/services/core/java/com/android/server/pm/PackageKeySetData.java
+++ b/services/core/java/com/android/server/pm/PackageKeySetData.java
@@ -27,12 +27,8 @@
     /* KeySet containing all signing keys - superset of the others */
     private long mProperSigningKeySet;
 
-    private long[] mSigningKeySets;
-
     private long[] mUpgradeKeySets;
 
-    private long[] mDefinedKeySets;
-
     private final ArrayMap<String, Long> mKeySetAliases = new ArrayMap<String, Long>();
 
     PackageKeySetData() {
@@ -41,23 +37,12 @@
 
     PackageKeySetData(PackageKeySetData original) {
         mProperSigningKeySet = original.mProperSigningKeySet;
-        mSigningKeySets = ArrayUtils.cloneOrNull(original.mSigningKeySets);
         mUpgradeKeySets = ArrayUtils.cloneOrNull(original.mUpgradeKeySets);
-        mDefinedKeySets = ArrayUtils.cloneOrNull(original.mDefinedKeySets);
         mKeySetAliases.putAll(original.mKeySetAliases);
     }
 
     protected void setProperSigningKeySet(long ks) {
-        if (ks == mProperSigningKeySet) {
-
-            /* nothing to change */
-            return;
-        }
-
-        /* otherwise, our current signing keysets are likely invalid */
-        removeAllSigningKeySets();
         mProperSigningKeySet = ks;
-        addSigningKeySet(ks);
         return;
     }
 
@@ -65,15 +50,10 @@
         return mProperSigningKeySet;
     }
 
-    protected void addSigningKeySet(long ks) {
-        mSigningKeySets = ArrayUtils.appendLong(mSigningKeySets, ks);
-    }
-
-    protected void removeSigningKeySet(long ks) {
-        mSigningKeySets = ArrayUtils.removeLong(mSigningKeySets, ks);
-    }
-
     protected void addUpgradeKeySet(String alias) {
+        if (alias == null) {
+            return;
+        }
 
         /* must have previously been defined */
         Long ks = mKeySetAliases.get(alias);
@@ -89,19 +69,9 @@
      * Used only when restoring keyset data from persistent storage.  Must
      * correspond to a defined-keyset.
      */
+
     protected void addUpgradeKeySetById(long ks) {
-        mSigningKeySets = ArrayUtils.appendLong(mSigningKeySets, ks);
-    }
-
-    protected void addDefinedKeySet(long ks, String alias) {
-        mDefinedKeySets = ArrayUtils.appendLong(mDefinedKeySets, ks);
-        mKeySetAliases.put(alias, ks);
-    }
-
-    protected void removeAllSigningKeySets() {
-        mProperSigningKeySet = KEYSET_UNASSIGNED;
-        mSigningKeySets = null;
-        return;
+        mUpgradeKeySets = ArrayUtils.appendLong(mUpgradeKeySets, ks);
     }
 
     protected void removeAllUpgradeKeySets() {
@@ -109,36 +79,44 @@
         return;
     }
 
-    protected void removeAllDefinedKeySets() {
-        mDefinedKeySets = null;
-        mKeySetAliases.clear();
-        return;
-    }
-
-    protected boolean packageIsSignedBy(long ks) {
-        return ArrayUtils.contains(mSigningKeySets, ks);
-    }
-
-    protected long[] getSigningKeySets() {
-        return mSigningKeySets;
-    }
-
     protected long[] getUpgradeKeySets() {
         return mUpgradeKeySets;
     }
 
-    protected long[] getDefinedKeySets() {
-        return mDefinedKeySets;
-    }
-
     protected ArrayMap<String, Long> getAliases() {
         return mKeySetAliases;
     }
 
+    /*
+     * Replace defined keysets with new ones.
+     */
+    protected void setAliases(ArrayMap<String, Long> newAliases) {
+
+        /* remove old aliases */
+        removeAllDefinedKeySets();
+
+        /* add new ones */
+        final int newAliasSize = newAliases.size();
+        for (int i = 0; i < newAliasSize; i++) {
+            mKeySetAliases.put(newAliases.keyAt(i), newAliases.valueAt(i));;
+        }
+    }
+
+    protected void addDefinedKeySet(long ks, String alias) {
+        mKeySetAliases.put(alias, ks);
+    }
+
+    protected void removeAllDefinedKeySets() {
+        final int aliasSize = mKeySetAliases.size();
+        for (int i = 0; i < aliasSize; i++) {
+            mKeySetAliases.removeAt(i);
+        }
+    }
+
     protected boolean isUsingDefinedKeySets() {
 
-        /* should never be the case that mDefinedKeySets.length == 0 */
-        return (mDefinedKeySets != null && mDefinedKeySets.length > 0);
+        /* should never be the case that mUpgradeKeySets.length == 0 */
+        return (mKeySetAliases.size() > 0);
     }
 
     protected boolean isUsingUpgradeKeySets() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2629e48..e7ba582 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -43,7 +43,17 @@
 import static android.content.pm.PackageManager.INSTALL_FAILED_USER_RESTRICTED;
 import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
 import static android.content.pm.PackageManager.INSTALL_FORWARD_LOCK;
+import static android.content.pm.PackageManager.INSTALL_INTERNAL;
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+import static android.content.pm.PackageManager.MOVE_EXTERNAL_MEDIA;
+import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST;
+import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING;
+import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
+import static android.content.pm.PackageManager.MOVE_INTERNAL;
 import static android.content.pm.PackageParser.isApkFile;
 import static android.os.Process.PACKAGE_INFO_GID;
 import static android.os.Process.SYSTEM_UID;
@@ -58,30 +68,10 @@
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
 import static com.android.server.pm.InstructionSets.getPreferredInstructionSet;
+import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet;
 
-import android.util.ArrayMap;
-
-import com.android.internal.R;
-import com.android.internal.app.IMediaContainerService;
-import com.android.internal.app.ResolverActivity;
-import com.android.internal.content.NativeLibraryHelper;
-import com.android.internal.content.PackageHelper;
-import com.android.internal.os.IParcelFileDescriptorFactory;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.FastPrintWriter;
-import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.EventLogTags;
-import com.android.server.IntentResolver;
-import com.android.server.LocalServices;
-import com.android.server.ServiceThread;
-import com.android.server.SystemConfig;
-import com.android.server.Watchdog;
-import com.android.server.pm.Settings.DatabaseVersion;
-import com.android.server.storage.DeviceStorageMonitorInternal;
-
-import org.xmlpull.v1.XmlSerializer;
-
+import android.Manifest;
+import org.xmlpull.v1.XmlPullParser;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
@@ -111,6 +101,7 @@
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
+import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.KeySet;
 import android.content.pm.ManifestDigest;
 import android.content.pm.PackageCleanItem;
@@ -119,10 +110,10 @@
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
+import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.ActivityIntentInfo;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.PackageParser;
 import android.content.pm.PackageStats;
 import android.content.pm.PackageUserState;
 import android.content.pm.ParceledListSlice;
@@ -142,11 +133,9 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
-import android.os.storage.IMountService;
-import android.os.storage.StorageManager;
-import android.os.Debug;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBinder;
@@ -162,6 +151,10 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.IMountService;
+import android.os.storage.StorageEventListener;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
 import android.security.KeyStore;
 import android.security.SystemKeyStore;
 import android.system.ErrnoException;
@@ -169,6 +162,7 @@
 import android.system.StructStat;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.DisplayMetrics;
@@ -180,11 +174,41 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
+import android.util.Xml;
 import android.view.Display;
 
+import dalvik.system.DexFile;
+import dalvik.system.VMRuntime;
+
+import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
+
+import com.android.internal.R;
+import com.android.internal.app.IMediaContainerService;
+import com.android.internal.app.ResolverActivity;
+import com.android.internal.content.NativeLibraryHelper;
+import com.android.internal.content.PackageHelper;
+import com.android.internal.os.IParcelFileDescriptorFactory;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.EventLogTags;
+import com.android.server.IntentResolver;
+import com.android.server.LocalServices;
+import com.android.server.ServiceThread;
+import com.android.server.SystemConfig;
+import com.android.server.Watchdog;
+import com.android.server.pm.Settings.DatabaseVersion;
+import com.android.server.storage.DeviceStorageMonitorInternal;
+
+import org.xmlpull.v1.XmlSerializer;
+
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
@@ -214,12 +238,6 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
-import dalvik.system.DexFile;
-import dalvik.system.VMRuntime;
-
-import libcore.io.IoUtils;
-import libcore.util.EmptyArray;
-
 /**
  * Keep track of all those .apks everywhere.
  * 
@@ -237,6 +255,7 @@
     static final boolean DEBUG_SETTINGS = false;
     static final boolean DEBUG_PREFERRED = false;
     static final boolean DEBUG_UPGRADE = false;
+    private static final boolean DEBUG_BACKUP = true;
     private static final boolean DEBUG_INSTALL = false;
     private static final boolean DEBUG_REMOVE = false;
     private static final boolean DEBUG_BROADCASTS = false;
@@ -248,8 +267,7 @@
     private static final boolean DEBUG_DEXOPT = false;
     private static final boolean DEBUG_ABI_SELECTION = false;
 
-    private static final boolean RUNTIME_PERMISSIONS_ENABLED =
-            SystemProperties.getInt("ro.runtime.premissions.enabled", 0) == 1;
+    static final boolean RUNTIME_PERMISSIONS_ENABLED = true;
 
     private static final int RADIO_UID = Process.PHONE_UID;
     private static final int LOG_UID = Process.LOG_UID;
@@ -275,6 +293,7 @@
     static final int SCAN_TRUSTED_OVERLAY = 1<<9;
     static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10;
     static final int SCAN_REPLACING = 1<<11;
+    static final int SCAN_REQUIRE_KNOWN = 1<<12;
 
     static final int REMOVE_CHATTY = 1<<16;
 
@@ -339,7 +358,7 @@
     /** Permission grant: grant the permission as an install permission. */
     private static final int GRANT_INSTALL = 2;
 
-    /** Permission grant: grant the permission as a runtime permission. */
+    /** Permission grant: grant the permission as a runtime one. */
     private static final int GRANT_RUNTIME = 3;
 
     /** Permission grant: grant as runtime a permission that was granted as an install time one. */
@@ -503,6 +522,231 @@
 
     boolean mResolverReplaced = false;
 
+    private final ComponentName mIntentFilterVerifierComponent;
+    private int mIntentFilterVerificationToken = 0;
+
+    final SparseArray<IntentFilterVerificationState> mIntentFilterVerificationStates
+            = new SparseArray<IntentFilterVerificationState>();
+
+    private interface IntentFilterVerifier<T extends IntentFilter> {
+        boolean addOneIntentFilterVerification(int verifierId, int userId, int verificationId,
+                                               T filter, String packageName);
+        void startVerifications(int userId);
+        void receiveVerificationResponse(int verificationId);
+    }
+
+    private class IntentVerifierProxy implements IntentFilterVerifier<ActivityIntentInfo> {
+        private Context mContext;
+        private ComponentName mIntentFilterVerifierComponent;
+        private ArrayList<Integer> mCurrentIntentFilterVerifications = new ArrayList<Integer>();
+
+        public IntentVerifierProxy(Context context, ComponentName verifierComponent) {
+            mContext = context;
+            mIntentFilterVerifierComponent = verifierComponent;
+        }
+
+        private String getDefaultScheme() {
+            // TODO: replace SCHEME_HTTP with SCHEME_HTTPS
+            return IntentFilter.SCHEME_HTTP;
+        }
+
+        @Override
+        public void startVerifications(int userId) {
+            // Launch verifications requests
+            int count = mCurrentIntentFilterVerifications.size();
+            for (int n=0; n<count; n++) {
+                int verificationId = mCurrentIntentFilterVerifications.get(n);
+                final IntentFilterVerificationState ivs =
+                        mIntentFilterVerificationStates.get(verificationId);
+
+                String packageName = ivs.getPackageName();
+                boolean modified = false;
+
+                ArrayList<PackageParser.ActivityIntentInfo> filters = ivs.getFilters();
+                final int filterCount = filters.size();
+                for (int m=0; m<filterCount; m++) {
+                    PackageParser.ActivityIntentInfo filter = filters.get(m);
+                    synchronized (mPackages) {
+                        modified = mSettings.createIntentFilterVerificationIfNeededLPw(
+                                packageName, filter.getHosts());
+                    }
+                }
+                synchronized (mPackages) {
+                    if (modified) {
+                        scheduleWriteSettingsLocked();
+                    }
+                }
+                sendVerificationRequest(userId, verificationId, ivs);
+            }
+            mCurrentIntentFilterVerifications.clear();
+        }
+
+        private void sendVerificationRequest(int userId, int verificationId,
+                                             IntentFilterVerificationState ivs) {
+
+            Intent verificationIntent = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
+            verificationIntent.putExtra(
+                    PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_ID,
+                    verificationId);
+            verificationIntent.putExtra(
+                    PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_URI_SCHEME,
+                    getDefaultScheme());
+            verificationIntent.putExtra(
+                    PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_HOSTS,
+                    ivs.getHostsString());
+            verificationIntent.putExtra(
+                    PackageManager.EXTRA_INTENT_FILTER_VERIFICATION_PACKAGE_NAME,
+                    ivs.getPackageName());
+            verificationIntent.setComponent(mIntentFilterVerifierComponent);
+            verificationIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+
+            UserHandle user = new UserHandle(userId);
+            mContext.sendBroadcastAsUser(verificationIntent, user);
+            Slog.d(TAG, "Sending IntenFilter verification broadcast");
+        }
+
+        public void receiveVerificationResponse(int verificationId) {
+            IntentFilterVerificationState ivs = mIntentFilterVerificationStates.get(verificationId);
+
+            final boolean verified = ivs.isVerified();
+
+            ArrayList<PackageParser.ActivityIntentInfo> filters = ivs.getFilters();
+            final int count = filters.size();
+            for (int n=0; n<count; n++) {
+                PackageParser.ActivityIntentInfo filter = filters.get(n);
+                filter.setVerified(verified);
+
+                Slog.d(TAG, "IntentFilter " + filter.toString() + " verified with result:"
+                        + verified + " and hosts:" + ivs.getHostsString());
+            }
+
+            mIntentFilterVerificationStates.remove(verificationId);
+
+            final String packageName = ivs.getPackageName();
+            IntentFilterVerificationInfo ivi = null;
+
+            synchronized (mPackages) {
+                ivi = mSettings.getIntentFilterVerificationLPr(packageName);
+            }
+            if (ivi == null) {
+                Slog.w(TAG, "IntentFilterVerificationInfo not found for verificationId:"
+                        + verificationId + " packageName:" + packageName);
+                return;
+            }
+            Slog.d(TAG, "Updating IntentFilterVerificationInfo for verificationId: "
+                    + verificationId);
+
+            synchronized (mPackages) {
+                if (verified) {
+                    ivi.setStatus(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS);
+                } else {
+                    ivi.setStatus(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK);
+                }
+                scheduleWriteSettingsLocked();
+
+                final int userId = ivs.getUserId();
+                if (userId != UserHandle.USER_ALL) {
+                    final int userStatus =
+                            mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
+
+                    int updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+                    boolean needUpdate = false;
+
+                    // We cannot override the STATUS_ALWAYS / STATUS_NEVER states if they have
+                    // already been set by the User thru the Disambiguation dialog
+                    switch (userStatus) {
+                        case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED:
+                            if (verified) {
+                                updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+                            } else {
+                                updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
+                            }
+                            needUpdate = true;
+                            break;
+
+                        case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK:
+                            if (verified) {
+                                updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+                                needUpdate = true;
+                            }
+                            break;
+
+                        default:
+                            // Nothing to do
+                    }
+
+                    if (needUpdate) {
+                        mSettings.updateIntentFilterVerificationStatusLPw(
+                                packageName, updatedStatus, userId);
+                        scheduleWritePackageRestrictionsLocked(userId);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean addOneIntentFilterVerification(int verifierId, int userId, int verificationId,
+                    ActivityIntentInfo filter, String packageName) {
+            if (!(filter.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
+                    filter.hasDataScheme(IntentFilter.SCHEME_HTTPS))) {
+                Slog.d(TAG, "IntentFilter does not contain HTTP nor HTTPS data scheme");
+                return false;
+            }
+            IntentFilterVerificationState ivs = mIntentFilterVerificationStates.get(verificationId);
+            if (ivs == null) {
+                ivs = createDomainVerificationState(verifierId, userId, verificationId,
+                        packageName);
+            }
+            ArrayList<String> hosts = filter.getHostsList();
+            if (!hasValidHosts(hosts)) {
+                return false;
+            }
+            ivs.addFilter(filter);
+            return true;
+        }
+
+        private IntentFilterVerificationState createDomainVerificationState(int verifierId,
+                int userId, int verificationId, String packageName) {
+            IntentFilterVerificationState ivs = new IntentFilterVerificationState(
+                    verifierId, userId, packageName);
+            ivs.setPendingState();
+            synchronized (mPackages) {
+                mIntentFilterVerificationStates.append(verificationId, ivs);
+                mCurrentIntentFilterVerifications.add(verificationId);
+            }
+            return ivs;
+        }
+
+        private boolean hasValidHosts(ArrayList<String> hosts) {
+            if (hosts.size() == 0) {
+                Slog.d(TAG, "IntentFilter does not contain any data hosts");
+                return false;
+            }
+            String hostEndBase = null;
+            for (String host : hosts) {
+                String[] hostParts = host.split("\\.");
+                // Should be at minimum a host like "example.com"
+                if (hostParts.length < 2) {
+                    Slog.d(TAG, "IntentFilter does not contain a valid data host name: " + host);
+                    return false;
+                }
+                // Verify that we have the same ending domain
+                int length = hostParts.length;
+                String hostEnd = hostParts[length - 1] + hostParts[length - 2];
+                if (hostEndBase == null) {
+                    hostEndBase = hostEnd;
+                }
+                if (!hostEnd.equalsIgnoreCase(hostEndBase)) {
+                    Slog.d(TAG, "IntentFilter does not contain the same data domains");
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    private IntentFilterVerifier mIntentFilterVerifier;
+
     // Set of pending broadcasts for aggregating enable/disable of components.
     static class PendingPackageBroadcasts {
         // for each user id, a map of <package name -> components within that package>
@@ -589,6 +833,8 @@
     static final int WRITE_PACKAGE_RESTRICTIONS = 14;
     static final int PACKAGE_VERIFIED = 15;
     static final int CHECK_PENDING_VERIFICATION = 16;
+    static final int START_INTENT_FILTER_VERIFICATIONS = 17;
+    static final int INTENT_FILTER_VERIFIED = 18;
 
     static final int WRITE_SETTINGS_DELAY = 10*1000;  // 10 seconds
 
@@ -629,6 +875,9 @@
     final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
     int mNextInstallToken = 1;  // nonzero; will be wrapped back to 1 when ++ overflows
 
+    // backup/restore of preferred activity state
+    private static final String TAG_PREFERRED_BACKUP = "pa";
+
     private final String mRequiredVerifierPackage;
 
     private final PackageUsage mPackageUsage = new PackageUsage();
@@ -1239,10 +1488,79 @@
 
                     break;
                 }
+                case START_INTENT_FILTER_VERIFICATIONS: {
+                    int userId = msg.arg1;
+                    int verifierUid = msg.arg2;
+                    PackageParser.Package pkg = (PackageParser.Package)msg.obj;
+
+                    verifyIntentFiltersIfNeeded(userId, verifierUid, pkg);
+                    break;
+                }
+                case INTENT_FILTER_VERIFIED: {
+                    final int verificationId = msg.arg1;
+
+                    final IntentFilterVerificationState state = mIntentFilterVerificationStates.get(
+                            verificationId);
+                    if (state == null) {
+                        Slog.w(TAG, "Invalid IntentFilter verification token "
+                                + verificationId + " received");
+                        break;
+                    }
+
+                    final int userId = state.getUserId();
+
+                    Slog.d(TAG, "Processing IntentFilter verification with token:"
+                            + verificationId + " and userId:" + userId);
+
+                    final IntentFilterVerificationResponse response =
+                            (IntentFilterVerificationResponse) msg.obj;
+
+                    state.setVerifierResponse(response.callerUid, response.code);
+
+                    Slog.d(TAG, "IntentFilter verification with token:" + verificationId
+                            + " and userId:" + userId
+                            + " is settings verifier response with response code:"
+                            + response.code);
+
+                    if (response.code == PackageManager.INTENT_FILTER_VERIFICATION_FAILURE) {
+                        Slog.d(TAG, "Domains failing verification: "
+                                + response.getFailedDomainsString());
+                    }
+
+                    if (state.isVerificationComplete()) {
+                        mIntentFilterVerifier.receiveVerificationResponse(verificationId);
+                    } else {
+                        Slog.d(TAG, "IntentFilter verification with token:" + verificationId
+                                + " was not said to be complete");
+                    }
+
+                    break;
+                }
             }
         }
     }
 
+    private StorageEventListener mStorageListener = new StorageEventListener() {
+        @Override
+        public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
+            if (vol.type == VolumeInfo.TYPE_PRIVATE) {
+                if (vol.state == VolumeInfo.STATE_MOUNTED) {
+                    loadPrivatePackages(vol);
+                } else if (vol.state == VolumeInfo.STATE_UNMOUNTING) {
+                    unloadPrivatePackages(vol);
+                }
+            }
+
+            if (vol.isPrimary() && vol.type == VolumeInfo.TYPE_PUBLIC) {
+                if (vol.state == VolumeInfo.STATE_MOUNTED) {
+                    updateExternalMediaStatus(true, false);
+                } else if (vol.state == VolumeInfo.STATE_UNMOUNTING) {
+                    updateExternalMediaStatus(false, false);
+                }
+            }
+        }
+    };
+
     private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int userId) {
         if (userId >= UserHandle.USER_OWNER) {
             grantRequestedRuntimePermissionsForUser(pkg, userId);
@@ -1348,7 +1666,7 @@
         mOnlyCore = onlyCore;
         mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
         mMetrics = new DisplayMetrics();
-        mSettings = new Settings(mContext, mPackages);
+        mSettings = new Settings(mPackages);
         mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
@@ -1699,10 +2017,10 @@
             if (!mOnlyCore) {
                 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                         SystemClock.uptimeMillis());
-                scanDirLI(mAppInstallDir, 0, scanFlags, 0);
+                scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
 
                 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
-                        scanFlags, 0);
+                        scanFlags | SCAN_REQUIRE_KNOWN, 0);
 
                 /**
                  * Remove disable package settings for any updated system
@@ -1810,7 +2128,14 @@
                     + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
                     + "; regranting permissions for internal storage");
             mSettings.mInternalSdkPlatform = mSdkVersion;
-            
+
+            // For now runtime permissions are toggled via a system property.
+            if (!RUNTIME_PERMISSIONS_ENABLED) {
+                // Remove the runtime permissions state if the feature
+                // was disabled by flipping the system property.
+                mSettings.deleteRuntimePermissionsFiles();
+            }
+
             updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
                     | (regrantPermissions
                             ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
@@ -1842,13 +2167,17 @@
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                     SystemClock.uptimeMillis());
 
-
             mRequiredVerifierPackage = getRequiredVerifierLPr();
+
+            mInstallerService = new PackageInstallerService(context, this);
+
+            mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
+            mIntentFilterVerifier = new IntentVerifierProxy(mContext,
+                    mIntentFilterVerifierComponent);
+
         } // synchronized (mPackages)
         } // synchronized (mInstallLock)
 
-        mInstallerService = new PackageInstallerService(context, this, mAppInstallDir);
-
         // Now after opening every single application zip, make sure they
         // are all flushed.  Not really needed, but keeps things nice and
         // tidy.
@@ -1902,6 +2231,46 @@
         return requiredVerifier;
     }
 
+    private ComponentName getIntentFilterVerifierComponentNameLPr() {
+        final Intent verification = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
+        final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
+                PackageManager.GET_DISABLED_COMPONENTS, 0 /* userId */);
+
+        ComponentName verifierComponentName = null;
+
+        int priority = -1000;
+        final int N = receivers.size();
+        for (int i = 0; i < N; i++) {
+            final ResolveInfo info = receivers.get(i);
+
+            if (info.activityInfo == null) {
+                continue;
+            }
+
+            final String packageName = info.activityInfo.packageName;
+
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps == null) {
+                continue;
+            }
+
+            if (checkPermission(android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT,
+                    packageName, UserHandle.USER_OWNER) != PackageManager.PERMISSION_GRANTED) {
+                continue;
+            }
+
+            // Select the IntentFilterVerifier with the highest priority
+            if (priority < info.priority) {
+                priority = info.priority;
+                verifierComponentName = new ComponentName(packageName, info.activityInfo.name);
+                Slog.d(TAG, "Selecting IntentFilterVerifier: " + verifierComponentName +
+                        " with priority: " + info.priority);
+            }
+        }
+
+        return verifierComponentName;
+    }
+
     @Override
     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
             throws RemoteException {
@@ -1921,9 +2290,10 @@
         removeDataDirsLI(ps.name);
         if (ps.codePath != null) {
             if (ps.codePath.isDirectory()) {
-                FileUtils.deleteContents(ps.codePath);
+                mInstaller.rmPackageDir(ps.codePath.getAbsolutePath());
+            } else {
+                ps.codePath.delete();
             }
-            ps.codePath.delete();
         }
         if (ps.resourcePath != null && !ps.resourcePath.equals(ps.codePath)) {
             if (ps.resourcePath.isDirectory()) {
@@ -1951,15 +2321,14 @@
             return null;
         }
 
-        PermissionsState permissionsState = ps.getPermissionsState();
+        final PermissionsState permissionsState = ps.getPermissionsState();
 
         final int[] gids = permissionsState.computeGids(userId);
-        Set<String> permissions = permissionsState.getPermissions(userId);
-
+        final Set<String> permissions = permissionsState.getPermissions(userId);
         final PackageUserState state = ps.readUserState(userId);
+
         return PackageParser.generatePackageInfo(p, gids, flags,
-                ps.firstInstallTime, ps.lastUpdateTime, permissions,
-                state, userId);
+                ps.firstInstallTime, ps.lastUpdateTime, permissions, state, userId);
     }
 
     @Override
@@ -2696,6 +3065,10 @@
 
     @Override
     public boolean grantPermission(String packageName, String name, int userId) {
+        if (!RUNTIME_PERMISSIONS_ENABLED) {
+            return false;
+        }
+
         if (!sUserManager.exists(userId)) {
             return false;
         }
@@ -2707,6 +3080,9 @@
         enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
                 "grantPermission");
 
+        boolean gidsChanged = false;
+        final SettingBase sb;
+
         synchronized (mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
             if (pkg == null) {
@@ -2720,7 +3096,7 @@
 
             enforceDeclaredAsUsedAndRuntimePermission(pkg, bp);
 
-            final SettingBase sb = (SettingBase) pkg.mExtras;
+            sb = (SettingBase) pkg.mExtras;
             if (sb == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
@@ -2734,19 +3110,27 @@
                 }
 
                 case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
-                    killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED);
+                    gidsChanged = true;
                 } break;
             }
 
             // Not critical if that is lost - app has to request again.
             mSettings.writeRuntimePermissionsForUserLPr(userId, false);
-
-            return true;
         }
+
+        if (gidsChanged) {
+            killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED);
+        }
+
+        return true;
     }
 
     @Override
     public boolean revokePermission(String packageName, String name, int userId) {
+        if (!RUNTIME_PERMISSIONS_ENABLED) {
+            return false;
+        }
+
         if (!sUserManager.exists(userId)) {
             return false;
         }
@@ -2758,6 +3142,8 @@
         enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
                 "revokePermission");
 
+        final SettingBase sb;
+
         synchronized (mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
             if (pkg == null) {
@@ -2771,7 +3157,7 @@
 
             enforceDeclaredAsUsedAndRuntimePermission(pkg, bp);
 
-            final SettingBase sb = (SettingBase) pkg.mExtras;
+            sb = (SettingBase) pkg.mExtras;
             if (sb == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
@@ -2783,13 +3169,13 @@
                 return false;
             }
 
-            killSettingPackagesForUser(sb, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
-
             // Critical, after this call all should never have the permission.
             mSettings.writeRuntimePermissionsForUserLPr(userId, true);
-
-            return true;
         }
+
+        killSettingPackagesForUser(sb, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
+
+        return true;
     }
 
     @Override
@@ -3509,14 +3895,20 @@
                 resolveInfo = queryCrossProfileIntents(
                         matchingFilters, intent, resolvedType, flags, userId);
 
-                // Check for results in the current profile.
+                // Check for results in the current profile. Adding GET_RESOLVED_FILTER flags
+                // as we need it later
                 List<ResolveInfo> result = mActivities.queryIntent(
                         intent, resolvedType, flags, userId);
                 if (resolveInfo != null) {
                     result.add(resolveInfo);
                     Collections.sort(result, mResolvePrioritySorter);
                 }
-                return filterIfNotPrimaryUser(result, userId);
+                result = filterIfNotPrimaryUser(result, userId);
+                if (result.size() > 1) {
+                    return filterCandidatesWithDomainPreferedActivitiesLPw(result);
+                }
+
+                return result;
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
@@ -3547,6 +3939,49 @@
         return resolveInfos;
     }
 
+    private List<ResolveInfo> filterCandidatesWithDomainPreferedActivitiesLPw(
+            List<ResolveInfo> candidates) {
+        if (DEBUG_PREFERRED) {
+            Slog.v("TAG", "Filtering results with prefered activities. Candidates count: " +
+                    candidates.size());
+        }
+        final int userId = UserHandle.getCallingUserId();
+        ArrayList<ResolveInfo> result = new ArrayList<ResolveInfo>(candidates);
+        synchronized (mPackages) {
+            final int count = result.size();
+            for (int n = count-1; n >= 0; n--) {
+                ResolveInfo info = result.get(n);
+                if (!info.filterNeedsVerification) {
+                    continue;
+                }
+                String packageName = info.activityInfo.packageName;
+                PackageSetting ps = mSettings.mPackages.get(packageName);
+                if (ps != null) {
+                    // Try to get the status from User settings first
+                    int status = ps.getDomainVerificationStatusForUser(userId);
+                    // if none available, get the master status
+                    if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
+                        if (ps.getIntentFilterVerificationInfo() != null) {
+                            status = ps.getIntentFilterVerificationInfo().getStatus();
+                        }
+                    }
+                    if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
+                        result.clear();
+                        result.add(info);
+                        // We break the for loop as we are good to go
+                        break;
+                    } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
+                        result.remove(n);
+                    }
+                }
+            }
+        }
+        if (DEBUG_PREFERRED) {
+            Slog.v("TAG", "Filtered results with prefered activities. New candidates count: " +
+                    result.size());
+        }
+        return result;
+    }
 
     private ResolveInfo querySkipCurrentProfileIntents(
             List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
@@ -4307,9 +4742,10 @@
                         e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
                     logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
                     if (file.isDirectory()) {
-                        FileUtils.deleteContents(file);
+                        mInstaller.rmPackageDir(file.getAbsolutePath());
+                    } else {
+                        file.delete();
                     }
-                    file.delete();
                 }
             }
         }
@@ -4757,7 +5193,7 @@
             // Give priority to system apps.
             for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
                 PackageParser.Package pkg = it.next();
-                if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
+                if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) {
                     if (DEBUG_DEXOPT) {
                         Log.i(TAG, "Adding system app " + sortedPkgs.size() + ": " + pkg.packageName);
                     }
@@ -4768,7 +5204,7 @@
             // Give priority to updated system apps.
             for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
                 PackageParser.Package pkg = it.next();
-                if (isUpdatedSystemApp(pkg)) {
+                if (pkg.isUpdatedSystemApp()) {
                     if (DEBUG_DEXOPT) {
                         Log.i(TAG, "Adding updated system app " + sortedPkgs.size() + ": " + pkg.packageName);
                     }
@@ -4889,14 +5325,6 @@
         return performDexOpt(packageName, instructionSet, false);
     }
 
-    private static String getPrimaryInstructionSet(ApplicationInfo info) {
-        if (info.primaryCpuAbi == null) {
-            return getPreferredInstructionSet();
-        }
-
-        return VMRuntime.getInstructionSet(info.primaryCpuAbi);
-    }
-
     public boolean performDexOpt(String packageName, String instructionSet, boolean backgroundDexopt) {
         boolean dexopt = mLazyDexOpt || backgroundDexopt;
         boolean updateUsage = !backgroundDexopt;  // Don't update usage if this is just a backgroundDexopt
@@ -5260,6 +5688,28 @@
                     + " already installed.  Skipping duplicate.");
         }
 
+        // If we're only installing presumed-existing packages, require that the
+        // scanned APK is both already known and at the path previously established
+        // for it.  Previously unknown packages we pick up normally, but if we have an
+        // a priori expectation about this package's install presence, enforce it.
+        if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) {
+            PackageSetting known = mSettings.peekPackageLPr(pkg.packageName);
+            if (known != null) {
+                if (DEBUG_PACKAGE_SCANNING) {
+                    Log.d(TAG, "Examining " + pkg.codePath
+                            + " and requiring known paths " + known.codePathString
+                            + " & " + known.resourcePathString);
+                }
+                if (!pkg.applicationInfo.getCodePath().equals(known.codePathString)
+                        || !pkg.applicationInfo.getResourcePath().equals(known.resourcePathString)) {
+                    throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
+                            "Application package " + pkg.packageName
+                            + " found at " + pkg.applicationInfo.getCodePath()
+                            + " but expected at " + known.codePathString + "; ignoring.");
+                }
+            }
+        }
+
         // Initialize package source and resource directories
         File destCodeFile = new File(pkg.applicationInfo.getCodePath());
         File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
@@ -5630,7 +6080,7 @@
         final String path = scanFile.getPath();
         final String codePath = pkg.applicationInfo.getCodePath();
         final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
-        if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
+        if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) {
             setBundledAppAbisAndRoots(pkg, pkgSetting);
 
             // If we haven't found any native libraries for the app, check if it has
@@ -5845,7 +6295,6 @@
                 throw new PackageManagerException(INSTALL_FAILED_DEXOPT, "scanPackageLI");
             }
         }
-
         if (mFactoryTest && pkg.requestedPermissions.contains(
                 android.Manifest.permission.FACTORY_TEST)) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
@@ -5861,7 +6310,7 @@
                     for (int i=0; i<pkg.libraryNames.size(); i++) {
                         String name = pkg.libraryNames.get(i);
                         boolean allowed = false;
-                        if (isUpdatedSystemApp(pkg)) {
+                        if (pkg.isUpdatedSystemApp()) {
                             // New library entries can only be added through the
                             // system image.  This is important to get rid of a lot
                             // of nasty edge cases: for example if we allowed a non-
@@ -5981,21 +6430,11 @@
             // Add the package's KeySets to the global KeySetManagerService
             KeySetManagerService ksms = mSettings.mKeySetManagerService;
             try {
-                // Old KeySetData no longer valid.
-                ksms.removeAppKeySetDataLPw(pkg.packageName);
                 ksms.addSigningKeySetToPackageLPw(pkg.packageName, pkg.mSigningKeys);
                 if (pkg.mKeySetMapping != null) {
-                    for (Map.Entry<String, ArraySet<PublicKey>> entry :
-                            pkg.mKeySetMapping.entrySet()) {
-                        if (entry.getValue() != null) {
-                            ksms.addDefinedKeySetToPackageLPw(pkg.packageName,
-                                                          entry.getValue(), entry.getKey());
-                        }
-                    }
+                    ksms.addDefinedKeySetsToPackageLPw(pkg.packageName, pkg.mKeySetMapping);
                     if (pkg.mUpgradeKeySets != null) {
-                        for (String upgradeAlias : pkg.mUpgradeKeySets) {
-                            ksms.addUpgradeKeySetToPackageLPw(pkg.packageName, upgradeAlias);
-                        }
+                        ksms.addUpgradeKeySetsToPackageLPw(pkg.packageName, pkg.mUpgradeKeySets);
                     }
                 }
             } catch (NullPointerException e) {
@@ -6467,7 +6906,7 @@
         final ApplicationInfo info = pkg.applicationInfo;
         final String codePath = pkg.codePath;
         final File codeFile = new File(codePath);
-        final boolean bundledApp = isSystemApp(info) && !isUpdatedSystemApp(info);
+        final boolean bundledApp = info.isSystemApp() && !info.isUpdatedSystemApp();
         final boolean asecApp = info.isForwardLocked() || isExternal(info);
 
         info.nativeLibraryRootDir = null;
@@ -6968,12 +7407,19 @@
         PermissionsState permissionsState = ps.getPermissionsState();
         PermissionsState origPermissions = permissionsState;
 
-        boolean changedPermission = false;
+        final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
+
+        int[] upgradeUserIds = PermissionsState.USERS_NONE;
+        int[] changedRuntimePermissionUserIds = PermissionsState.USERS_NONE;
+
+        boolean changedInstallPermission = false;
 
         if (replace) {
-            ps.permissionsFixed = false;
-            origPermissions = new PermissionsState(permissionsState);
-            permissionsState.reset();
+            ps.installPermissionsFixed = false;
+            if (!ps.isSharedUser()) {
+                origPermissions = new PermissionsState(permissionsState);
+                permissionsState.reset();
+            }
         }
 
         permissionsState.setGlobalGids(mGlobalGids);
@@ -7022,17 +7468,33 @@
                                     <= Build.VERSION_CODES.LOLLIPOP_MR1) {
                         // For legacy apps dangerous permissions are install time ones.
                         grant = GRANT_INSTALL;
-                    } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
-                        // For modern system apps dangerous permissions are install time ones.
-                        grant = GRANT_INSTALL;
-                    } else {
+                    } else if (ps.isSystem()) {
+                        final int[] updatedUserIds = ps.getPermissionsUpdatedForUserIds();
                         if (origPermissions.hasInstallPermission(bp.name)) {
-                            // For legacy apps that became modern, install becomes runtime.
+                            // If a system app had an install permission, then the app was
+                            // upgraded and we grant the permissions as runtime to all users.
                             grant = GRANT_UPGRADE;
-                        } else if (replace) {
-                            // For upgraded modern apps keep runtime permissions unchanged.
+                            upgradeUserIds = currentUserIds;
+                        } else if (!Arrays.equals(updatedUserIds, currentUserIds)) {
+                            // If users changed since the last permissions update for a
+                            // system app, we grant the permission as runtime to the new users.
+                            grant = GRANT_UPGRADE;
+                            upgradeUserIds = currentUserIds;
+                            for (int userId : updatedUserIds) {
+                                upgradeUserIds = ArrayUtils.removeInt(upgradeUserIds, userId);
+                            }
+                        } else {
+                            // Otherwise, we grant the permission as runtime if the app
+                            // already had it, i.e. we preserve runtime permissions.
                             grant = GRANT_RUNTIME;
                         }
+                    } else if (origPermissions.hasInstallPermission(bp.name)) {
+                        // For legacy apps that became modern, install becomes runtime.
+                        grant = GRANT_UPGRADE;
+                        upgradeUserIds = currentUserIds;
+                    } else if (replace) {
+                        // For upgraded modern apps keep runtime permissions unchanged.
+                        grant = GRANT_RUNTIME;
                     }
                 } break;
 
@@ -7050,7 +7512,7 @@
             }
 
             if (grant != GRANT_DENIED) {
-                if (!isSystemApp(ps) && ps.permissionsFixed) {
+                if (!isSystemApp(ps) && ps.installPermissionsFixed) {
                     // If this is an existing, non-system package, then
                     // we can't add any new permissions to it.
                     if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {
@@ -7068,7 +7530,7 @@
                         // Grant an install permission.
                         if (permissionsState.grantInstallPermission(bp) !=
                                 PermissionsState.PERMISSION_OPERATION_FAILURE) {
-                            changedPermission = true;
+                            changedInstallPermission = true;
                         }
                     } break;
 
@@ -7076,9 +7538,11 @@
                         // Grant previously granted runtime permissions.
                         for (int userId : UserManagerService.getInstance().getUserIds()) {
                             if (origPermissions.hasRuntimePermission(bp.name, userId)) {
-                                if (permissionsState.grantRuntimePermission(bp, userId) !=
+                                if (permissionsState.grantRuntimePermission(bp, userId) ==
                                         PermissionsState.PERMISSION_OPERATION_FAILURE) {
-                                    changedPermission = true;
+                                    // If we cannot put the permission as it was, we have to write.
+                                    changedRuntimePermissionUserIds = ArrayUtils.appendInt(
+                                            changedRuntimePermissionUserIds, userId);
                                 }
                             }
                         }
@@ -7087,10 +7551,12 @@
                     case GRANT_UPGRADE: {
                         // Grant runtime permissions for a previously held install permission.
                         permissionsState.revokeInstallPermission(bp);
-                        for (int userId : UserManagerService.getInstance().getUserIds()) {
+                        for (int userId : upgradeUserIds) {
                             if (permissionsState.grantRuntimePermission(bp, userId) !=
                                     PermissionsState.PERMISSION_OPERATION_FAILURE) {
-                                changedPermission = true;
+                                // If we granted the permission, we have to write.
+                                changedRuntimePermissionUserIds = ArrayUtils.appendInt(
+                                        changedRuntimePermissionUserIds, userId);
                             }
                         }
                     } break;
@@ -7107,7 +7573,7 @@
             } else {
                 if (permissionsState.revokeInstallPermission(bp) !=
                         PermissionsState.PERMISSION_OPERATION_FAILURE) {
-                    changedPermission = true;
+                    changedInstallPermission = true;
                     Slog.i(TAG, "Un-granting permission " + perm
                             + " from package " + pkg.packageName
                             + " (protectionLevel=" + bp.protectionLevel
@@ -7127,12 +7593,21 @@
             }
         }
 
-        if ((changedPermission || replace) && !ps.permissionsFixed &&
+        if ((changedInstallPermission || replace) && !ps.installPermissionsFixed &&
                 !isSystemApp(ps) || isUpdatedSystemApp(ps)){
             // This is the first that we have heard about this package, so the
             // permissions we have now selected are fixed until explicitly
             // changed.
-            ps.permissionsFixed = true;
+            ps.installPermissionsFixed = true;
+        }
+
+        ps.setPermissionsUpdatedForUserIds(currentUserIds);
+
+        // Persist the runtime permissions state for users with changes.
+        if (RUNTIME_PERMISSIONS_ENABLED) {
+            for (int userId : changedRuntimePermissionUserIds) {
+                mSettings.writeRuntimePermissionsForUserLPr(userId, true);
+            }
         }
     }
 
@@ -7166,7 +7641,7 @@
             if (isSystemApp(pkg)) {
                 // For updated system applications, a system permission
                 // is granted only if it had been defined by the original application.
-                if (isUpdatedSystemApp(pkg)) {
+                if (pkg.isUpdatedSystemApp()) {
                     final PackageSetting sysPs = mSettings
                             .getDisabledSystemPkgLPr(pkg.packageName);
                     if (sysPs.getPermissionsState().hasInstallPermission(perm)) {
@@ -7251,7 +7726,7 @@
         }
 
         public final void addActivity(PackageParser.Activity a, String type) {
-            final boolean systemApp = isSystemApp(a.info.applicationInfo);
+            final boolean systemApp = a.info.applicationInfo.isSystemApp();
             mActivities.put(a.getComponentName(), a);
             if (DEBUG_SHOW_INFO)
                 Log.v(
@@ -7365,6 +7840,9 @@
             if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
                 res.filter = info;
             }
+            if (info != null) {
+                res.filterNeedsVerification = info.needsVerification();
+            }
             res.priority = info.getPriority();
             res.preferredOrder = activity.owner.mPreferredOrder;
             //System.out.println("Result: " + res.activityInfo.className +
@@ -7378,7 +7856,7 @@
             } else {
                 res.icon = info.icon;
             }
-            res.system = isSystemApp(res.activityInfo.applicationInfo);
+            res.system = res.activityInfo.applicationInfo.isSystemApp();
             return res;
         }
 
@@ -7587,14 +8065,12 @@
             }
             res.priority = info.getPriority();
             res.preferredOrder = service.owner.mPreferredOrder;
-            //System.out.println("Result: " + res.activityInfo.className +
-            //                   " = " + res.priority);
             res.match = match;
             res.isDefault = info.hasDefault;
             res.labelRes = info.labelRes;
             res.nonLocalizedLabel = info.nonLocalizedLabel;
             res.icon = info.icon;
-            res.system = isSystemApp(res.serviceInfo.applicationInfo);
+            res.system = res.serviceInfo.applicationInfo.isSystemApp();
             return res;
         }
 
@@ -7817,7 +8293,7 @@
             res.labelRes = info.labelRes;
             res.nonLocalizedLabel = info.nonLocalizedLabel;
             res.icon = info.icon;
-            res.system = isSystemApp(res.providerInfo.applicationInfo);
+            res.system = res.providerInfo.applicationInfo.isSystemApp();
             return res;
         }
 
@@ -8009,8 +8485,8 @@
     public void installPackage(String originPath, IPackageInstallObserver2 observer,
             int installFlags, String installerPackageName, VerificationParams verificationParams,
             String packageAbiOverride) {
-        installPackageAsUser(originPath, observer, installFlags, installerPackageName, verificationParams,
-                packageAbiOverride, UserHandle.getCallingUserId());
+        installPackageAsUser(originPath, observer, installFlags, installerPackageName,
+                verificationParams, packageAbiOverride, UserHandle.getCallingUserId());
     }
 
     @Override
@@ -8057,7 +8533,7 @@
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         msg.obj = new InstallParams(origin, observer, installFlags,
-                installerPackageName, verificationParams, user, packageAbiOverride);
+                installerPackageName, null, verificationParams, user, packageAbiOverride);
         mHandler.sendMessage(msg);
     }
 
@@ -8076,7 +8552,7 @@
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         msg.obj = new InstallParams(origin, observer, params.installFlags,
-                installerPackageName, verifParams, user, params.abiOverride);
+                installerPackageName, params.volumeUuid, verifParams, user, params.abiOverride);
         mHandler.sendMessage(msg);
     }
 
@@ -8465,6 +8941,45 @@
                 android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) == 1;
     }
 
+    @Override
+    public void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains)
+            throws RemoteException {
+        mContext.enforceCallingOrSelfPermission(
+                Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT,
+                "Only intentfilter verification agents can verify applications");
+
+        final Message msg = mHandler.obtainMessage(INTENT_FILTER_VERIFIED);
+        final IntentFilterVerificationResponse response = new IntentFilterVerificationResponse(
+                Binder.getCallingUid(), verificationCode, failedDomains);
+        msg.arg1 = id;
+        msg.obj = response;
+        mHandler.sendMessage(msg);
+    }
+
+    @Override
+    public int getIntentVerificationStatus(String packageName, int userId) {
+        synchronized (mPackages) {
+            return mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
+        }
+    }
+
+    @Override
+    public boolean updateIntentVerificationStatus(String packageName, int status, int userId) {
+        boolean result = false;
+        synchronized (mPackages) {
+            result = mSettings.updateIntentFilterVerificationStatusLPw(packageName, status, userId);
+        }
+        scheduleWritePackageRestrictionsLocked(userId);
+        return result;
+    }
+
+    @Override
+    public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
+        synchronized (mPackages) {
+            return mSettings.getIntentFilterVerificationsLPr(packageName);
+        }
+    }
+
     /**
      * Get the "allow unknown sources" setting.
      *
@@ -8839,19 +9354,21 @@
         final IPackageInstallObserver2 observer;
         int installFlags;
         final String installerPackageName;
+        final String volumeUuid;
         final VerificationParams verificationParams;
         private InstallArgs mArgs;
         private int mRet;
         final String packageAbiOverride;
 
         InstallParams(OriginInfo origin, IPackageInstallObserver2 observer, int installFlags,
-                String installerPackageName, VerificationParams verificationParams, UserHandle user,
-                String packageAbiOverride) {
+                String installerPackageName, String volumeUuid,
+                VerificationParams verificationParams, UserHandle user, String packageAbiOverride) {
             super(user);
             this.origin = origin;
             this.observer = observer;
             this.installFlags = installFlags;
             this.installerPackageName = installerPackageName;
+            this.volumeUuid = volumeUuid;
             this.verificationParams = verificationParams;
             this.packageAbiOverride = packageAbiOverride;
         }
@@ -9205,7 +9722,7 @@
      * @param installFlags package installation flags
      * @return true if should be installed on external storage
      */
-    private static boolean installOnSd(int installFlags) {
+    private static boolean installOnExternalAsec(int installFlags) {
         if ((installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
             return false;
         }
@@ -9226,7 +9743,7 @@
     }
 
     private InstallArgs createInstallArgs(InstallParams params) {
-        if (installOnSd(params.installFlags) || params.isForwardLocked()) {
+        if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
             return new AsecInstallArgs(params);
         } else {
             return new FileInstallArgs(params);
@@ -9240,7 +9757,7 @@
     private InstallArgs createInstallArgsForExisting(int installFlags, String codePath,
             String resourcePath, String nativeLibraryRoot, String[] instructionSets) {
         final boolean isInAsec;
-        if (installOnSd(installFlags)) {
+        if (installOnExternalAsec(installFlags)) {
             /* Apps on SD card are always in ASEC containers. */
             isInAsec = true;
         } else if (installForwardLocked(installFlags)
@@ -9256,7 +9773,7 @@
 
         if (isInAsec) {
             return new AsecInstallArgs(codePath, instructionSets,
-                    installOnSd(installFlags), installForwardLocked(installFlags));
+                    installOnExternalAsec(installFlags), installForwardLocked(installFlags));
         } else {
             return new FileInstallArgs(codePath, resourcePath, nativeLibraryRoot,
                     instructionSets);
@@ -9271,6 +9788,7 @@
         // Always refers to PackageManager flags only
         final int installFlags;
         final String installerPackageName;
+        final String volumeUuid;
         final ManifestDigest manifestDigest;
         final UserHandle user;
         final String abiOverride;
@@ -9281,12 +9799,13 @@
         /* nullable */ String[] instructionSets;
 
         InstallArgs(OriginInfo origin, IPackageInstallObserver2 observer, int installFlags,
-                String installerPackageName, ManifestDigest manifestDigest, UserHandle user,
-                String[] instructionSets, String abiOverride) {
+                String installerPackageName, String volumeUuid, ManifestDigest manifestDigest,
+                UserHandle user, String[] instructionSets, String abiOverride) {
             this.origin = origin;
             this.installFlags = installFlags;
             this.observer = observer;
             this.installerPackageName = installerPackageName;
+            this.volumeUuid = volumeUuid;
             this.manifestDigest = manifestDigest;
             this.user = user;
             this.instructionSets = instructionSets;
@@ -9338,7 +9857,7 @@
             return (installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
         }
 
-        protected boolean isExternal() {
+        protected boolean isExternalAsec() {
             return (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
         }
 
@@ -9385,8 +9904,8 @@
         /** New install */
         FileInstallArgs(InstallParams params) {
             super(params.origin, params.observer, params.installFlags,
-                    params.installerPackageName, params.getManifestDigest(), params.getUser(),
-                    null /* instruction sets */, params.packageAbiOverride);
+                    params.installerPackageName, params.volumeUuid, params.getManifestDigest(),
+                    params.getUser(), null /* instruction sets */, params.packageAbiOverride);
             if (isFwdLocked()) {
                 throw new IllegalArgumentException("Forward locking only supported in ASEC");
             }
@@ -9395,7 +9914,7 @@
         /** Existing install */
         FileInstallArgs(String codePath, String resourcePath, String legacyNativeLibraryPath,
                 String[] instructionSets) {
-            super(OriginInfo.fromNothing(), null, 0, null, null, null, instructionSets, null);
+            super(OriginInfo.fromNothing(), null, 0, null, null, null, null, instructionSets, null);
             this.codeFile = (codePath != null) ? new File(codePath) : null;
             this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
             this.legacyNativeLibraryPath = (legacyNativeLibraryPath != null) ?
@@ -9419,7 +9938,7 @@
             }
 
             try {
-                final File tempDir = mInstallerService.allocateInternalStageDirLegacy();
+                final File tempDir = mInstallerService.allocateStageDirLegacy(volumeUuid);
                 codeFile = tempDir;
                 resourceFile = tempDir;
             } catch (IOException e) {
@@ -9480,8 +9999,9 @@
                 cleanUp();
                 return false;
             } else {
+                final File targetDir = codeFile.getParentFile();
                 final File beforeCodeFile = codeFile;
-                final File afterCodeFile = getNextCodePath(pkg.packageName);
+                final File afterCodeFile = getNextCodePath(targetDir, pkg.packageName);
 
                 Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
                 try {
@@ -9547,9 +10067,10 @@
             }
 
             if (codeFile.isDirectory()) {
-                FileUtils.deleteContents(codeFile);
+                mInstaller.rmPackageDir(codeFile.getAbsolutePath());
+            } else {
+                codeFile.delete();
             }
-            codeFile.delete();
 
             if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
                 resourceFile.delete();
@@ -9630,16 +10151,15 @@
         /** New install */
         AsecInstallArgs(InstallParams params) {
             super(params.origin, params.observer, params.installFlags,
-                    params.installerPackageName, params.getManifestDigest(),
-                    params.getUser(), null /* instruction sets */,
-                    params.packageAbiOverride);
+                    params.installerPackageName, params.volumeUuid, params.getManifestDigest(),
+                    params.getUser(), null /* instruction sets */, params.packageAbiOverride);
         }
 
         /** Existing install */
         AsecInstallArgs(String fullCodePath, String[] instructionSets,
                         boolean isExternal, boolean isForwardLocked) {
             super(OriginInfo.fromNothing(), null, (isExternal ? INSTALL_EXTERNAL : 0)
-                    | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
+                    | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, null,
                     instructionSets, null);
             // Hackily pretend we're still looking at a full code path
             if (!fullCodePath.endsWith(RES_FILE_NAME)) {
@@ -9656,7 +10176,7 @@
 
         AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
             super(OriginInfo.fromNothing(), null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
-                    | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
+                    | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null, null,
                     instructionSets, null);
             this.cid = cid;
             setMountPath(PackageHelper.getSdDir(cid));
@@ -9671,7 +10191,7 @@
                     abiOverride);
 
             final File target;
-            if (isExternal()) {
+            if (isExternalAsec()) {
                 target = new UserEnvironment(UserHandle.USER_OWNER).getExternalStorageDirectory();
             } else {
                 target = Environment.getDataDirectory();
@@ -9700,7 +10220,7 @@
             }
 
             final String newMountPath = imcs.copyPackageToContainer(
-                    origin.file.getAbsolutePath(), cid, getEncryptKey(), isExternal(),
+                    origin.file.getAbsolutePath(), cid, getEncryptKey(), isExternalAsec(),
                     isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */));
 
             if (newMountPath != null) {
@@ -9981,32 +10501,16 @@
         return prefix + idxStr;
     }
 
-    private File getNextCodePath(String packageName) {
+    private File getNextCodePath(File targetDir, String packageName) {
         int suffix = 1;
         File result;
         do {
-            result = new File(mAppInstallDir, packageName + "-" + suffix);
+            result = new File(targetDir, packageName + "-" + suffix);
             suffix++;
         } while (result.exists());
         return result;
     }
 
-    // Utility method used to ignore ADD/REMOVE events
-    // by directory observer.
-    private static boolean ignoreCodePath(String fullPathStr) {
-        String apkName = deriveCodePathName(fullPathStr);
-        int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
-        if (idx != -1 && ((idx+1) < apkName.length())) {
-            // Make sure the package ends with a numeral
-            String version = apkName.substring(idx+1);
-            try {
-                Integer.parseInt(version);
-                return true;
-            } catch (NumberFormatException e) {}
-        }
-        return false;
-    }
-    
     // Utility method that returns the relative package path with respect
     // to the installation directory. Like say for /data/data/com.test-1.apk
     // string com.test-1 is returned.
@@ -10065,9 +10569,9 @@
     /*
      * Install a non-existing package.
      */
-    private void installNewPackageLI(PackageParser.Package pkg,
-            int parseFlags, int scanFlags, UserHandle user,
-            String installerPackageName, PackageInstalledInfo res) {
+    private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags,
+            UserHandle user, String installerPackageName, String volumeUuid,
+            PackageInstalledInfo res) {
         // Remember this for later, in case we need to rollback this install
         String pkgName = pkg.packageName;
 
@@ -10096,7 +10600,7 @@
             PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanFlags,
                     System.currentTimeMillis(), user);
 
-            updateSettingsLI(newPackage, installerPackageName, null, null, res, user);
+            updateSettingsLI(newPackage, installerPackageName, volumeUuid, null, null, res, user);
             // delete the partially installed application. the data directory will have to be
             // restored if it was already existing
             if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
@@ -10128,9 +10632,9 @@
         return false;
     }
 
-    private void replacePackageLI(PackageParser.Package pkg,
-            int parseFlags, int scanFlags, UserHandle user,
-            String installerPackageName, PackageInstalledInfo res) {
+    private void replacePackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags,
+            UserHandle user, String installerPackageName, String volumeUuid,
+            PackageInstalledInfo res) {
         PackageParser.Package oldPackage;
         String pkgName = pkg.packageName;
         int[] allUsers;
@@ -10169,17 +10673,17 @@
         boolean sysPkg = (isSystemApp(oldPackage));
         if (sysPkg) {
             replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags,
-                    user, allUsers, perUserInstalled, installerPackageName, res);
+                    user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res);
         } else {
             replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags,
-                    user, allUsers, perUserInstalled, installerPackageName, res);
+                    user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res);
         }
     }
 
     private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
             PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
-            int[] allUsers, boolean[] perUserInstalled,
-            String installerPackageName, PackageInstalledInfo res) {
+            int[] allUsers, boolean[] perUserInstalled, String installerPackageName,
+            String volumeUuid, PackageInstalledInfo res) {
         String pkgName = deletedPackage.packageName;
         boolean deletedPkg = true;
         boolean updatedSettings = false;
@@ -10218,8 +10722,8 @@
             try {
                 final PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags,
                         scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
-                updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res,
-                        user);
+                updateSettingsLI(newPackage, installerPackageName, volumeUuid, allUsers,
+                        perUserInstalled, res, user);
                 updatedSettings = true;
             } catch (PackageManagerException e) {
                 res.setError("Package couldn't be installed in " + pkg.codePath, e);
@@ -10244,10 +10748,10 @@
                 if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage);
                 File restoreFile = new File(deletedPackage.codePath);
                 // Parse old package
-                boolean oldOnSd = isExternal(deletedPackage);
+                boolean oldExternal = isExternal(deletedPackage);
                 int oldParseFlags  = mDefParseFlags | PackageParser.PARSE_CHATTY |
                         (deletedPackage.isForwardLocked() ? PackageParser.PARSE_FORWARD_LOCK : 0) |
-                        (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
+                        (oldExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
                 int oldScanFlags = SCAN_UPDATE_SIGNATURE | SCAN_UPDATE_TIME;
                 try {
                     scanPackageLI(restoreFile, oldParseFlags, oldScanFlags, origUpdateTime, null);
@@ -10271,8 +10775,8 @@
 
     private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
             PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
-            int[] allUsers, boolean[] perUserInstalled,
-            String installerPackageName, PackageInstalledInfo res) {
+            int[] allUsers, boolean[] perUserInstalled, String installerPackageName,
+            String volumeUuid, PackageInstalledInfo res) {
         if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
                 + ", old=" + deletedPackage);
         boolean disabledSystem = false;
@@ -10349,8 +10853,8 @@
             }
 
             if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
-                updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res,
-                        user);
+                updateSettingsLI(newPackage, installerPackageName, volumeUuid, allUsers,
+                        perUserInstalled, res, user);
                 updatedSettings = true;
             }
 
@@ -10385,8 +10889,8 @@
     }
 
     private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
-            int[] allUsers, boolean[] perUserInstalled,
-            PackageInstalledInfo res, UserHandle user) {
+            String volumeUuid, int[] allUsers, boolean[] perUserInstalled, PackageInstalledInfo res,
+            UserHandle user) {
         String pkgName = newPackage.packageName;
         synchronized (mPackages) {
             //write settings. the installStatus will be incomplete at this stage.
@@ -10444,6 +10948,7 @@
             res.pkg = newPackage;
             mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
             mSettings.setInstallerPackageName(pkgName, installerPackageName);
+            mSettings.setVolumeUuid(pkgName, volumeUuid);
             res.returnCode = PackageManager.INSTALL_SUCCEEDED;
             //to update install status
             mSettings.writeLPr();
@@ -10452,10 +10957,12 @@
 
     private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
         final int installFlags = args.installFlags;
-        String installerPackageName = args.installerPackageName;
-        File tmpPackageFile = new File(args.getCodePath());
-        boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
-        boolean onSd = ((installFlags & PackageManager.INSTALL_EXTERNAL) != 0);
+        final String installerPackageName = args.installerPackageName;
+        final String volumeUuid = args.volumeUuid;
+        final File tmpPackageFile = new File(args.getCodePath());
+        final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
+        final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)
+                || (args.volumeUuid != null));
         boolean replace = false;
         final int scanFlags = SCAN_NEW_INSTALL | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE;
         // Result object to be returned
@@ -10465,7 +10972,7 @@
         // Retrieve PackageSettings and parse package
         final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
                 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
-                | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
+                | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
         PackageParser pp = new PackageParser();
         pp.setSeparateProcesses(mSeparateProcesses);
         pp.setDisplayMetrics(mMetrics);
@@ -10617,24 +11124,36 @@
 
         }
 
-        if (systemApp && onSd) {
+        if (systemApp && onExternal) {
             // Disable updates to system apps on sdcard
             res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
                     "Cannot install updates to system apps on sdcard");
             return;
         }
 
+        // Run dexopt before old package gets removed, to minimize time when app is not available
+        int result = mPackageDexOptimizer
+                .performDexOpt(pkg, null /* instruction sets */, true /* forceDex */,
+                        false /* defer */, false /* inclDependencies */);
+        if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
+            res.setError(INSTALL_FAILED_DEXOPT, "Dexopt failed for " + pkg.codePath);
+            return;
+        }
+
         if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
             res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename");
             return;
         }
 
+        startIntentFilterVerifications(args.user.getIdentifier(), pkg);
+
         if (replace) {
-            replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
-                    installerPackageName, res);
+            // Call replacePackageLI with SCAN_NO_DEX, since we already made dexopt
+            replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING | SCAN_NO_DEX, args.user,
+                    installerPackageName, volumeUuid, res);
         } else {
             installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
-                    args.user, installerPackageName, res);
+                    args.user, installerPackageName, volumeUuid, res);
         }
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(pkgName);
@@ -10644,6 +11163,86 @@
         }
     }
 
+    private void startIntentFilterVerifications(int userId, PackageParser.Package pkg) {
+        if (mIntentFilterVerifierComponent == null) {
+            Slog.d(TAG, "No IntentFilter verification will not be done as "
+                    + "there is no IntentFilterVerifier available!");
+            return;
+        }
+
+        final int verifierUid = getPackageUid(
+                mIntentFilterVerifierComponent.getPackageName(),
+                (userId == UserHandle.USER_ALL) ? UserHandle.USER_OWNER : userId);
+
+        mHandler.removeMessages(START_INTENT_FILTER_VERIFICATIONS);
+        final Message msg = mHandler.obtainMessage(START_INTENT_FILTER_VERIFICATIONS);
+        msg.obj = pkg;
+        msg.arg1 = userId;
+        msg.arg2 = verifierUid;
+
+        mHandler.sendMessage(msg);
+    }
+
+    private void verifyIntentFiltersIfNeeded(int userId, int verifierUid,
+                                             PackageParser.Package pkg) {
+        int size = pkg.activities.size();
+        if (size == 0) {
+            Slog.d(TAG, "No activity, so no need to verify any IntentFilter!");
+            return;
+        }
+
+        Slog.d(TAG, "Checking for userId:" + userId + " if any IntentFilter from the " + size
+                + " Activities needs verification ...");
+
+        final int verificationId = mIntentFilterVerificationToken++;
+        int count = 0;
+        synchronized (mPackages) {
+            for (PackageParser.Activity a : pkg.activities) {
+                for (ActivityIntentInfo filter : a.intents) {
+                    boolean needFilterVerification = filter.needsVerification() &&
+                            !filter.isVerified();
+                    if (needFilterVerification && needNetworkVerificationLPr(filter)) {
+                        Slog.d(TAG, "Verification needed for IntentFilter:" + filter.toString());
+                        mIntentFilterVerifier.addOneIntentFilterVerification(
+                                verifierUid, userId, verificationId, filter, pkg.packageName);
+                        count++;
+                    } else {
+                        Slog.d(TAG, "No verification needed for IntentFilter:" + filter.toString());
+                    }
+                }
+            }
+        }
+
+        if (count > 0) {
+            mIntentFilterVerifier.startVerifications(userId);
+            Slog.d(TAG, "Started " + count + " IntentFilter verification"
+                    + (count > 1 ? "s" : "") +  " for userId:" + userId + "!");
+        } else {
+            Slog.d(TAG, "No need to start any IntentFilter verification!");
+        }
+    }
+
+    private boolean needNetworkVerificationLPr(ActivityIntentInfo filter) {
+        final ComponentName cn  = filter.activity.getComponentName();
+        final String packageName = cn.getPackageName();
+
+        IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr(
+                packageName);
+        if (ivi == null) {
+            return true;
+        }
+        int status = ivi.getStatus();
+        switch (status) {
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED:
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK:
+                return true;
+
+            default:
+                // Nothing to do
+                return false;
+        }
+    }
+
     private static boolean isMultiArch(PackageSetting ps) {
         return (ps.pkgFlags & ApplicationInfo.FLAG_MULTIARCH) != 0;
     }
@@ -10672,10 +11271,6 @@
         return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
     }
 
-    private static boolean isSystemApp(ApplicationInfo info) {
-        return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
-    }
-
     private static boolean isSystemApp(PackageSetting ps) {
         return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
@@ -10684,17 +11279,11 @@
         return (ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
     }
 
-    private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
-        return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
-    }
-
-    private static boolean isUpdatedSystemApp(ApplicationInfo info) {
-        return (info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
-    }
-
     private int packageFlagsToInstallFlags(PackageSetting ps) {
         int installFlags = 0;
-        if (isExternal(ps)) {
+        if (isExternal(ps) && TextUtils.isEmpty(ps.volumeUuid)) {
+            // This existing package was an external ASEC install when we have
+            // the external flag without a UUID
             installFlags |= PackageManager.INSTALL_EXTERNAL;
         }
         if (ps.isForwardLocked()) {
@@ -10971,19 +11560,23 @@
                         for (int userId : UserManagerService.getInstance().getUserIds()) {
                             final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs,
                                     userId);
-                            if (userIdToKill == userId) {
+                            if (userIdToKill == UserHandle.USER_ALL
+                                    || userIdToKill >= UserHandle.USER_OWNER) {
                                 // If gids changed for this user, kill all affected packages.
-                                killSettingPackagesForUser(deletedPs, userIdToKill,
-                                        KILL_APP_REASON_GIDS_CHANGED);
-                            } else if (userIdToKill == UserHandle.USER_ALL) {
-                                // If gids changed for all users, kill them all - done.
-                                killSettingPackagesForUser(deletedPs, userIdToKill,
-                                        KILL_APP_REASON_GIDS_CHANGED);
-                                break;
+                                mHandler.post(new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        // This has to happen with no lock held.
+                                        killSettingPackagesForUser(deletedPs, userIdToKill,
+                                                KILL_APP_REASON_GIDS_CHANGED);
+                                    }
+                                });
+                            break;
                             }
                         }
                     }
                     clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
+                    clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL);
                 }
                 // make sure to preserve per-user disabled state if this removal was just
                 // a downgrade of a system app to the factory package
@@ -11212,8 +11805,8 @@
                         true,  //notLaunched
                         false, //hidden
                         null, null, null,
-                        false // blockUninstall
-                        );
+                        false, // blockUninstall
+                        INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
                 if (!isSystemApp(ps)) {
                     if (ps.isAnyInstalled(sUserManager.getUserIds())) {
                         // Other user still have this package installed, so all
@@ -11836,6 +12429,19 @@
         return changed;
     }
 
+    /** This method takes a specific user id as well as UserHandle.USER_ALL. */
+    void clearIntentFilterVerificationsLPw(String packageName, int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            mSettings.removeIntentFilterVerificationLPw(packageName, sUserManager.getUserIds());
+            for (int oneUserId : sUserManager.getUserIds()) {
+                scheduleWritePackageRestrictionsLocked(oneUserId);
+            }
+        } else {
+            mSettings.removeIntentFilterVerificationLPw(packageName, userId);
+            scheduleWritePackageRestrictionsLocked(userId);
+        }
+    }
+
     @Override
     public void resetPreferredActivities(int userId) {
         /* TODO: Actually use userId. Why is it being passed in? */
@@ -11945,6 +12551,83 @@
         }
     }
 
+    /**
+     * Non-Binder method, support for the backup/restore mechanism: write the
+     * full set of preferred activities in its canonical XML format.  Returns true
+     * on success; false otherwise.
+     */
+    @Override
+    public byte[] getPreferredActivityBackup(int userId) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Only the system may call getPreferredActivityBackup()");
+        }
+
+        ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
+        try {
+            final XmlSerializer serializer = new FastXmlSerializer();
+            serializer.setOutput(dataStream, "utf-8");
+            serializer.startDocument(null, true);
+            serializer.startTag(null, TAG_PREFERRED_BACKUP);
+
+            synchronized (mPackages) {
+                mSettings.writePreferredActivitiesLPr(serializer, userId, true);
+            }
+
+            serializer.endTag(null, TAG_PREFERRED_BACKUP);
+            serializer.endDocument();
+            serializer.flush();
+        } catch (Exception e) {
+            if (DEBUG_BACKUP) {
+                Slog.e(TAG, "Unable to write preferred activities for backup", e);
+            }
+            return null;
+        }
+
+        return dataStream.toByteArray();
+    }
+
+    @Override
+    public void restorePreferredActivities(byte[] backup, int userId) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Only the system may call restorePreferredActivities()");
+        }
+
+        try {
+            final XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(new ByteArrayInputStream(backup), null);
+
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG
+                    && type != XmlPullParser.END_DOCUMENT) {
+            }
+            if (type != XmlPullParser.START_TAG) {
+                // oops didn't find a start tag?!
+                if (DEBUG_BACKUP) {
+                    Slog.e(TAG, "Didn't find start tag during restore");
+                }
+                return;
+            }
+
+            // this is supposed to be TAG_PREFERRED_BACKUP
+            if (!TAG_PREFERRED_BACKUP.equals(parser.getName())) {
+                if (DEBUG_BACKUP) {
+                    Slog.e(TAG, "Found unexpected tag " + parser.getName());
+                }
+                return;
+            }
+
+            // skip interfering stuff, then we're aligned with the backing implementation
+            while ((type = parser.next()) == XmlPullParser.TEXT) { }
+            synchronized (mPackages) {
+                mSettings.readPreferredActivitiesLPw(parser, userId);
+            }
+        } catch (Exception e) {
+            if (DEBUG_BACKUP) {
+                Slog.e(TAG, "Exception restoring preferred activities: " + e.getMessage());
+            }
+        }
+    }
+
     @Override
     public void addCrossProfileIntentFilter(IntentFilter intentFilter, String ownerPackage,
             int sourceUserId, int targetUserId, int flags) {
@@ -12306,6 +12989,12 @@
             }
             mPostSystemReadyMessages = null;
         }
+
+        // Watch for external volumes that come and go over time
+        final StorageManager storage = mContext.getSystemService(StorageManager.class);
+        storage.registerListener(mStorageListener);
+
+        mInstallerService.systemReady();
     }
 
     @Override
@@ -12346,6 +13035,8 @@
         public static final int DUMP_KEYSETS = 1 << 11;
         public static final int DUMP_VERSION = 1 << 12;
         public static final int DUMP_INSTALLS = 1 << 13;
+        public static final int DUMP_INTENT_FILTER_VERIFIERS = 1 << 14;
+        public static final int DUMP_DOMAIN_PREFERRED = 1 << 15;
 
         public static final int OPTION_SHOW_FILTERS = 1 << 0;
 
@@ -12451,6 +13142,8 @@
                 pw.println("    write: write current settings now");
                 pw.println("    <package.name>: info about given package");
                 pw.println("    installs: details about install sessions");
+                pw.println("    d[omain-preferred-apps]: print domains preferred apps");
+                pw.println("    i[ntent-filter-verifiers]|ifv: print intent filter verifier info");
                 return;
             } else if ("--checkin".equals(opt)) {
                 checkin = true;
@@ -12487,6 +13180,8 @@
                     fullPreferred = true;
                     opti++;
                 }
+            } else if ("d".equals(cmd) || "domain-preferred-apps".equals(cmd)) {
+                dumpState.setDump(DumpState.DUMP_DOMAIN_PREFERRED);
             } else if ("p".equals(cmd) || "packages".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_PACKAGES);
             } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
@@ -12497,6 +13192,9 @@
                 dumpState.setDump(DumpState.DUMP_MESSAGES);
             } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_VERIFIERS);
+            } else if ("i".equals(cmd) || "ifv".equals(cmd)
+                    || "intent-filter-verifiers".equals(cmd)) {
+                dumpState.setDump(DumpState.DUMP_INTENT_FILTER_VERIFIERS);
             } else if ("version".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_VERSION);
             } else if ("k".equals(cmd) || "keysets".equals(cmd)) {
@@ -12552,6 +13250,29 @@
                 }
             }
 
+            if (dumpState.isDumping(DumpState.DUMP_INTENT_FILTER_VERIFIERS) &&
+                    packageName == null) {
+                if (mIntentFilterVerifierComponent != null) {
+                    String verifierPackageName = mIntentFilterVerifierComponent.getPackageName();
+                    if (!checkin) {
+                        if (dumpState.onTitlePrinted())
+                            pw.println();
+                        pw.println("Intent Filter Verifier:");
+                        pw.print("  Using: ");
+                        pw.print(verifierPackageName);
+                        pw.print(" (uid=");
+                        pw.print(getPackageUid(verifierPackageName, 0));
+                        pw.println(")");
+                    } else if (verifierPackageName != null) {
+                        pw.print("ifv,"); pw.print(verifierPackageName);
+                        pw.print(","); pw.println(getPackageUid(verifierPackageName, 0));
+                    }
+                } else {
+                    pw.println();
+                    pw.println("No Intent Filter Verifier available!");
+                }
+            }
+
             if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
                 boolean printedHeader = false;
                 final Iterator<String> it = mSharedLibraries.keySet().iterator();
@@ -12671,6 +13392,65 @@
                 }
             }
 
+            if (!checkin && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) {
+                pw.println();
+                int count = mSettings.mPackages.size();
+                if (count == 0) {
+                    pw.println("No domain preferred apps!");
+                    pw.println();
+                } else {
+                    final String prefix = "  ";
+                    Collection<PackageSetting> allPackageSettings = mSettings.mPackages.values();
+                    if (allPackageSettings.size() == 0) {
+                        pw.println("No domain preferred apps!");
+                        pw.println();
+                    } else {
+                        pw.println("Domain preferred apps status:");
+                        pw.println();
+                        count = 0;
+                        for (PackageSetting ps : allPackageSettings) {
+                            IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo();
+                            if (ivi == null || ivi.getPackageName() == null) continue;
+                            pw.println(prefix + "Package Name: " + ivi.getPackageName());
+                            pw.println(prefix + "Domains: " + ivi.getDomainsString());
+                            pw.println(prefix + "Status: " + ivi.getStatusString());
+                            pw.println();
+                            count++;
+                        }
+                        if (count == 0) {
+                            pw.println(prefix + "No domain preferred app status!");
+                            pw.println();
+                        }
+                        for (int userId : sUserManager.getUserIds()) {
+                            pw.println("Domain preferred apps for User " + userId + ":");
+                            pw.println();
+                            count = 0;
+                            for (PackageSetting ps : allPackageSettings) {
+                                IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo();
+                                if (ivi == null || ivi.getPackageName() == null) {
+                                    continue;
+                                }
+                                final int status = ps.getDomainVerificationStatusForUser(userId);
+                                if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
+                                    continue;
+                                }
+                                pw.println(prefix + "Package Name: " + ivi.getPackageName());
+                                pw.println(prefix + "Domains: " + ivi.getDomainsString());
+                                String statusStr = IntentFilterVerificationInfo.
+                                        getStatusStringFromValue(status);
+                                pw.println(prefix + "Status: " + statusStr);
+                                pw.println();
+                                count++;
+                            }
+                            if (count == 0) {
+                                pw.println(prefix + "No domain preferred apps!");
+                                pw.println();
+                            }
+                        }
+                    }
+                }
+            }
+
             if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
                 mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
                 if (packageName == null) {
@@ -12953,13 +13733,32 @@
     }
 
     private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
+            ArrayList<ApplicationInfo> infos, IIntentReceiver finishedReceiver) {
+        final int size = infos.size();
+        final String[] packageNames = new String[size];
+        final int[] packageUids = new int[size];
+        for (int i = 0; i < size; i++) {
+            final ApplicationInfo info = infos.get(i);
+            packageNames[i] = info.packageName;
+            packageUids[i] = info.uid;
+        }
+        sendResourcesChangedBroadcast(mediaStatus, replacing, packageNames, packageUids,
+                finishedReceiver);
+    }
+
+    private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
             ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
-        int size = pkgList.size();
+        sendResourcesChangedBroadcast(mediaStatus, replacing,
+                pkgList.toArray(new String[pkgList.size()]), uidArr, finishedReceiver);
+    }
+
+    private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
+            String[] pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
+        int size = pkgList.length;
         if (size > 0) {
             // Send broadcasts here
             Bundle extras = new Bundle();
-            extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
-                    .toArray(new String[size]));
+            extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
             if (uidArr != null) {
                 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
             }
@@ -13002,8 +13801,8 @@
                 }
                 // Parse package
                 int parseFlags = mDefParseFlags;
-                if (args.isExternal()) {
-                    parseFlags |= PackageParser.PARSE_ON_SDCARD;
+                if (args.isExternalAsec()) {
+                    parseFlags |= PackageParser.PARSE_EXTERNAL_STORAGE;
                 }
                 if (args.isFwdLocked()) {
                     parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
@@ -13150,73 +13949,130 @@
         }
     }
 
-    /** Binder call */
+    private void loadPrivatePackages(VolumeInfo vol) {
+        final ArrayList<ApplicationInfo> loaded = new ArrayList<>();
+        final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE;
+        synchronized (mPackages) {
+            final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(vol.fsUuid);
+            for (PackageSetting ps : packages) {
+                synchronized (mInstallLock) {
+                    final PackageParser.Package pkg;
+                    try {
+                        pkg = scanPackageLI(ps.codePath, parseFlags, 0, 0, null);
+                        loaded.add(pkg.applicationInfo);
+                    } catch (PackageManagerException e) {
+                        Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage());
+                    }
+                }
+            }
+
+            // TODO: regrant any permissions that changed based since original install
+
+            mSettings.writeLPr();
+        }
+
+        Slog.d(TAG, "Loaded packages " + loaded);
+        sendResourcesChangedBroadcast(true, false, loaded, null);
+    }
+
+    private void unloadPrivatePackages(VolumeInfo vol) {
+        final ArrayList<ApplicationInfo> unloaded = new ArrayList<>();
+        synchronized (mPackages) {
+            final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(vol.fsUuid);
+            for (PackageSetting ps : packages) {
+                if (ps.pkg == null) continue;
+                synchronized (mInstallLock) {
+                    final ApplicationInfo info = ps.pkg.applicationInfo;
+                    final PackageRemovedInfo outInfo = new PackageRemovedInfo();
+                    if (deletePackageLI(ps.name, null, false, null, null,
+                            PackageManager.DELETE_KEEP_DATA, outInfo, false)) {
+                        unloaded.add(info);
+                    } else {
+                        Slog.w(TAG, "Failed to unload " + ps.codePath);
+                    }
+                }
+            }
+
+            mSettings.writeLPr();
+        }
+
+        Slog.d(TAG, "Unloaded packages " + unloaded);
+        sendResourcesChangedBroadcast(false, false, unloaded, null);
+    }
+
     @Override
     public void movePackage(final String packageName, final IPackageMoveObserver observer,
             final int flags) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
-        UserHandle user = new UserHandle(UserHandle.getCallingUserId());
-        int returnCode = PackageManager.MOVE_SUCCEEDED;
-        int currInstallFlags = 0;
-        int newInstallFlags = 0;
+
+        final int installFlags;
+        if ((flags & MOVE_INTERNAL) != 0) {
+            installFlags = INSTALL_INTERNAL;
+        } else if ((flags & MOVE_EXTERNAL_MEDIA) != 0) {
+            installFlags = INSTALL_EXTERNAL;
+        } else {
+            throw new IllegalArgumentException("Unsupported move flags " + flags);
+        }
+
+        try {
+            movePackageInternal(packageName, null, installFlags, false, observer);
+        } catch (PackageManagerException e) {
+            Slog.d(TAG, "Failed to move " + packageName, e);
+            try {
+                observer.packageMoved(packageName, e.error);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    @Override
+    public void movePackageAndData(final String packageName, final String volumeUuid,
+            final IPackageMoveObserver observer) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
+        try {
+            movePackageInternal(packageName, volumeUuid, INSTALL_INTERNAL, true, observer);
+        } catch (PackageManagerException e) {
+            Slog.d(TAG, "Failed to move " + packageName, e);
+            try {
+                observer.packageMoved(packageName, e.error);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    private void movePackageInternal(final String packageName, String volumeUuid, int installFlags,
+            boolean andData, final IPackageMoveObserver observer) throws PackageManagerException {
+        final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
 
         File codeFile = null;
         String installerPackageName = null;
         String packageAbiOverride = null;
 
+        // TOOD: move app private data before installing
+
         // reader
         synchronized (mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
             final PackageSetting ps = mSettings.mPackages.get(packageName);
             if (pkg == null || ps == null) {
-                returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
-            } else {
-                // Disable moving fwd locked apps and system packages
-                if (pkg.applicationInfo != null && isSystemApp(pkg)) {
-                    Slog.w(TAG, "Cannot move system application");
-                    returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
-                } else if (pkg.mOperationPending) {
-                    Slog.w(TAG, "Attempt to move package which has pending operations");
-                    returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
-                } else {
-                    // Find install location first
-                    if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
-                            && (flags & PackageManager.MOVE_INTERNAL) != 0) {
-                        Slog.w(TAG, "Ambigous flags specified for move location.");
-                        returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
-                    } else {
-                        newInstallFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
-                                ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
-                        currInstallFlags = isExternal(pkg)
-                                ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
-
-                        if (newInstallFlags == currInstallFlags) {
-                            Slog.w(TAG, "No move required. Trying to move to same location");
-                            returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
-                        } else {
-                            if (pkg.isForwardLocked()) {
-                                currInstallFlags |= PackageManager.INSTALL_FORWARD_LOCK;
-                                newInstallFlags |= PackageManager.INSTALL_FORWARD_LOCK;
-                            }
-                        }
-                    }
-                    if (returnCode == PackageManager.MOVE_SUCCEEDED) {
-                        pkg.mOperationPending = true;
-                    }
-                }
-
-                codeFile = new File(pkg.codePath);
-                installerPackageName = ps.installerPackageName;
-                packageAbiOverride = ps.cpuAbiOverrideString;
+                throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
             }
-        }
 
-        if (returnCode != PackageManager.MOVE_SUCCEEDED) {
-            try {
-                observer.packageMoved(packageName, returnCode);
-            } catch (RemoteException ignored) {
+            if (pkg.applicationInfo.isSystemApp()) {
+                throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE,
+                        "Cannot move system application");
+            } else if (pkg.mOperationPending) {
+                throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING,
+                        "Attempt to move package which has pending operations");
             }
-            return;
+
+            // TODO: yell if already in desired location
+
+            pkg.mOperationPending = true;
+
+            codeFile = new File(pkg.codePath);
+            installerPackageName = ps.installerPackageName;
+            packageAbiOverride = ps.cpuAbiOverrideString;
         }
 
         final IPackageInstallObserver2 installObserver = new IPackageInstallObserver2.Stub() {
@@ -13258,12 +14114,12 @@
 
         // Treat a move like reinstalling an existing app, which ensures that we
         // process everythign uniformly, like unpacking native libraries.
-        newInstallFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
+        installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
-        msg.obj = new InstallParams(origin, installObserver, newInstallFlags,
-                installerPackageName, null, user, packageAbiOverride);
+        msg.obj = new InstallParams(origin, installObserver, installFlags,
+                installerPackageName, volumeUuid, null, user, packageAbiOverride);
         mHandler.sendMessage(msg);
     }
 
@@ -13359,6 +14215,11 @@
         }
     }
 
+    void newUserCreatedLILPw(int userHandle) {
+        // Adding a user requires updating runtime permissions for system apps.
+        updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL);
+    }
+
     @Override
     public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
         mContext.enforceCallingOrSelfPermission(
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 889164c..e7c0ef7 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -70,4 +70,12 @@
     public boolean isForwardLocked() {
         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
     }
+
+    public boolean isSystem() {
+        return (pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
+    }
+
+    public boolean isSharedUser() {
+        return sharedUser != null;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 9e8b3df..f294b32 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -20,7 +20,10 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 
+import android.content.pm.IntentFilterVerificationInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageUserState;
+import android.os.storage.VolumeInfo;
 import android.util.ArraySet;
 import android.util.SparseArray;
 
@@ -92,7 +95,7 @@
 
     PackageSignatures signatures = new PackageSignatures();
 
-    boolean permissionsFixed;
+    boolean installPermissionsFixed;
 
     PackageKeySetData keySetData = new PackageKeySetData();
 
@@ -106,8 +109,13 @@
 
     PackageSettingBase origPackage;
 
-    /* package name of the app that installed this package */
+    /** Package name of the app that installed this package */
     String installerPackageName;
+    /** UUID of {@link VolumeInfo} hosting this app */
+    String volumeUuid;
+
+    IntentFilterVerificationInfo verificationInfo;
+
     PackageSettingBase(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString,
@@ -145,7 +153,7 @@
 
         signatures = new PackageSignatures(base.signatures);
 
-        permissionsFixed = base.permissionsFixed;
+        installPermissionsFixed = base.installPermissionsFixed;
         userState.clear();
         for (int i=0; i<base.userState.size(); i++) {
             userState.put(base.userState.keyAt(i),
@@ -156,6 +164,7 @@
         origPackage = base.origPackage;
 
         installerPackageName = base.installerPackageName;
+        volumeUuid = base.volumeUuid;
 
         keySetData = new PackageKeySetData(base.keySetData);
     }
@@ -178,10 +187,18 @@
         installerPackageName = packageName;
     }
 
-    String getInstallerPackageName() {
+    public String getInstallerPackageName() {
         return installerPackageName;
     }
 
+    public void setVolumeUuid(String volumeUuid) {
+        this.volumeUuid = volumeUuid;
+    }
+
+    public String getVolumeUuid() {
+        return volumeUuid;
+    }
+
     public void setInstallStatus(int newStatus) {
         installStatus = newStatus;
     }
@@ -198,7 +215,8 @@
      * Make a shallow copy of this package settings.
      */
     public void copyFrom(PackageSettingBase base) {
-        getPermissionsState().copyFrom(base.getPermissionsState());
+        setPermissionsUpdatedForUserIds(base.getPermissionsUpdatedForUserIds());
+        mPermissionsState.copyFrom(base.mPermissionsState);
         primaryCpuAbiString = base.primaryCpuAbiString;
         secondaryCpuAbiString = base.secondaryCpuAbiString;
         cpuAbiOverrideString = base.cpuAbiOverrideString;
@@ -206,13 +224,14 @@
         firstInstallTime = base.firstInstallTime;
         lastUpdateTime = base.lastUpdateTime;
         signatures = base.signatures;
-        permissionsFixed = base.permissionsFixed;
+        installPermissionsFixed = base.installPermissionsFixed;
         userState.clear();
         for (int i=0; i<base.userState.size(); i++) {
             userState.put(base.userState.keyAt(i), base.userState.valueAt(i));
         }
         installStatus = base.installStatus;
         keySetData = base.keySetData;
+        verificationInfo = base.verificationInfo;
     }
 
     private PackageUserState modifyUserState(int userId) {
@@ -316,7 +335,7 @@
     void setUserState(int userId, int enabled, boolean installed, boolean stopped,
             boolean notLaunched, boolean hidden,
             String lastDisableAppCaller, ArraySet<String> enabledComponents,
-            ArraySet<String> disabledComponents, boolean blockUninstall) {
+            ArraySet<String> disabledComponents, boolean blockUninstall, int domainVerifState) {
         PackageUserState state = modifyUserState(userId);
         state.enabled = enabled;
         state.installed = installed;
@@ -327,6 +346,7 @@
         state.enabledComponents = enabledComponents;
         state.disabledComponents = disabledComponents;
         state.blockUninstall = blockUninstall;
+        state.domainVerificationStatus = domainVerifState;
     }
 
     ArraySet<String> getEnabledComponents(int userId) {
@@ -414,4 +434,25 @@
     void removeUser(int userId) {
         userState.delete(userId);
     }
+
+    public IntentFilterVerificationInfo getIntentFilterVerificationInfo() {
+        return verificationInfo;
+    }
+
+    public void setIntentFilterVerificationInfo(IntentFilterVerificationInfo info) {
+        verificationInfo = info;
+    }
+
+    public int getDomainVerificationStatusForUser(int userId) {
+        return readUserState(userId).domainVerificationStatus;
+    }
+
+    public void setDomainVerificationStatusForUser(int status, int userId) {
+        modifyUserState(userId).domainVerificationStatus = status;
+    }
+
+    public void clearDomainVerificationStatusForUser(int userId) {
+        modifyUserState(userId).domainVerificationStatus =
+                PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PermissionsState.java b/services/core/java/com/android/server/pm/PermissionsState.java
index 3e0e342..705abf8 100644
--- a/services/core/java/com/android/server/pm/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/PermissionsState.java
@@ -55,9 +55,9 @@
     /** The permission operation failed. */
     public static final int PERMISSION_OPERATION_FAILURE = 3;
 
-    private static final int[] USERS_ALL = {UserHandle.USER_ALL};
+    public static final int[] USERS_ALL = {UserHandle.USER_ALL};
 
-    private static final int[] USERS_NONE = {};
+    public static final int[] USERS_NONE = {};
 
     private static final int[] NO_GIDS = {};
 
@@ -149,6 +149,9 @@
      *     #PERMISSION_OPERATION_FAILURE}.
      */
     public int grantRuntimePermission(BasePermission permission, int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            return PERMISSION_OPERATION_FAILURE;
+        }
         return grantPermission(permission, userId);
     }
 
@@ -162,6 +165,9 @@
      *     #PERMISSION_OPERATION_FAILURE}.
      */
     public int revokeRuntimePermission(BasePermission permission, int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            return PERMISSION_OPERATION_FAILURE;
+        }
         return revokePermission(permission, userId);
     }
 
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index d350c09..0c7f79d 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -17,13 +17,15 @@
 package com.android.server.pm;
 
 import android.content.pm.ApplicationInfo;
-import android.util.ArraySet;
+
+import java.util.Arrays;
 
 abstract class SettingBase {
     int pkgFlags;
     int pkgPrivateFlags;
 
-    private final PermissionsState mPermissionsState;
+    protected final PermissionsState mPermissionsState;
+    private int[] mPermissionsUpdatedForUserIds = PermissionsState.USERS_NONE;
 
     SettingBase(int pkgFlags, int pkgPrivateFlags) {
         setFlags(pkgFlags);
@@ -35,12 +37,29 @@
         pkgFlags = base.pkgFlags;
         pkgPrivateFlags = base.pkgPrivateFlags;
         mPermissionsState = new PermissionsState(base.mPermissionsState);
+        setPermissionsUpdatedForUserIds(base.mPermissionsUpdatedForUserIds);
     }
 
     public PermissionsState getPermissionsState() {
         return mPermissionsState;
     }
 
+    public int[] getPermissionsUpdatedForUserIds() {
+        return mPermissionsUpdatedForUserIds;
+    }
+
+    public void setPermissionsUpdatedForUserIds(int[] userIds) {
+        if (Arrays.equals(mPermissionsUpdatedForUserIds, userIds)) {
+            return;
+        }
+
+        if (userIds == PermissionsState.USERS_NONE || userIds == PermissionsState.USERS_ALL) {
+            mPermissionsUpdatedForUserIds = userIds;
+        } else {
+            mPermissionsUpdatedForUserIds = Arrays.copyOf(userIds, userIds.length);
+        }
+    }
+
     void setFlags(int pkgFlags) {
         this.pkgFlags = pkgFlags
                 & (ApplicationInfo.FLAG_SYSTEM
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 82aa74a..6b7c35c 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -22,12 +22,13 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.PACKAGE_INFO_GID;
 
-import android.content.Context;
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
+import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.os.Binder;
@@ -41,17 +42,21 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.VolumeInfo;
 import android.util.AtomicFile;
+import android.text.TextUtils;
 import android.util.LogPrinter;
-
 import android.util.SparseBooleanArray;
 import android.util.SparseLongArray;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
+import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
+import com.android.server.backup.PreferredActivityBackupHelper;
 import com.android.server.pm.PackageManagerService.DumpState;
 
 import java.io.FileNotFoundException;
@@ -89,6 +94,7 @@
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
@@ -161,6 +167,7 @@
             "persistent-preferred-activities";
     static final String TAG_CROSS_PROFILE_INTENT_FILTERS =
             "crossProfile-intent-filters";
+    public static final String TAG_DOMAIN_VERIFICATION = "domain-verification";
 
     private static final String ATTR_NAME = "name";
     private static final String ATTR_USER = "user";
@@ -175,9 +182,9 @@
     private static final String ATTR_HIDDEN = "hidden";
     private static final String ATTR_INSTALLED = "inst";
     private static final String ATTR_BLOCK_UNINSTALL = "blockUninstall";
+    private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
 
     private final Object mLock;
-    private final Context mContext;
 
     private final RuntimePermissionPersistence mRuntimePermissionsPersistence;
 
@@ -243,6 +250,8 @@
     // For reading/writing settings file.
     private final ArrayList<Signature> mPastSignatures =
             new ArrayList<Signature>();
+    private final ArrayMap<Long, Integer> mKeySetRefs =
+            new ArrayMap<Long, Integer>();
 
     // Mapping from permission names to info about them.
     final ArrayMap<String, BasePermission> mPermissions =
@@ -277,12 +286,11 @@
 
     public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
 
-    Settings(Context context, Object lock) {
-        this(context, Environment.getDataDirectory(), lock);
+    Settings(Object lock) {
+        this(Environment.getDataDirectory(), lock);
     }
 
-    Settings(Context context, File dataDir, Object lock) {
-        mContext = context;
+    Settings(File dataDir, Object lock) {
         mLock = lock;
 
         mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
@@ -327,14 +335,20 @@
         }
     }
 
-    void setInstallerPackageName(String pkgName,
-            String installerPkgName) {
+    void setInstallerPackageName(String pkgName, String installerPkgName) {
         PackageSetting p = mPackages.get(pkgName);
-        if(p != null) {
+        if (p != null) {
             p.setInstallerPackageName(installerPkgName);
         }
     }
 
+    void setVolumeUuid(String pkgName, String volumeUuid) {
+        PackageSetting p = mPackages.get(pkgName);
+        if (p != null) {
+            p.setVolumeUuid(volumeUuid);
+        }
+    }
+
     SharedUserSetting getSharedUserLPw(String name,
             int pkgFlags, int pkgPrivateFlags, boolean create) {
         SharedUserSetting s = mSharedUsers.get(name);
@@ -593,8 +607,8 @@
                                     true, // notLaunched
                                     false, // hidden
                                     null, null, null,
-                                    false // blockUninstall
-                                    );
+                                    false, // blockUninstall
+                                    INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
                             writePackageRestrictionsLPr(user.id);
                         }
                     }
@@ -868,7 +882,7 @@
             if (mOtherUserIds.get(uid) != null) {
                 PackageManagerService.reportSettingsProblem(Log.ERROR,
                         "Adding duplicate shared id: " + uid
-                        + " name=" + name);
+                                + " name=" + name);
                 return false;
             }
             mOtherUserIds.put(uid, obj);
@@ -934,6 +948,96 @@
         return cpir;
     }
 
+    /**
+     * The following functions suppose that you have a lock for managing access to the
+     * mIntentFiltersVerifications map.
+     */
+
+    /* package protected */
+    IntentFilterVerificationInfo getIntentFilterVerificationLPr(String packageName) {
+        PackageSetting ps = mPackages.get(packageName);
+        if (ps == null) {
+            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
+            return null;
+        }
+        return ps.getIntentFilterVerificationInfo();
+    }
+
+    /* package protected */
+    boolean createIntentFilterVerificationIfNeededLPw(String packageName, String[] domains) {
+        PackageSetting ps = mPackages.get(packageName);
+        if (ps == null) {
+            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
+            return false;
+        }
+        if (ps.getIntentFilterVerificationInfo() == null) {
+            IntentFilterVerificationInfo ivi = new IntentFilterVerificationInfo(packageName, domains);
+            ps.setIntentFilterVerificationInfo(ivi);
+            return false;
+        }
+        return true;
+    }
+
+    int getIntentFilterVerificationStatusLPr(String packageName, int userId) {
+        PackageSetting ps = mPackages.get(packageName);
+        if (ps == null) {
+            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
+            return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+        }
+        int status = ps.getDomainVerificationStatusForUser(userId);
+        if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
+            if (ps.getIntentFilterVerificationInfo() != null) {
+                status = ps.getIntentFilterVerificationInfo().getStatus();
+            }
+        }
+        return status;
+    }
+
+    boolean updateIntentFilterVerificationStatusLPw(String packageName, int status, int userId) {
+        PackageSetting ps = mPackages.get(packageName);
+        if (ps == null) {
+            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
+            return false;
+        }
+        ps.setDomainVerificationStatusForUser(status, userId);
+        return true;
+    }
+
+    /**
+     * Used for dump. Should be read only.
+     */
+    List<IntentFilterVerificationInfo> getIntentFilterVerificationsLPr(
+            String packageName) {
+        if (packageName == null) {
+            return Collections.<IntentFilterVerificationInfo>emptyList();
+        }
+        ArrayList<IntentFilterVerificationInfo> result = new ArrayList<>();
+        for (PackageSetting ps : mPackages.values()) {
+            IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo();
+            if (ivi == null || TextUtils.isEmpty(ivi.getPackageName()) ||
+                    !ivi.getPackageName().equalsIgnoreCase(packageName)) {
+                continue;
+            }
+            result.add(ivi);
+        }
+        return result;
+    }
+
+    void removeIntentFilterVerificationLPw(String packageName, int userId) {
+        PackageSetting ps = mPackages.get(packageName);
+        if (ps == null) {
+            Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName);
+            return;
+        }
+        ps.clearDomainVerificationStatusForUser(userId);
+    }
+
+    void removeIntentFilterVerificationLPw(String packageName, int[] userIds) {
+        for (int userId : userIds) {
+            removeIntentFilterVerificationLPw(packageName, userId);
+        }
+    }
+
     private File getUserPackagesStateFile(int userId) {
         // TODO: Implement a cleaner solution when adding tests.
         // This instead of Environment.getUserSystemDirectory(userId) to support testing.
@@ -948,6 +1052,17 @@
         return new File(userDir, RUNTIME_PERMISSIONS_FILE_NAME);
     }
 
+    boolean isFirstRuntimePermissionsBoot() {
+        return !getUserRuntimePermissionsFile(UserHandle.USER_OWNER).exists();
+    }
+
+    void deleteRuntimePermissionsFiles() {
+        for (int userId : UserManagerService.getInstance().getUserIds()) {
+            File file = getUserRuntimePermissionsFile(userId);
+            file.delete();
+        }
+    }
+
     private File getUserPackagesStateBackupFile(int userId) {
         return new File(Environment.getUserSystemDirectory(userId),
                 "package-restrictions-backup.xml");
@@ -1002,7 +1117,13 @@
         mExternalDatabaseVersion = CURRENT_DATABASE_VERSION;
     }
 
-    private void readPreferredActivitiesLPw(XmlPullParser parser, int userId)
+    /**
+     * Applies the preferred activity state described by the given XML.  This code
+     * also supports the restore-from-backup code path.
+     *
+     * @see PreferredActivityBackupHelper
+     */
+    void readPreferredActivitiesLPw(XmlPullParser parser, int userId)
             throws XmlPullParserException, IOException {
         int outerDepth = parser.getDepth();
         int type;
@@ -1075,6 +1196,25 @@
         }
     }
 
+    private void readDomainVerificationLPw(XmlPullParser parser, PackageSettingBase packageSetting)
+            throws XmlPullParserException, IOException {
+        IntentFilterVerificationInfo ivi = new IntentFilterVerificationInfo(parser);
+        packageSetting.setIntentFilterVerificationInfo(ivi);
+        Log.d(TAG, "Read domain verification for package:" + ivi.getPackageName());
+    }
+
+    void writeDomainVerificationsLPr(XmlSerializer serializer, String packageName,
+                                     IntentFilterVerificationInfo verificationInfo)
+            throws IllegalArgumentException, IllegalStateException, IOException {
+        if (verificationInfo != null && verificationInfo.getPackageName() != null) {
+            serializer.startTag(null, TAG_DOMAIN_VERIFICATION);
+            verificationInfo.writeToXml(serializer);
+            Log.d(TAG, "Wrote domain verification for package: "
+                    + verificationInfo.getPackageName());
+            serializer.endTag(null, TAG_DOMAIN_VERIFICATION);
+        }
+    }
+
     void readPackageRestrictionsLPr(int userId) {
         if (DEBUG_MU) {
             Log.i(TAG, "Reading package restrictions for user=" + userId);
@@ -1119,8 +1259,8 @@
                                 false,  // notLaunched
                                 false,  // hidden
                                 null, null, null,
-                                false // blockUninstall
-                                );
+                                false, // blockUninstall
+                                INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
                     }
                     return;
                 }
@@ -1189,6 +1329,12 @@
                     final boolean blockUninstall = blockUninstallStr == null
                             ? false : Boolean.parseBoolean(blockUninstallStr);
 
+                    final String verifStateStr =
+                            parser.getAttributeValue(null, ATTR_DOMAIN_VERIFICATON_STATE);
+                    final int verifState = (verifStateStr == null) ?
+                            PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED :
+                            Integer.parseInt(verifStateStr);
+
                     ArraySet<String> enabledComponents = null;
                     ArraySet<String> disabledComponents = null;
 
@@ -1209,7 +1355,8 @@
                     }
 
                     ps.setUserState(userId, enabled, installed, stopped, notLaunched, hidden,
-                            enabledCaller, enabledComponents, disabledComponents, blockUninstall);
+                            enabledCaller, enabledComponents, disabledComponents, blockUninstall,
+                            verifState);
                 } else if (tagName.equals("preferred-activities")) {
                     readPreferredActivitiesLPw(parser, userId);
                 } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
@@ -1267,6 +1414,11 @@
         return components;
     }
 
+    /**
+     * Record the state of preferred activity configuration into XML.  This is used both
+     * for recording packages.xml internally and for supporting backup/restore of the
+     * preferred activity configuration.
+     */
     void writePreferredActivitiesLPr(XmlSerializer serializer, int userId, boolean full)
             throws IllegalArgumentException, IllegalStateException, IOException {
         serializer.startTag(null, "preferred-activities");
@@ -1356,7 +1508,9 @@
                                 && ustate.enabledComponents.size() > 0)
                         || (ustate.disabledComponents != null
                                 && ustate.disabledComponents.size() > 0)
-                        || ustate.blockUninstall) {
+                        || ustate.blockUninstall
+                        || (ustate.domainVerificationStatus !=
+                            PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED)) {
                     serializer.startTag(null, TAG_PACKAGE);
                     serializer.attribute(null, ATTR_NAME, pkg.name);
                     if (DEBUG_MU) Log.i(TAG, "  pkg=" + pkg.name + ", state=" + ustate.enabled);
@@ -1384,6 +1538,11 @@
                                     ustate.lastDisableAppCaller);
                         }
                     }
+                    if (ustate.domainVerificationStatus !=
+                            PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
+                        serializer.attribute(null, ATTR_DOMAIN_VERIFICATON_STATE,
+                                Integer.toString(ustate.domainVerificationStatus));
+                    }
                     if (ustate.enabledComponents != null
                             && ustate.enabledComponents.size() > 0) {
                         serializer.startTag(null, TAG_ENABLED_COMPONENTS);
@@ -1410,9 +1569,7 @@
             }
 
             writePreferredActivitiesLPr(serializer, userId, true);
-
             writePersistentPreferredActivitiesLPr(serializer, userId);
-
             writeCrossProfileIntentFiltersLPr(serializer, userId);
 
             serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
@@ -1917,38 +2074,33 @@
         if (pkg.installerPackageName != null) {
             serializer.attribute(null, "installer", pkg.installerPackageName);
         }
+        if (pkg.volumeUuid != null) {
+            serializer.attribute(null, "volumeUuid", pkg.volumeUuid);
+        }
         pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
         if ((pkg.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
             writePermissionsLPr(serializer, pkg.getPermissionsState().getInstallPermissions());
         }
 
-        writeSigningKeySetsLPr(serializer, pkg.keySetData);
+        writeSigningKeySetLPr(serializer, pkg.keySetData);
         writeUpgradeKeySetsLPr(serializer, pkg.keySetData);
         writeKeySetAliasesLPr(serializer, pkg.keySetData);
+        writeDomainVerificationsLPr(serializer, pkg.name, pkg.verificationInfo);
 
         serializer.endTag(null, "package");
     }
 
-    void writeSigningKeySetsLPr(XmlSerializer serializer,
+    void writeSigningKeySetLPr(XmlSerializer serializer,
             PackageKeySetData data) throws IOException {
-        if (data.getSigningKeySets() != null) {
-            // Keep track of the original signing-keyset.
-            // Must be recorded first, since it will be read first and wipe the
-            // current signing-keysets for the package when set.
-            long properSigningKeySet = data.getProperSigningKeySet();
-            serializer.startTag(null, "proper-signing-keyset");
-            serializer.attribute(null, "identifier", Long.toString(properSigningKeySet));
-            serializer.endTag(null, "proper-signing-keyset");
-            for (long id : data.getSigningKeySets()) {
-                serializer.startTag(null, "signing-keyset");
-                serializer.attribute(null, "identifier", Long.toString(id));
-                serializer.endTag(null, "signing-keyset");
-            }
-        }
+        serializer.startTag(null, "proper-signing-keyset");
+        serializer.attribute(null, "identifier",
+                Long.toString(data.getProperSigningKeySet()));
+        serializer.endTag(null, "proper-signing-keyset");
     }
 
     void writeUpgradeKeySetsLPr(XmlSerializer serializer,
             PackageKeySetData data) throws IOException {
+        long properSigning = data.getProperSigningKeySet();
         if (data.isUsingUpgradeKeySets()) {
             for (long id : data.getUpgradeKeySets()) {
                 serializer.startTag(null, "upgrade-keyset");
@@ -2040,6 +2192,7 @@
 
         mPendingPackages.clear();
         mPastSignatures.clear();
+        mKeySetRefs.clear();
 
         try {
             if (str == null) {
@@ -2101,7 +2254,8 @@
                     // TODO: check whether this is okay! as it is very
                     // similar to how preferred-activities are treated
                     readCrossProfileIntentFiltersLPw(parser, 0);
-                } else if (tagName.equals("updated-package")) {
+                }
+                else if (tagName.equals("updated-package")) {
                     readDisabledSysPackageLPw(parser);
                 } else if (tagName.equals("cleaning-package")) {
                     String name = parser.getAttributeValue(null, ATTR_NAME);
@@ -2166,7 +2320,7 @@
                     final String enforcement = parser.getAttributeValue(null, ATTR_ENFORCEMENT);
                     mReadExternalStorageEnforced = "1".equals(enforcement);
                 } else if (tagName.equals("keyset-settings")) {
-                    mKeySetManagerService.readKeySetsLPw(parser);
+                    mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs);
                 } else {
                     Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
                             + parser.getName());
@@ -2188,6 +2342,7 @@
         }
 
         final int N = mPendingPackages.size();
+
         for (int i = 0; i < N; i++) {
             final PendingPackage pp = mPendingPackages.get(i);
             Object idObj = getUserIdLPr(pp.sharedId);
@@ -2730,6 +2885,18 @@
             }
         }
 
+        // We keep track for which users we granted permissions to be able
+        // to grant runtime permissions to system apps for newly appeared
+        // users or newly appeared system apps. If we supported runtime
+        // permissions during the previous boot, then we already granted
+        // permissions for all device users. In such a case we set the users
+        // for which we granted permissions to avoid clobbering of runtime
+        // permissions we granted to system apps but the user revoked later.
+        if (!isFirstRuntimePermissionsBoot()) {
+            final int[] userIds = UserManagerService.getInstance().getUserIds();
+            ps.setPermissionsUpdatedForUserIds(userIds);
+        }
+
         mDisabledSysPackages.put(name, ps);
     }
 
@@ -2752,6 +2919,7 @@
         String cpuAbiOverrideString = null;
         String systemStr = null;
         String installerPackageName = null;
+        String volumeUuid = null;
         String uidError = null;
         int pkgFlags = 0;
         int pkgPrivateFlags = 0;
@@ -2789,6 +2957,7 @@
                 }
             }
             installerPackageName = parser.getAttributeValue(null, "installer");
+            volumeUuid = parser.getAttributeValue(null, "volumeUuid");
 
             systemStr = parser.getAttributeValue(null, "publicFlags");
             if (systemStr != null) {
@@ -2937,6 +3106,7 @@
         if (packageSetting != null) {
             packageSetting.uidError = "true".equals(uidError);
             packageSetting.installerPackageName = installerPackageName;
+            packageSetting.volumeUuid = volumeUuid;
             packageSetting.legacyNativeLibraryPathString = legacyNativeLibraryPathStr;
             packageSetting.primaryCpuAbiString = primaryCpuAbiString;
             packageSetting.secondaryCpuAbiString = secondaryCpuAbiString;
@@ -2990,20 +3160,33 @@
                 } else if (tagName.equals(TAG_PERMISSIONS)) {
                     readInstallPermissionsLPr(parser,
                             packageSetting.getPermissionsState());
-                    packageSetting.permissionsFixed = true;
+                    packageSetting.installPermissionsFixed = true;
                 } else if (tagName.equals("proper-signing-keyset")) {
                     long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
+                    Integer refCt = mKeySetRefs.get(id);
+                    if (refCt != null) {
+                        mKeySetRefs.put(id, refCt + 1);
+                    } else {
+                        mKeySetRefs.put(id, 1);
+                    }
                     packageSetting.keySetData.setProperSigningKeySet(id);
                 } else if (tagName.equals("signing-keyset")) {
-                    long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
-                    packageSetting.keySetData.addSigningKeySet(id);
+                    // from v1 of keysetmanagerservice - no longer used
                 } else if (tagName.equals("upgrade-keyset")) {
                     long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
                     packageSetting.keySetData.addUpgradeKeySetById(id);
                 } else if (tagName.equals("defined-keyset")) {
                     long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
                     String alias = parser.getAttributeValue(null, "alias");
+                    Integer refCt = mKeySetRefs.get(id);
+                    if (refCt != null) {
+                        mKeySetRefs.put(id, refCt + 1);
+                    } else {
+                        mKeySetRefs.put(id, 1);
+                    }
                     packageSetting.keySetData.addDefinedKeySet(id, alias);
+                } else if (tagName.equals(TAG_DOMAIN_VERIFICATION)) {
+                    readDomainVerificationLPw(parser, packageSetting);
                 } else {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Unknown element under <package>: " + parser.getName());
@@ -3011,7 +3194,17 @@
                 }
             }
 
-
+            // We keep track for which users we granted permissions to be able
+            // to grant runtime permissions to system apps for newly appeared
+            // users or newly appeared system apps. If we supported runtime
+            // permissions during the previous boot, then we already granted
+            // permissions for all device users. In such a case we set the users
+            // for which we granted permissions to avoid clobbering of runtime
+            // permissions we granted to system apps but the user revoked later.
+            if (!isFirstRuntimePermissionsBoot()) {
+                final int[] userIds = UserManagerService.getInstance().getUserIds();
+                packageSetting.setPermissionsUpdatedForUserIds(userIds);
+            }
         } else {
             XmlUtils.skipCurrentTag(parser);
         }
@@ -3129,6 +3322,18 @@
                     XmlUtils.skipCurrentTag(parser);
                 }
             }
+
+            // We keep track for which users we granted permissions to be able
+            // to grant runtime permissions to system apps for newly appeared
+            // users or newly appeared system apps. If we supported runtime
+            // permissions during the previous boot, then we already granted
+            // permissions for all device users. In such a case we set the users
+            // for which we granted permissions to avoid clobbering of runtime
+            // permissions we granted to system apps but the user revoked later.
+            if (!isFirstRuntimePermissionsBoot()) {
+                final int[] userIds = UserManagerService.getInstance().getUserIds();
+                su.setPermissionsUpdatedForUserIds(userIds);
+            }
         } else {
             XmlUtils.skipCurrentTag(parser);
         }
@@ -3346,7 +3551,7 @@
         return false;
     }
 
-    private List<UserInfo> getAllUsers() {
+    List<UserInfo> getAllUsers() {
         long id = Binder.clearCallingIdentity();
         try {
             return UserManagerService.getInstance().getUsers(false);
@@ -3358,6 +3563,22 @@
         return null;
     }
 
+    /**
+     * Return all {@link PackageSetting} that are actively installed on the
+     * given {@link VolumeInfo#fsUuid}.
+     */
+    List<PackageSetting> getVolumePackagesLPr(String volumeUuid) {
+        Preconditions.checkNotNull(volumeUuid);
+        ArrayList<PackageSetting> res = new ArrayList<>();
+        for (int i = 0; i < mPackages.size(); i++) {
+            final PackageSetting setting = mPackages.valueAt(i);
+            if (Objects.equals(volumeUuid, setting.volumeUuid)) {
+                res.add(setting);
+            }
+        }
+        return res;
+    }
+
     static void printFlags(PrintWriter pw, int val, Object[] spec) {
         pw.print("[ ");
         for (int i=0; i<spec.length; i+=2) {
@@ -3564,8 +3785,13 @@
             pw.print(prefix); pw.print("  installerPackageName=");
                     pw.println(ps.installerPackageName);
         }
+        if (ps.volumeUuid != null) {
+            pw.print(prefix); pw.print("  volumeUuid=");
+                    pw.println(ps.volumeUuid);
+        }
         pw.print(prefix); pw.print("  signatures="); pw.println(ps.signatures);
-        pw.print(prefix); pw.print("  permissionsFixed="); pw.print(ps.permissionsFixed);
+        pw.print(prefix); pw.print("  installPermissionsFixed=");
+                pw.print(ps.installPermissionsFixed);
                 pw.print(" installStatus="); pw.println(ps.installStatus);
         pw.print(prefix); pw.print("  pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
                 pw.println();
@@ -3842,11 +4068,19 @@
         }
 
         public void writePermissionsForUserSyncLPr(int userId) {
+            if (!PackageManagerService.RUNTIME_PERMISSIONS_ENABLED) {
+                return;
+            }
+
             mHandler.removeMessages(userId);
             writePermissionsSync(userId);
         }
 
         public void writePermissionsForUserAsyncLPr(int userId) {
+            if (!PackageManagerService.RUNTIME_PERMISSIONS_ENABLED) {
+                return;
+            }
+
             final long currentTimeMillis = SystemClock.uptimeMillis();
 
             if (mWriteScheduled.get(userId)) {
@@ -4006,128 +4240,67 @@
 
         private void parseRuntimePermissionsLPr(XmlPullParser parser, int userId)
                 throws IOException, XmlPullParserException {
-            parser.next();
-            skipEmptyTextTags(parser);
-            if (!accept(parser, XmlPullParser.START_TAG, TAG_RUNTIME_PERMISSIONS)) {
-                return;
-            }
+            final int outerDepth = parser.getDepth();
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                    continue;
+                }
 
-            parser.next();
+                switch (parser.getName()) {
+                    case TAG_PACKAGE: {
+                        String name = parser.getAttributeValue(null, ATTR_NAME);
+                        PackageSetting ps = mPackages.get(name);
+                        if (ps == null) {
+                            Slog.w(PackageManagerService.TAG, "Unknown package:" + name);
+                            XmlUtils.skipCurrentTag(parser);
+                            continue;
+                        }
+                        parsePermissionsLPr(parser, ps.getPermissionsState(), userId);
+                    } break;
 
-            while (parsePackageLPr(parser, userId)
-                    || parseSharedUserLPr(parser, userId)) {
-                parser.next();
-            }
-
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.END_TAG, TAG_RUNTIME_PERMISSIONS);
-        }
-
-        private boolean parsePackageLPr(XmlPullParser parser, int userId)
-                throws IOException, XmlPullParserException {
-            skipEmptyTextTags(parser);
-            if (!accept(parser, XmlPullParser.START_TAG, TAG_PACKAGE)) {
-                return false;
-            }
-
-            String name = parser.getAttributeValue(null, ATTR_NAME);
-
-            parser.next();
-
-            PackageSetting ps = mPackages.get(name);
-            if (ps != null) {
-                while (parsePermissionLPr(parser, ps.getPermissionsState(), userId)) {
-                    parser.next();
+                    case TAG_SHARED_USER: {
+                        String name = parser.getAttributeValue(null, ATTR_NAME);
+                        SharedUserSetting sus = mSharedUsers.get(name);
+                        if (sus == null) {
+                            Slog.w(PackageManagerService.TAG, "Unknown shared user:" + name);
+                            XmlUtils.skipCurrentTag(parser);
+                            continue;
+                        }
+                        parsePermissionsLPr(parser, sus.getPermissionsState(), userId);
+                    } break;
                 }
             }
-
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.END_TAG, TAG_PACKAGE);
-
-            return true;
         }
 
-        private boolean parseSharedUserLPr(XmlPullParser parser, int userId)
-                throws IOException, XmlPullParserException {
-            skipEmptyTextTags(parser);
-            if (!accept(parser, XmlPullParser.START_TAG, TAG_SHARED_USER)) {
-                return false;
-            }
-
-            String name = parser.getAttributeValue(null, ATTR_NAME);
-
-            parser.next();
-
-            SharedUserSetting sus = mSharedUsers.get(name);
-            if (sus != null) {
-                while (parsePermissionLPr(parser, sus.getPermissionsState(), userId)) {
-                    parser.next();
-                }
-            }
-
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.END_TAG, TAG_SHARED_USER);
-
-            return true;
-        }
-
-        private boolean parsePermissionLPr(XmlPullParser parser, PermissionsState permissionsState,
+        private void parsePermissionsLPr(XmlPullParser parser, PermissionsState permissionsState,
                 int userId) throws IOException, XmlPullParserException {
-            skipEmptyTextTags(parser);
-            if (!accept(parser, XmlPullParser.START_TAG, TAG_ITEM)) {
-                return false;
-            }
-
-            String name = parser.getAttributeValue(null, ATTR_NAME);
-
-            parser.next();
-
-            BasePermission bp = mPermissions.get(name);
-            if (bp != null) {
-                if (permissionsState.grantRuntimePermission(bp, userId) ==
-                        PermissionsState.PERMISSION_OPERATION_FAILURE) {
-                    Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name);
+            final int outerDepth = parser.getDepth();
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                    continue;
                 }
-            } else {
-                Slog.w(PackageManagerService.TAG, "Unknown permission:" + name);
-            }
 
-            skipEmptyTextTags(parser);
-            expect(parser, XmlPullParser.END_TAG, TAG_ITEM);
+                switch (parser.getName()) {
+                    case TAG_ITEM: {
+                        String name = parser.getAttributeValue(null, ATTR_NAME);
+                        BasePermission bp = mPermissions.get(name);
+                        if (bp == null) {
+                            Slog.w(PackageManagerService.TAG, "Unknown permission:" + name);
+                            XmlUtils.skipCurrentTag(parser);
+                            continue;
+                        }
 
-            return true;
-        }
-
-        private void expect(XmlPullParser parser, int type, String tag)
-                throws IOException, XmlPullParserException {
-            if (!accept(parser, type, tag)) {
-                throw new XmlPullParserException("Expected event: " + type
-                        + " and tag: " + tag + " but got event: " + parser.getEventType()
-                        + " and tag:" + parser.getName());
-            }
-        }
-
-        private void skipEmptyTextTags(XmlPullParser parser)
-                throws IOException, XmlPullParserException {
-            while (accept(parser, XmlPullParser.TEXT, null)
-                    && parser.isWhitespace()) {
-                parser.next();
-            }
-        }
-
-        private boolean accept(XmlPullParser parser, int type, String tag)
-                throws IOException, XmlPullParserException {
-            if (parser.getEventType() != type) {
-                return false;
-            }
-            if (tag != null) {
-                if (!tag.equals(parser.getName())) {
-                    return false;
+                        if (permissionsState.grantRuntimePermission(bp, userId) ==
+                                PermissionsState.PERMISSION_OPERATION_FAILURE) {
+                            Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name);
+                        }
+                    } break;
                 }
-            } else if (parser.getName() != null) {
-                return false;
             }
-            return true;
         }
 
         private void writePermissions(XmlSerializer serializer, Set<String> permissions)
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 26ecb72..a8c5527 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -36,6 +36,7 @@
 import android.os.IUserManager;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -49,9 +50,11 @@
 import android.util.TimeUtils;
 import android.util.Xml;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -71,6 +74,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import libcore.io.IoUtils;
+
 public class UserManagerService extends IUserManager.Stub {
 
     private static final String LOG_TAG = "UserManagerService";
@@ -107,6 +112,8 @@
     private static final String ATTR_TYPE_STRING = "s";
     private static final String ATTR_TYPE_BOOLEAN = "b";
     private static final String ATTR_TYPE_INTEGER = "i";
+    private static final String ATTR_TYPE_BUNDLE = "B";
+    private static final String ATTR_TYPE_BUNDLE_ARRAY = "BA";
 
     private static final String USER_INFO_DIR = "system" + File.separator + "users";
     private static final String USER_LIST_FILENAME = "userlist.xml";
@@ -1219,6 +1226,7 @@
                     updateUserIdsLocked();
                     Bundle restrictions = new Bundle();
                     mUserRestrictions.append(userId, restrictions);
+                    mPm.newUserCreatedLILPw(userId);
                 }
             }
             if (userInfo != null) {
@@ -1671,124 +1679,171 @@
 
     private Bundle readApplicationRestrictionsLocked(String packageName,
             int userId) {
+        AtomicFile restrictionsFile =
+                new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
+                        packageToRestrictionsFileName(packageName)));
+        return readApplicationRestrictionsLocked(restrictionsFile);
+    }
+
+    @VisibleForTesting
+    static Bundle readApplicationRestrictionsLocked(AtomicFile restrictionsFile) {
         final Bundle restrictions = new Bundle();
-        final ArrayList<String> values = new ArrayList<String>();
+        final ArrayList<String> values = new ArrayList<>();
+        if (!restrictionsFile.getBaseFile().exists()) {
+            return restrictions;
+        }
 
         FileInputStream fis = null;
         try {
-            AtomicFile restrictionsFile =
-                    new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
-                            packageToRestrictionsFileName(packageName)));
             fis = restrictionsFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(fis, null);
-            int type;
-            while ((type = parser.next()) != XmlPullParser.START_TAG
-                    && type != XmlPullParser.END_DOCUMENT) {
-                ;
-            }
-
-            if (type != XmlPullParser.START_TAG) {
+            XmlUtils.nextElement(parser);
+            if (parser.getEventType() != XmlPullParser.START_TAG) {
                 Slog.e(LOG_TAG, "Unable to read restrictions file "
                         + restrictionsFile.getBaseFile());
                 return restrictions;
             }
-
-            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
-                if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_ENTRY)) {
-                    String key = parser.getAttributeValue(null, ATTR_KEY);
-                    String valType = parser.getAttributeValue(null, ATTR_VALUE_TYPE);
-                    String multiple = parser.getAttributeValue(null, ATTR_MULTIPLE);
-                    if (multiple != null) {
-                        values.clear();
-                        int count = Integer.parseInt(multiple);
-                        while (count > 0 && (type = parser.next()) != XmlPullParser.END_DOCUMENT) {
-                            if (type == XmlPullParser.START_TAG
-                                    && parser.getName().equals(TAG_VALUE)) {
-                                values.add(parser.nextText().trim());
-                                count--;
-                            }
-                        }
-                        String [] valueStrings = new String[values.size()];
-                        values.toArray(valueStrings);
-                        restrictions.putStringArray(key, valueStrings);
-                    } else {
-                        String value = parser.nextText().trim();
-                        if (ATTR_TYPE_BOOLEAN.equals(valType)) {
-                            restrictions.putBoolean(key, Boolean.parseBoolean(value));
-                        } else if (ATTR_TYPE_INTEGER.equals(valType)) {
-                            restrictions.putInt(key, Integer.parseInt(value));
-                        } else {
-                            restrictions.putString(key, value);
-                        }
-                    }
-                }
+            while (parser.next() != XmlPullParser.END_DOCUMENT) {
+                readEntry(restrictions, values, parser);
             }
-        } catch (IOException ioe) {
-        } catch (XmlPullParserException pe) {
+        } catch (IOException|XmlPullParserException e) {
+            Log.w(LOG_TAG, "Error parsing " + restrictionsFile.getBaseFile(), e);
         } finally {
-            if (fis != null) {
-                try {
-                    fis.close();
-                } catch (IOException e) {
-                }
-            }
+            IoUtils.closeQuietly(fis);
         }
         return restrictions;
     }
 
+    private static void readEntry(Bundle restrictions, ArrayList<String> values,
+            XmlPullParser parser) throws XmlPullParserException, IOException {
+        int type = parser.getEventType();
+        if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_ENTRY)) {
+            String key = parser.getAttributeValue(null, ATTR_KEY);
+            String valType = parser.getAttributeValue(null, ATTR_VALUE_TYPE);
+            String multiple = parser.getAttributeValue(null, ATTR_MULTIPLE);
+            if (multiple != null) {
+                values.clear();
+                int count = Integer.parseInt(multiple);
+                while (count > 0 && (type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                    if (type == XmlPullParser.START_TAG
+                            && parser.getName().equals(TAG_VALUE)) {
+                        values.add(parser.nextText().trim());
+                        count--;
+                    }
+                }
+                String [] valueStrings = new String[values.size()];
+                values.toArray(valueStrings);
+                restrictions.putStringArray(key, valueStrings);
+            } else if (ATTR_TYPE_BUNDLE.equals(valType)) {
+                restrictions.putBundle(key, readBundleEntry(parser, values));
+            } else if (ATTR_TYPE_BUNDLE_ARRAY.equals(valType)) {
+                final int outerDepth = parser.getDepth();
+                ArrayList<Bundle> bundleList = new ArrayList<>();
+                while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+                    Bundle childBundle = readBundleEntry(parser, values);
+                    bundleList.add(childBundle);
+                }
+                restrictions.putParcelableArray(key,
+                        bundleList.toArray(new Bundle[bundleList.size()]));
+            } else {
+                String value = parser.nextText().trim();
+                if (ATTR_TYPE_BOOLEAN.equals(valType)) {
+                    restrictions.putBoolean(key, Boolean.parseBoolean(value));
+                } else if (ATTR_TYPE_INTEGER.equals(valType)) {
+                    restrictions.putInt(key, Integer.parseInt(value));
+                } else {
+                    restrictions.putString(key, value);
+                }
+            }
+        }
+    }
+
+    private static Bundle readBundleEntry(XmlPullParser parser, ArrayList<String> values)
+            throws IOException, XmlPullParserException {
+        Bundle childBundle = new Bundle();
+        final int outerDepth = parser.getDepth();
+        while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+            readEntry(childBundle, values, parser);
+        }
+        return childBundle;
+    }
+
     private void writeApplicationRestrictionsLocked(String packageName,
             Bundle restrictions, int userId) {
-        FileOutputStream fos = null;
         AtomicFile restrictionsFile = new AtomicFile(
                 new File(Environment.getUserSystemDirectory(userId),
                         packageToRestrictionsFileName(packageName)));
+        writeApplicationRestrictionsLocked(restrictions, restrictionsFile);
+    }
+
+    @VisibleForTesting
+    static void writeApplicationRestrictionsLocked(Bundle restrictions,
+            AtomicFile restrictionsFile) {
+        FileOutputStream fos = null;
         try {
             fos = restrictionsFile.startWrite();
             final BufferedOutputStream bos = new BufferedOutputStream(fos);
 
-            // XmlSerializer serializer = XmlUtils.serializerInstance();
             final XmlSerializer serializer = new FastXmlSerializer();
             serializer.setOutput(bos, "utf-8");
             serializer.startDocument(null, true);
             serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
             serializer.startTag(null, TAG_RESTRICTIONS);
-
-            for (String key : restrictions.keySet()) {
-                Object value = restrictions.get(key);
-                serializer.startTag(null, TAG_ENTRY);
-                serializer.attribute(null, ATTR_KEY, key);
-
-                if (value instanceof Boolean) {
-                    serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BOOLEAN);
-                    serializer.text(value.toString());
-                } else if (value instanceof Integer) {
-                    serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_INTEGER);
-                    serializer.text(value.toString());
-                } else if (value == null || value instanceof String) {
-                    serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING);
-                    serializer.text(value != null ? (String) value : "");
-                } else {
-                    serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING_ARRAY);
-                    String[] values = (String[]) value;
-                    serializer.attribute(null, ATTR_MULTIPLE, Integer.toString(values.length));
-                    for (String choice : values) {
-                        serializer.startTag(null, TAG_VALUE);
-                        serializer.text(choice != null ? choice : "");
-                        serializer.endTag(null, TAG_VALUE);
-                    }
-                }
-                serializer.endTag(null, TAG_ENTRY);
-            }
-
+            writeBundle(restrictions, serializer);
             serializer.endTag(null, TAG_RESTRICTIONS);
 
             serializer.endDocument();
             restrictionsFile.finishWrite(fos);
         } catch (Exception e) {
             restrictionsFile.failWrite(fos);
-            Slog.e(LOG_TAG, "Error writing application restrictions list");
+            Slog.e(LOG_TAG, "Error writing application restrictions list", e);
+        }
+    }
+
+    private static void writeBundle(Bundle restrictions, XmlSerializer serializer)
+            throws IOException {
+        for (String key : restrictions.keySet()) {
+            Object value = restrictions.get(key);
+            serializer.startTag(null, TAG_ENTRY);
+            serializer.attribute(null, ATTR_KEY, key);
+
+            if (value instanceof Boolean) {
+                serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BOOLEAN);
+                serializer.text(value.toString());
+            } else if (value instanceof Integer) {
+                serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_INTEGER);
+                serializer.text(value.toString());
+            } else if (value == null || value instanceof String) {
+                serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING);
+                serializer.text(value != null ? (String) value : "");
+            } else if (value instanceof Bundle) {
+                serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE);
+                writeBundle((Bundle) value, serializer);
+            } else if (value instanceof Parcelable[]) {
+                serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE_ARRAY);
+                Parcelable[] array = (Parcelable[]) value;
+                for (Parcelable parcelable : array) {
+                    if (!(parcelable instanceof Bundle)) {
+                        throw new IllegalArgumentException("bundle-array can only hold Bundles");
+                    }
+                    serializer.startTag(null, TAG_ENTRY);
+                    serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE);
+                    writeBundle((Bundle) parcelable, serializer);
+                    serializer.endTag(null, TAG_ENTRY);
+                }
+            } else {
+                serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING_ARRAY);
+                String[] values = (String[]) value;
+                serializer.attribute(null, ATTR_MULTIPLE, Integer.toString(values.length));
+                for (String choice : values) {
+                    serializer.startTag(null, TAG_VALUE);
+                    serializer.text(choice != null ? choice : "");
+                    serializer.endTag(null, TAG_VALUE);
+                }
+            }
+            serializer.endTag(null, TAG_ENTRY);
         }
     }
 
diff --git a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
index 847eee8..fef1e575 100644
--- a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
+++ b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
@@ -27,6 +27,7 @@
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.os.SystemClock;
+import android.util.Slog;
 import android.view.Display;
 import android.view.animation.LinearInterpolator;
 
@@ -45,6 +46,8 @@
     private static final long BURNIN_PROTECTION_WAKEUP_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
     private static final long BURNIN_PROTECTION_MINIMAL_INTERVAL_MS = TimeUnit.SECONDS.toMillis(10);
 
+    private static final boolean DEBUG = false;
+
     private static final String ACTION_BURN_IN_PROTECTION =
             "android.internal.policy.action.BURN_IN_PROTECTION";
 
@@ -77,10 +80,13 @@
     private BroadcastReceiver mBurnInProtectionReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
+            if (DEBUG) {
+                Slog.d(TAG, "onReceive " + intent);
+            }
             updateBurnInProtection();
         }
     };
-    
+
     public BurnInProtectionHelper(Context context, int minHorizontalOffset,
             int maxHorizontalOffset, int minVerticalOffset, int maxVerticalOffset,
             int maxOffsetRadius) {
@@ -136,12 +142,26 @@
                 mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(),
                         mLastBurnInXOffset, mLastBurnInYOffset);
             }
+            // We use currentTimeMillis to compute the next wakeup time since we want to wake up at
+            // the same time as we wake up to update ambient mode to minimize power consumption.
+            // However, we use elapsedRealtime to schedule the alarm so that setting the time can't
+            // disable burn-in protection for extended periods.
+            final long nowWall = System.currentTimeMillis();
+            final long nowElapsed = SystemClock.elapsedRealtime();
             // Next adjustment at least ten seconds in the future.
-            long next = SystemClock.elapsedRealtime() + BURNIN_PROTECTION_MINIMAL_INTERVAL_MS;
+            long nextWall = nowWall + BURNIN_PROTECTION_MINIMAL_INTERVAL_MS;
             // And aligned to the minute.
-            next = next - next % BURNIN_PROTECTION_WAKEUP_INTERVAL_MS
+            nextWall = nextWall - nextWall % BURNIN_PROTECTION_WAKEUP_INTERVAL_MS
                     + BURNIN_PROTECTION_WAKEUP_INTERVAL_MS;
-            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mBurnInProtectionIntent);
+            // Use elapsed real time that is adjusted to full minute on wall clock.
+            final long nextElapsed = nowElapsed + (nextWall - nowWall);
+            if (DEBUG) {
+                Slog.d(TAG, "scheduling next wake-up, now wall time " + nowWall
+                        + ", next wall: " + nextWall + ", now elapsed: " + nowElapsed
+                        + ", next elapsed: " + nextElapsed);
+            }
+            mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, nextElapsed,
+                    mBurnInProtectionIntent);
         } else {
             mAlarmManager.cancel(mBurnInProtectionIntent);
             mCenteringAnimator.start();
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index be6550c..ed14569 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1398,6 +1398,14 @@
                     public void onDebug() {
                         // no-op
                     }
+                    @Override
+                    public void onDown() {
+                        mOrientationListener.onTouchStart();
+                    }
+                    @Override
+                    public void onUpOrCancel() {
+                        mOrientationListener.onTouchEnd();
+                    }
                 });
         mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
         mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
@@ -1914,6 +1922,7 @@
         case TYPE_PHONE:
             return 3;
         case TYPE_SEARCH_BAR:
+        case TYPE_VOICE_INTERACTION_STARTING:
             return 4;
         case TYPE_VOICE_INTERACTION:
             // voice interaction layer is almost immediately above apps.
@@ -2262,16 +2271,9 @@
                 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
                 break;
             case TYPE_NAVIGATION_BAR_PANEL:
-                mContext.enforceCallingOrSelfPermission(
-                        android.Manifest.permission.STATUS_BAR_SERVICE,
-                        "PhoneWindowManager");
-                break;
             case TYPE_STATUS_BAR_PANEL:
-                mContext.enforceCallingOrSelfPermission(
-                        android.Manifest.permission.STATUS_BAR_SERVICE,
-                        "PhoneWindowManager");
-                break;
             case TYPE_STATUS_BAR_SUB_PANEL:
+            case TYPE_VOICE_INTERACTION_STARTING:
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.STATUS_BAR_SERVICE,
                         "PhoneWindowManager");
@@ -3501,8 +3503,14 @@
     /** {@inheritDoc} */
     @Override
     public int getSystemDecorLayerLw() {
-        if (mStatusBar != null) return mStatusBar.getSurfaceLayer();
-        if (mNavigationBar != null) return mNavigationBar.getSurfaceLayer();
+        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
+            return mStatusBar.getSurfaceLayer();
+        }
+
+        if (mNavigationBar != null && mNavigationBar.isVisibleLw()) {
+            return mNavigationBar.getSurfaceLayer();
+        }
+
         return 0;
     }
 
@@ -3643,7 +3651,7 @@
                 pf.bottom = df.bottom = of.bottom = cf.bottom
                         = mOverscanScreenTop + mOverscanScreenHeight;
             }
-        } else  if (attrs.type == TYPE_INPUT_METHOD || attrs.type == TYPE_VOICE_INTERACTION) {
+        } else if (attrs.type == TYPE_INPUT_METHOD) {
             pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
             pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
             pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
@@ -3654,6 +3662,15 @@
             // IM dock windows always go to the bottom of the screen.
             attrs.gravity = Gravity.BOTTOM;
             mDockLayer = win.getSurfaceLayer();
+        } else if (attrs.type == TYPE_VOICE_INTERACTION) {
+            pf.left = df.left = of.left = cf.left = vf.left = mUnrestrictedScreenLeft;
+            pf.top = df.top = of.top = mUnrestrictedScreenTop;
+            pf.right = df.right = of.right = cf.right = vf.right = mUnrestrictedScreenLeft
+                    + mUnrestrictedScreenWidth;
+            pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
+                    + mUnrestrictedScreenHeight;
+            cf.bottom = vf.bottom = mStableBottom;
+            cf.top = vf.top = mStableTop;
         } else if (win == mStatusBar && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
             pf.left = df.left = of.left = mUnrestrictedScreenLeft;
             pf.top = df.top = of.top = mUnrestrictedScreenTop;
@@ -3893,6 +3910,7 @@
                         && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
                         && (attrs.type == TYPE_STATUS_BAR
                             || attrs.type == TYPE_TOAST
+                            || attrs.type == TYPE_VOICE_INTERACTION_STARTING
                             || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
                             && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
                     // Asking for layout as if the nav bar is hidden, lets the
diff --git a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
index cfa631f..627b328 100644
--- a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
@@ -75,6 +75,7 @@
                 mDebugFireable = true;
                 mDownPointers = 0;
                 captureDown(event, 0);
+                mCallbacks.onDown();
                 break;
             case MotionEvent.ACTION_POINTER_DOWN:
                 captureDown(event, event.getActionIndex());
@@ -106,6 +107,7 @@
             case MotionEvent.ACTION_CANCEL:
                 mSwipeFireable = false;
                 mDebugFireable = false;
+                mCallbacks.onUpOrCancel();
                 break;
             default:
                 if (DEBUG) Slog.d(TAG, "Ignoring " + event);
@@ -192,6 +194,8 @@
         void onSwipeFromTop();
         void onSwipeFromBottom();
         void onSwipeFromRight();
+        void onDown();
+        void onUpOrCancel();
         void onDebug();
     }
 }
diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index 0118127..c8fd82e 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -22,6 +22,7 @@
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.os.Handler;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Slog;
@@ -133,6 +134,24 @@
         }
     }
 
+    public void onTouchStart() {
+        synchronized (mLock) {
+            if (mSensorEventListener != null) {
+                mSensorEventListener.onTouchStartLocked();
+            }
+        }
+    }
+
+    public void onTouchEnd() {
+        long whenElapsedNanos = SystemClock.elapsedRealtimeNanos();
+
+        synchronized (mLock) {
+            if (mSensorEventListener != null) {
+                mSensorEventListener.onTouchEndLocked(whenElapsedNanos);
+            }
+        }
+    }
+
     /**
      * Sets the current rotation.
      *
@@ -269,6 +288,11 @@
         private static final long PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS =
                 500 * NANOS_PER_MS;
 
+        // The minimum amount of time that must have elapsed since the screen was last touched
+        // before the proposed rotation can change.
+        private static final long PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS =
+                500 * NANOS_PER_MS;
+
         // If the tilt angle remains greater than the specified angle for a minimum of
         // the specified time, then the device is deemed to be lying flat
         // (just chillin' on a table).
@@ -398,6 +422,10 @@
         private long mAccelerationTimestampNanos;
         private boolean mAccelerating;
 
+        // Timestamp when the last touch to the touch screen ended
+        private long mTouchEndedTimestampNanos = Long.MIN_VALUE;
+        private boolean mTouched;
+
         // Whether we are locked into an overhead usage mode.
         private boolean mOverhead;
 
@@ -422,6 +450,7 @@
             pw.println(prefix + "mSwinging=" + mSwinging);
             pw.println(prefix + "mAccelerating=" + mAccelerating);
             pw.println(prefix + "mOverhead=" + mOverhead);
+            pw.println(prefix + "mTouched=" + mTouched);
         }
 
         @Override
@@ -601,6 +630,7 @@
                             + ", isFlat=" + isFlat
                             + ", isSwinging=" + isSwinging
                             + ", isOverhead=" + mOverhead
+                            + ", isTouched=" + mTouched
                             + ", timeUntilSettledMS=" + remainingMS(now,
                                     mPredictedRotationTimestampNanos + PROPOSAL_SETTLE_TIME_NANOS)
                             + ", timeUntilAccelerationDelayExpiredMS=" + remainingMS(now,
@@ -608,7 +638,9 @@
                             + ", timeUntilFlatDelayExpiredMS=" + remainingMS(now,
                                     mFlatTimestampNanos + PROPOSAL_MIN_TIME_SINCE_FLAT_ENDED_NANOS)
                             + ", timeUntilSwingDelayExpiredMS=" + remainingMS(now,
-                                    mSwingTimestampNanos + PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS));
+                                    mSwingTimestampNanos + PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS)
+                            + ", timeUntilTouchDelayExpiredMS=" + remainingMS(now,
+                                    mTouchEndedTimestampNanos + PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS));
                 }
             }
 
@@ -710,6 +742,12 @@
                 return false;
             }
 
+            // The last touch must have ended sufficiently long ago.
+            if (mTouched || now < mTouchEndedTimestampNanos
+                    + PROPOSAL_MIN_TIME_SINCE_TOUCH_END_NANOS) {
+                return false;
+            }
+
             // Looks good!
             return true;
         }
@@ -796,5 +834,14 @@
         private float remainingMS(long now, long until) {
             return now >= until ? 0 : (until - now) * 0.000001f;
         }
+
+        private void onTouchStartLocked() {
+            mTouched = true;
+        }
+
+        private void onTouchEndLocked(long whenElapsedNanos) {
+            mTouched = false;
+            mTouchEndedTimestampNanos = whenElapsedNanos;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/power/DeviceIdleController.java
similarity index 84%
rename from services/core/java/com/android/server/DeviceIdleController.java
rename to services/core/java/com/android/server/power/DeviceIdleController.java
index 062992d..dd00446 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/power/DeviceIdleController.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.server.power;
 
 import android.app.AlarmManager;
 import android.app.PendingIntent;
@@ -30,12 +30,16 @@
 import android.hardware.display.DisplayManager;
 import android.net.INetworkPolicyManager;
 import android.os.Binder;
+import android.os.PowerManager;
+import android.os.PowerManagerInternal;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.TimeUtils;
 import android.view.Display;
 import com.android.internal.app.IBatteryStats;
+import com.android.server.SystemService;
 import com.android.server.am.BatteryStatsService;
 
 import java.io.FileDescriptor;
@@ -60,6 +64,11 @@
      */
     private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L;
     /**
+     * This is the time, after seeing motion, that we wait after becoming inactive from
+     * that until we start looking for motion again.
+     */
+    private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L;
+    /**
      * This is the time, after the inactive timeout elapses, that we will wait looking
      * for significant motion until we truly consider the device to be idle.
      */
@@ -94,11 +103,13 @@
 
     private AlarmManager mAlarmManager;
     private IBatteryStats mBatteryStats;
+    private PowerManagerInternal mLocalPowerManager;
     private INetworkPolicyManager mNetworkPolicyManager;
     private DisplayManager mDisplayManager;
     private SensorManager mSensorManager;
     private Sensor mSigMotionSensor;
     private PendingIntent mAlarmIntent;
+    private Intent mIdleIntent;
     private Display mCurDisplay;
     private boolean mScreenOn;
     private boolean mCharging;
@@ -124,6 +135,7 @@
 
     private int mState;
 
+    private long mInactiveTimeout;
     private long mNextAlarmTime;
     private long mNextIdlePendingDelay;
     private long mNextIdleDelay;
@@ -181,6 +193,7 @@
         synchronized (this) {
             mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
             mBatteryStats = BatteryStatsService.getService();
+            mLocalPowerManager = getLocalService(PowerManagerInternal.class);
             mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
                                 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
             mDisplayManager = (DisplayManager) getContext().getSystemService(
@@ -193,6 +206,9 @@
                     .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
 
+            mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+            mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+
             IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_BATTERY_CHANGED);
             filter.addAction(ACTION_STEP_IDLE_STATE);
@@ -205,6 +221,7 @@
             // a battery update the next time the level drops.
             mCharging = true;
             mState = STATE_ACTIVE;
+            mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT;
             updateDisplayLocked();
         }
 
@@ -238,12 +255,17 @@
 
     void becomeActiveLocked() {
         if (mState != STATE_ACTIVE) {
+            mLocalPowerManager.setDeviceIdleMode(false);
             try {
                 mNetworkPolicyManager.setDeviceIdleMode(false);
                 mBatteryStats.noteDeviceIdleMode(false, true, false);
             } catch (RemoteException e) {
             }
+            if (mState == STATE_IDLE) {
+                getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+            }
             mState = STATE_ACTIVE;
+            mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT;
             mNextIdlePendingDelay = 0;
             mNextIdleDelay = 0;
             cancelAlarmLocked();
@@ -256,7 +278,9 @@
             // Screen has turned off; we are now going to become inactive and start
             // waiting to see if we will ultimately go idle.
             mState = STATE_INACTIVE;
-            scheduleAlarmLocked(DEFAULT_INACTIVE_TIMEOUT, false);
+            mNextIdlePendingDelay = 0;
+            mNextIdleDelay = 0;
+            scheduleAlarmLocked(mInactiveTimeout, false);
         }
     }
 
@@ -283,11 +307,13 @@
                     mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT;
                 }
                 mState = STATE_IDLE;
+                mLocalPowerManager.setDeviceIdleMode(true);
                 try {
                     mNetworkPolicyManager.setDeviceIdleMode(true);
                     mBatteryStats.noteDeviceIdleMode(true, false, false);
                 } catch (RemoteException e) {
                 }
+                getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
                 break;
             case STATE_IDLE:
                 // We have been idling long enough, now it is time to do some work.
@@ -297,11 +323,13 @@
                     mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT;
                 }
                 mState = STATE_IDLE_PENDING;
+                mLocalPowerManager.setDeviceIdleMode(false);
                 try {
                     mNetworkPolicyManager.setDeviceIdleMode(false);
                     mBatteryStats.noteDeviceIdleMode(false, false, false);
                 } catch (RemoteException e) {
                 }
+                getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
                 break;
         }
     }
@@ -313,13 +341,18 @@
         // state to wait again for no motion.  Note that we only monitor for significant
         // motion after moving out of the inactive state, so no need to worry about that.
         if (mState != STATE_ACTIVE) {
-            mState = STATE_INACTIVE;
+            mLocalPowerManager.setDeviceIdleMode(false);
             try {
                 mNetworkPolicyManager.setDeviceIdleMode(false);
                 mBatteryStats.noteDeviceIdleMode(false, false, true);
             } catch (RemoteException e) {
             }
-            stepIdleStateLocked();
+            if (mState == STATE_IDLE) {
+                getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+            }
+            mState = STATE_ACTIVE;
+            mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT;
+            becomeInactiveIfAppropriateLocked();
         }
     }
 
@@ -399,26 +432,30 @@
             }
         }
 
-        pw.print("  mSigMotionSensor="); pw.println(mSigMotionSensor);
-        pw.print("  mCurDisplay="); pw.println(mCurDisplay);
-        pw.print("  mScreenOn="); pw.println(mScreenOn);
-        pw.print("  mCharging="); pw.println(mCharging);
-        pw.print("  mSigMotionActive="); pw.println(mSigMotionActive);
-        pw.print("  mState="); pw.println(stateToString(mState));
-        if (mNextAlarmTime != 0) {
-            pw.print("  mNextAlarmTime=");
-            TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
+        synchronized (this) {
+            pw.print("  mSigMotionSensor="); pw.println(mSigMotionSensor);
+            pw.print("  mCurDisplay="); pw.println(mCurDisplay);
+            pw.print("  mScreenOn="); pw.println(mScreenOn);
+            pw.print("  mCharging="); pw.println(mCharging);
+            pw.print("  mSigMotionActive="); pw.println(mSigMotionActive);
+            pw.print("  mState="); pw.println(stateToString(mState));
+            pw.print("  mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
             pw.println();
-        }
-        if (mNextIdlePendingDelay != 0) {
-            pw.print("  mNextIdlePendingDelay=");
-            TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
-            pw.println();
-        }
-        if (mNextIdleDelay != 0) {
-            pw.print("  mNextIdleDelay=");
-            TimeUtils.formatDuration(mNextIdleDelay, pw);
-            pw.println();
+            if (mNextAlarmTime != 0) {
+                pw.print("  mNextAlarmTime=");
+                TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
+                pw.println();
+            }
+            if (mNextIdlePendingDelay != 0) {
+                pw.print("  mNextIdlePendingDelay=");
+                TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
+                pw.println();
+            }
+            if (mNextIdleDelay != 0) {
+                pw.print("  mNextIdleDelay=");
+                TimeUtils.formatDuration(mNextIdleDelay, pw);
+                pw.println();
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 1349926..c48367e 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -78,6 +78,7 @@
     private static final int MSG_USER_ACTIVITY = 1;
     private static final int MSG_BROADCAST = 2;
     private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
+    private static final int MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED = 4;
 
     private final Object mLock = new Object();
 
@@ -92,6 +93,7 @@
     private final NotifierHandler mHandler;
     private final Intent mScreenOnIntent;
     private final Intent mScreenOffIntent;
+    private final Intent mScreenBrightnessBoostIntent;
 
     // The current interactive state.
     private int mActualInteractiveState;
@@ -128,6 +130,10 @@
         mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
         mScreenOffIntent.addFlags(
                 Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+        mScreenBrightnessBoostIntent =
+                new Intent(PowerManager.ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED);
+        mScreenBrightnessBoostIntent.addFlags(
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
 
         // Initialize interactive state for battery stats.
         try {
@@ -349,6 +355,19 @@
     }
 
     /**
+     * Called when screen brightness boost begins or ends.
+     */
+    public void onScreenBrightnessBoostChanged() {
+        if (DEBUG) {
+            Slog.d(TAG, "onScreenBrightnessBoostChanged");
+        }
+
+        mSuspendBlocker.acquire();
+        Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED);
+        msg.setAsynchronous(true);
+        mHandler.sendMessage(msg);
+    }
+    /**
      * Called when there has been user activity.
      */
     public void onUserActivity(int event, int uid) {
@@ -457,6 +476,22 @@
         }
     }
 
+    private void sendBrightnessBoostChangedBroadcast() {
+        if (DEBUG) {
+            Slog.d(TAG, "Sending brightness boost changed broadcast.");
+        }
+
+        mContext.sendOrderedBroadcastAsUser(mScreenBrightnessBoostIntent, UserHandle.ALL, null,
+                mScreeBrightnessBoostChangedDone, mHandler, 0, null, null);
+    }
+
+    private final BroadcastReceiver mScreeBrightnessBoostChangedDone = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mSuspendBlocker.release();
+        }
+    };
+
     private void sendWakeUpBroadcast() {
         if (DEBUG) {
             Slog.d(TAG, "Sending wake up broadcast.");
@@ -539,6 +574,9 @@
                 case MSG_WIRELESS_CHARGING_STARTED:
                     playWirelessChargingStartedSound();
                     break;
+                case MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED:
+                    sendBrightnessBoostChangedBroadcast();
+                    break;
             }
         }
     }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9e373b7..6c8959c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -420,6 +420,9 @@
     // True if the battery level is currently considered low.
     private boolean mBatteryLevelLow;
 
+    // True if we are currently in device idle mode.
+    private boolean mDeviceIdleMode;
+
     // True if theater mode is enabled
     private boolean mTheaterModeEnabled;
 
@@ -1900,6 +1903,7 @@
                     }
                 }
                 mScreenBrightnessBoostInProgress = false;
+                mNotifier.onScreenBrightnessBoostChanged();
                 userActivityNoUpdateLocked(now,
                         PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
             }
@@ -2178,6 +2182,12 @@
         }
     }
 
+    private boolean isDeviceIdleModeInternal() {
+        synchronized (mLock) {
+            return mDeviceIdleMode;
+        }
+    }
+
     private void handleBatteryStateChangedLocked() {
         mDirty |= DIRTY_BATTERY_STATE;
         updatePowerStateLocked();
@@ -2275,7 +2285,10 @@
 
             Slog.i(TAG, "Brightness boost activated (uid " + uid +")...");
             mLastScreenBrightnessBoostTime = eventTime;
-            mScreenBrightnessBoostInProgress = true;
+            if (!mScreenBrightnessBoostInProgress) {
+                mScreenBrightnessBoostInProgress = true;
+                mNotifier.onScreenBrightnessBoostChanged();
+            }
             mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;
 
             userActivityNoUpdateLocked(eventTime,
@@ -2284,6 +2297,12 @@
         }
     }
 
+    private boolean isScreenBrightnessBoostedInternal() {
+        synchronized (mLock) {
+            return mScreenBrightnessBoostInProgress;
+        }
+    }
+
     /**
      * Called when a screen brightness boost timeout has occurred.
      *
@@ -3050,6 +3069,16 @@
             }
         }
 
+        @Override // Binder call
+        public boolean isDeviceIdleMode() {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return isDeviceIdleModeInternal();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         /**
          * Reboots the device.
          *
@@ -3218,6 +3247,16 @@
         }
 
         @Override // Binder call
+        public boolean isScreenBrightnessBoosted() {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return isScreenBrightnessBoostedInternal();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -3295,5 +3334,12 @@
                 mLowPowerModeListeners.add(listener);
             }
         }
+
+        @Override
+        public void setDeviceIdleMode(boolean enabled) {
+            synchronized (mLock) {
+                mDeviceIdleMode = enabled;
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 0109313..dec195d 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -272,13 +272,14 @@
         alarmFilter.addDataScheme(mAlarmIntent.getScheme());
         final String pathUri = mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME);
         alarmFilter.addDataPath(pathUri, PatternMatcher.PATTERN_LITERAL);
-        mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null);
 
         // Schedules a restart for when connecting times out. If the connection succeeds,
         // the restart is canceled in mCallback's onConnected.
         scheduleRestart();
         mBound = context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user);
-        if (!mBound) {
+        if (mBound) {
+            mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null);
+        } else {
             Log.e(TAG, "Can't bind to TrustAgent " + mName.flattenToShortString());
         }
     }
@@ -398,7 +399,6 @@
     }
 
     public void destroy() {
-        mContext.unregisterReceiver(mBroadcastReceiver);
         mHandler.removeMessages(MSG_RESTART_TIMEOUT);
 
         if (!mBound) {
@@ -408,6 +408,7 @@
         mTrustManagerService.mArchive.logAgentStopped(mUserId, mName);
         mContext.unbindService(mConnection);
         mBound = false;
+        mContext.unregisterReceiver(mBroadcastReceiver);
         mTrustAgentService = null;
         mSetTrustAgentFeaturesToken = null;
         mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 5375bfc..152370a 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1341,6 +1341,108 @@
         }
 
         @Override
+        public void timeShiftPause(IBinder sessionToken, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "timeShiftPause");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .timeShiftPause();
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in timeShiftPause", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void timeShiftResume(IBinder sessionToken, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "timeShiftResume");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .timeShiftResume();
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in timeShiftResume", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void timeShiftSeekTo(IBinder sessionToken, long timeMs, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "timeShiftSeekTo");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .timeShiftSeekTo(timeMs);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in timeShiftSeekTo", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void timeShiftSetPlaybackRate(IBinder sessionToken, float rate, int audioMode,
+                int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "timeShiftSetPlaybackRate");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .timeShiftSetPlaybackRate(rate, audioMode);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in timeShiftSetPlaybackRate", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void timeShiftTrackCurrentPosition(IBinder sessionToken, boolean enabled,
+                int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "timeShiftTrackCurrentPosition");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .timeShiftTrackCurrentPosition(enabled);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in timeShiftTrackCurrentPosition", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public List<TvInputHardwareInfo> getHardwareList() throws RemoteException {
             if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -2144,6 +2246,58 @@
                 }
             }
         }
+
+        @Override
+        public void onTimeShiftStatusChanged(int status) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onTimeShiftStatusChanged()");
+                }
+                if (mSessionState.session == null || mSessionState.client == null) {
+                    return;
+                }
+                try {
+                    mSessionState.client.onTimeShiftStatusChanged(status, mSessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onTimeShiftStatusChanged", e);
+                }
+            }
+        }
+
+        @Override
+        public void onTimeShiftStartPositionChanged(long timeMs) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onTimeShiftStartPositionChanged()");
+                }
+                if (mSessionState.session == null || mSessionState.client == null) {
+                    return;
+                }
+                try {
+                    mSessionState.client.onTimeShiftStartPositionChanged(timeMs, mSessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onTimeShiftStartPositionChanged", e);
+                }
+            }
+        }
+
+        @Override
+        public void onTimeShiftCurrentPositionChanged(long timeMs) {
+            synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onTimeShiftCurrentPositionChanged()");
+                }
+                if (mSessionState.session == null || mSessionState.client == null) {
+                    return;
+                }
+                try {
+                    mSessionState.client.onTimeShiftCurrentPositionChanged(timeMs,
+                            mSessionState.seq);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in onTimeShiftCurrentPositionChanged", e);
+                }
+            }
+        }
     }
 
     private static final class WatchLogHandler extends Handler {
diff --git a/services/core/java/com/android/server/updates/TZInfoInstallReceiver.java b/services/core/java/com/android/server/updates/TZInfoInstallReceiver.java
deleted file mode 100644
index 2fe68f8..0000000
--- a/services/core/java/com/android/server/updates/TZInfoInstallReceiver.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.updates;
-
-import android.util.Base64;
-
-import java.io.IOException;
-
-public class TZInfoInstallReceiver extends ConfigUpdateInstallReceiver {
-
-    public TZInfoInstallReceiver() {
-        super("/data/misc/zoneinfo/", "tzdata", "metadata/", "version");
-    }
-
-    @Override
-    protected void install(byte[] encodedContent, int version) throws IOException {
-        super.install(Base64.decode(encodedContent, Base64.DEFAULT), version);
-    }
-}
diff --git a/services/core/java/com/android/server/updates/TzDataInstallReceiver.java b/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
new file mode 100644
index 0000000..b260e4e
--- /dev/null
+++ b/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
@@ -0,0 +1,54 @@
+/*
+ * 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.updates;
+
+import android.util.Slog;
+
+import java.io.File;
+import java.io.IOException;
+import libcore.tzdata.update.TzDataBundleInstaller;
+
+/**
+ * An install receiver responsible for installing timezone data updates.
+ */
+public class TzDataInstallReceiver extends ConfigUpdateInstallReceiver {
+
+    private static final String TAG = "TZDataInstallReceiver";
+
+    private static final File TZ_DATA_DIR = new File("/data/misc/zoneinfo");
+    private static final String UPDATE_DIR_NAME = TZ_DATA_DIR.getPath() + "/updates/";
+    private static final String UPDATE_METADATA_DIR_NAME = "metadata/";
+    private static final String UPDATE_VERSION_FILE_NAME = "version";
+    private static final String UPDATE_CONTENT_FILE_NAME = "tzdata_bundle.zip";
+
+    private final TzDataBundleInstaller installer;
+
+    public TzDataInstallReceiver() {
+        super(UPDATE_DIR_NAME, UPDATE_CONTENT_FILE_NAME, UPDATE_METADATA_DIR_NAME,
+                UPDATE_VERSION_FILE_NAME);
+        installer = new TzDataBundleInstaller(TAG, TZ_DATA_DIR);
+    }
+
+    @Override
+    protected void install(byte[] content, int version) throws IOException {
+        boolean valid = installer.install(content);
+        Slog.i(TAG, "Timezone data install valid for this device: " + valid);
+        // Even if !valid, we call super.install(). Only in the event of an exception should we
+        // not. If we didn't do this we could attempt to install repeatedly.
+        super.install(content, version);
+    }
+}
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index a58f30d..55ec9fc 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -242,7 +242,7 @@
     }
 
     // This must be called while inside a transaction.
-    boolean stepAnimationLocked(long currentTime) {
+    boolean stepAnimationLocked(long currentTime, final int displayId) {
         if (mService.okToDisplay()) {
             // We will run animations as long as the display isn't frozen.
 
@@ -292,7 +292,7 @@
         }
 
         mAnimator.setAppLayoutChanges(this, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
-                "AppWindowToken");
+                "AppWindowToken", displayId);
 
         clearAnimation();
         animating = false;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b8f26c9..34120a0 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -78,7 +78,7 @@
         }
         if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: removing taskId=" + mTaskId
                 + " from stack=" + mStack);
-        EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
+        EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask");
         if (mStack != null) {
             mStack.removeTask(this);
         }
@@ -88,7 +88,7 @@
     boolean removeAppToken(AppWindowToken wtoken) {
         boolean removed = mAppTokens.remove(wtoken);
         if (mAppTokens.size() == 0) {
-            EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, mTaskId,
+            EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId,
                     "removeAppToken: last token");
             if (mDeferRemoval) {
                 removeLocked();
@@ -107,6 +107,11 @@
         }
     }
 
+    boolean showWhenLocked() {
+        final int tokensCount = mAppTokens.size();
+        return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showWhenLocked;
+    }
+
     @Override
     public String toString() {
         return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b61a6f7..e845f83 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -275,21 +275,29 @@
         return false;
     }
 
+    void addTask(Task task, boolean toTop) {
+        addTask(task, toTop, task.showWhenLocked());
+    }
+
     /**
      * Put a Task in this stack. Used for adding and moving.
      * @param task The task to add.
      * @param toTop Whether to add it to the top or bottom.
+     * @param showWhenLocked Whether to show the task when the device is locked
+     *                       regardless of the current user.
      */
-    void addTask(Task task, boolean toTop) {
+    void addTask(Task task, boolean toTop, boolean showWhenLocked) {
         int stackNdx;
         if (!toTop) {
             stackNdx = 0;
         } else {
             stackNdx = mTasks.size();
-            if (!mService.isCurrentProfileLocked(task.mUserId)) {
+            if (!showWhenLocked && !mService.isCurrentProfileLocked(task.mUserId)) {
                 // Place the task below all current user tasks.
                 while (--stackNdx >= 0) {
-                    if (!mService.isCurrentProfileLocked(mTasks.get(stackNdx).mUserId)) {
+                    final Task tmpTask = mTasks.get(stackNdx);
+                    if (!tmpTask.showWhenLocked()
+                            || !mService.isCurrentProfileLocked(tmpTask.mUserId)) {
                         break;
                     }
                 }
@@ -490,7 +498,7 @@
         int top = mTasks.size();
         for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
             Task task = mTasks.get(taskNdx);
-            if (mService.isCurrentProfileLocked(task.mUserId)) {
+            if (mService.isCurrentProfileLocked(task.mUserId) || task.showWhenLocked()) {
                 mTasks.remove(taskNdx);
                 mTasks.add(task);
                 --top;
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 46fa38a..897b865 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -159,13 +159,13 @@
                     final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator;
                     final boolean wasAnimating = appAnimator.animation != null
                             && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
-                    if (appAnimator.stepAnimationLocked(mCurrentTime)) {
+                    if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
                         mAnimating = mAppWindowAnimating = true;
                     } else if (wasAnimating) {
                         // stopped animating, do one more pass through the layout
                         setAppLayoutChanges(appAnimator,
                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                                "appToken " + appAnimator.mAppToken + " done");
+                                "appToken " + appAnimator.mAppToken + " done", displayId);
                         if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
                                 "updateWindowsApps...: done animating " + appAnimator.mAppToken);
                     }
@@ -178,12 +178,12 @@
                 final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
                 final boolean wasAnimating = appAnimator.animation != null
                         && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
-                if (appAnimator.stepAnimationLocked(mCurrentTime)) {
+                if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
                     mAnimating = mAppWindowAnimating = true;
                 } else if (wasAnimating) {
                     // stopped animating, do one more pass through the layout
                     setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                        "exiting appToken " + appAnimator.mAppToken + " done");
+                        "exiting appToken " + appAnimator.mAppToken + " done", displayId);
                     if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
                             "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
                 }
@@ -575,11 +575,11 @@
                             // This will set mOrientationChangeComplete and cause a pass through layout.
                             setAppLayoutChanges(appAnimator,
                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
-                                    "testTokenMayBeDrawnLocked: freezingScreen");
+                                    "testTokenMayBeDrawnLocked: freezingScreen", displayId);
                         } else {
                             setAppLayoutChanges(appAnimator,
                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
-                                    "testTokenMayBeDrawnLocked");
+                                    "testTokenMayBeDrawnLocked", displayId);
 
                             // We can now show all of the drawn windows!
                             if (!mService.mOpeningApps.contains(wtoken)) {
@@ -792,28 +792,30 @@
         if (displayId < 0) {
             return 0;
         }
-        return mService.getDisplayContentLocked(displayId).pendingLayoutChanges;
+        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+        return (displayContent != null) ? displayContent.pendingLayoutChanges : 0;
     }
 
     void setPendingLayoutChanges(final int displayId, final int changes) {
-        if (displayId >= 0) {
-            mService.getDisplayContentLocked(displayId).pendingLayoutChanges |= changes;
+        if (displayId < 0) {
+            return;
+        }
+        final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
+        if (displayContent != null) {
+            displayContent.pendingLayoutChanges |= changes;
         }
     }
 
-    void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) {
-        // Used to track which displays layout changes have been done.
-        SparseIntArray displays = new SparseIntArray(2);
+    void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason,
+            final int displayId) {
         WindowList windows = appAnimator.mAppToken.allAppWindows;
         for (int i = windows.size() - 1; i >= 0; i--) {
-            final int displayId = windows.get(i).getDisplayId();
-            if (displayId >= 0 && displays.indexOfKey(displayId) < 0) {
+            if (displayId == windows.get(i).getDisplayId()) {
                 setPendingLayoutChanges(displayId, changes);
                 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                    mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId));
+                    mService.debugLayoutRepeats(reason, getPendingLayoutChanges(displayId));
                 }
-                // Keep from processing this display again.
-                displays.put(displayId, changes);
+                break;
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1dc027a..7fab5a6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -617,8 +617,8 @@
     static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
     boolean mAnimateWallpaperWithTarget;
 
-    // We give a wallpaper up to 1000ms to finish drawing before playing app transitions.
-    static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 1000;
+    // We give a wallpaper up to 500ms to finish drawing before playing app transitions.
+    static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500;
     static final int WALLPAPER_DRAW_NORMAL = 0;
     static final int WALLPAPER_DRAW_PENDING = 1;
     static final int WALLPAPER_DRAW_TIMEOUT = 2;
@@ -3620,7 +3620,7 @@
         EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
         Task task = new Task(taskId, stack, userId, this);
         mTaskIdToTask.put(taskId, task);
-        stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */);
+        stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */, atoken.showWhenLocked);
         return task;
     }
 
@@ -3720,10 +3720,8 @@
         } else {
             // TODO(multidisplay): Change to the correct display.
             final WindowList windows = getDefaultWindowListLocked();
-            int pos = windows.size() - 1;
-            while (pos >= 0) {
+            for (int pos = windows.size() - 1; pos >= 0; --pos) {
                 WindowState win = windows.get(pos);
-                pos--;
                 if (win.mAppToken != null) {
                     // We hit an application window. so the orientation will be determined by the
                     // app window. No point in continuing further.
@@ -4173,8 +4171,8 @@
         }
 
         synchronized(mWindowMap) {
-            if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition,
-                    new RuntimeException("here").fillInStackTrace());
+            if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition
+                    + " Callers=" + Debug.getCallers(5));
             if (mAppTransition.isTransitionSet()) {
                 mAppTransition.setReady();
                 final long origId = Binder.clearCallingIdentity();
@@ -4610,22 +4608,26 @@
             if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" +
                     token + ", visible=" + visible + "): " + mAppTransition +
                     " hidden=" + wtoken.hidden + " hiddenRequested=" +
-                    wtoken.hiddenRequested, HIDE_STACK_CRAWLS ?
-                            null : new RuntimeException("here").fillInStackTrace());
+                    wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
+
+            mOpeningApps.remove(wtoken);
+            mClosingApps.remove(wtoken);
+            wtoken.waitingToShow = wtoken.waitingToHide = false;
+            wtoken.hiddenRequested = !visible;
+
+            mOpeningApps.remove(wtoken);
+            mClosingApps.remove(wtoken);
+            wtoken.waitingToShow = wtoken.waitingToHide = false;
+            wtoken.hiddenRequested = !visible;
 
             // If we are preparing an app transition, then delay changing
             // the visibility of this token until we execute that transition.
             if (okToDisplay() && mAppTransition.isTransitionSet()) {
-                wtoken.hiddenRequested = !visible;
-
                 if (!wtoken.startingDisplayed) {
                     if (DEBUG_APP_TRANSITIONS) Slog.v(
                             TAG, "Setting dummy animation on: " + wtoken);
                     wtoken.mAppAnimator.setDummyAnimation();
                 }
-                mOpeningApps.remove(wtoken);
-                mClosingApps.remove(wtoken);
-                wtoken.waitingToShow = wtoken.waitingToHide = false;
                 wtoken.inPendingTransaction = true;
                 if (visible) {
                     mOpeningApps.add(wtoken);
@@ -9062,6 +9064,7 @@
                     goodToGo = false;
                 }
             }
+
             if (goodToGo && isWallpaperVisible(mWallpaperTarget)) {
                 boolean wallpaperGoodToGo = true;
                 for (int curTokenIndex = mWallpaperTokens.size() - 1;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f94ed77..db3268d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1490,6 +1490,11 @@
             mOrientationChanging = false;
             mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
                     - mService.mDisplayFreezeTime);
+            // We are assuming the hosting process is dead or in a zombie state.
+            Slog.w(TAG, "Failed to report 'resized' to the client of " + this
+                    + ", removing this window.");
+            mService.mPendingRemove.add(this);
+            mService.requestTraversalLocked();
         }
     }
 
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 7b74e91..6448de2 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -10,6 +10,7 @@
     $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
     $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_fingerprint_FingerprintService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \
     $(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \
     $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \
diff --git a/services/core/jni/com_android_server_UsbMidiDevice.cpp b/services/core/jni/com_android_server_UsbMidiDevice.cpp
index 94853b8..cb70144 100644
--- a/services/core/jni/com_android_server_UsbMidiDevice.cpp
+++ b/services/core/jni/com_android_server_UsbMidiDevice.cpp
@@ -94,9 +94,20 @@
     return fds;
 }
 
+static void
+android_server_UsbMidiDevice_close(JNIEnv *env, jobject /* thiz */, jobjectArray fds)
+{
+    int count = env->GetArrayLength(fds);
+    for (int i = 0; i < count; i++) {
+        jobject fd = env->GetObjectArrayElement(fds, i);
+        close(jniGetFDFromFileDescriptor(env, fd));
+    }
+}
+
 static JNINativeMethod method_table[] = {
     { "nativeGetSubdeviceCount", "(II)I", (void*)android_server_UsbMidiDevice_get_subdevice_count },
     { "nativeOpen", "(III)[Ljava/io/FileDescriptor;", (void*)android_server_UsbMidiDevice_open },
+    { "nativeClose", "([Ljava/io/FileDescriptor;)V", (void*)android_server_UsbMidiDevice_close },
 };
 
 int register_android_server_UsbMidiDevice(JNIEnv *env)
diff --git a/core/jni/android_server_FingerprintManager.cpp b/services/core/jni/com_android_server_fingerprint_FingerprintService.cpp
similarity index 82%
rename from core/jni/android_server_FingerprintManager.cpp
rename to services/core/jni/com_android_server_fingerprint_FingerprintService.cpp
index 853425c..5d59234 100644
--- a/core/jni/android_server_FingerprintManager.cpp
+++ b/services/core/jni/com_android_server_fingerprint_FingerprintService.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "Fingerprint-JNI"
 
 #include "JNIHelp.h"
+#include <inttypes.h>
 
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
@@ -47,14 +48,15 @@
 
 class CallbackHandler : public MessageHandler {
     int type;
-    int arg1, arg2;
+    int arg1, arg2, arg3;
 public:
-    CallbackHandler(int type, int arg1, int arg2) : type(type), arg1(arg1), arg2(arg2) { }
+    CallbackHandler(int type, int arg1, int arg2, int arg3)
+        : type(type), arg1(arg1), arg2(arg2), arg3(arg3) { }
 
     virtual void handleMessage(const Message& message) {
         //ALOG(LOG_VERBOSE, LOG_TAG, "hal_notify(msg=%d, arg1=%d, arg2=%d)\n", msg.type, arg1, arg2);
         JNIEnv* env = AndroidRuntime::getJNIEnv();
-        env->CallVoidMethod(gCallback, gFingerprintServiceClassInfo.notify, type, arg1, arg2);
+        env->CallVoidMethod(gCallback, gFingerprintServiceClassInfo.notify, type, arg1, arg2, arg3);
     }
 };
 
@@ -62,6 +64,7 @@
 static void hal_notify_callback(fingerprint_msg_t msg) {
     uint32_t arg1 = 0;
     uint32_t arg2 = 0;
+    uint32_t arg3 = 0;
     switch (msg.type) {
         case FINGERPRINT_ERROR:
             arg1 = msg.data.error;
@@ -71,13 +74,16 @@
             break;
         case FINGERPRINT_PROCESSED:
             arg1 = msg.data.processed.finger.fid;
+            arg2 = msg.data.processed.finger.gid;
             break;
         case FINGERPRINT_TEMPLATE_ENROLLING:
             arg1 = msg.data.enroll.finger.fid;
-            arg2 = msg.data.enroll.samples_remaining;
+            arg2 = msg.data.enroll.finger.gid;
+            arg3 = msg.data.enroll.samples_remaining;
             break;
         case FINGERPRINT_TEMPLATE_REMOVED:
             arg1 = msg.data.removed.finger.fid;
+            arg2 = msg.data.removed.finger.gid;
             break;
         default:
             ALOGE("fingerprint: invalid msg: %d", msg.type);
@@ -86,7 +92,7 @@
     // This call potentially comes in on a thread not owned by us. Hand it off to our
     // looper so it runs on our thread when calling back to FingerprintService.
     // CallbackHandler object is reference-counted, so no cleanup necessary.
-    gLooper->sendMessage(new CallbackHandler(msg.type, arg1, arg2), Message());
+    gLooper->sendMessage(new CallbackHandler(msg.type, arg1, arg2, arg3), Message());
 }
 
 static void nativeInit(JNIEnv *env, jobject clazz, jobject mQueue, jobject callbackObj) {
@@ -95,9 +101,15 @@
     gLooper = android_os_MessageQueue_getMessageQueue(env, mQueue)->getLooper();
 }
 
-static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout) {
-    ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnroll()\n");
-    int ret = gContext.device->enroll(gContext.device, 0, timeout);
+static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout, jint groupId) {
+    ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnroll(gid=%d, timeout=%d)\n", groupId, timeout);
+    int ret = gContext.device->enroll(gContext.device, groupId, timeout);
+    return reinterpret_cast<jint>(ret);
+}
+
+static jint nativeAuthenticate(JNIEnv* env, jobject clazz, jlong sessionId, jint groupId) {
+    ALOG(LOG_VERBOSE, LOG_TAG, "nativeAuthenticate(sid=%" PRId64 ", gid=%d)\n", sessionId, groupId);
+    int ret = gContext.device->authenticate(gContext.device, sessionId, groupId);
     return reinterpret_cast<jint>(ret);
 }
 
@@ -107,11 +119,11 @@
     return reinterpret_cast<jint>(ret);
 }
 
-static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerprintId) {
-    ALOG(LOG_VERBOSE, LOG_TAG, "nativeRemove(%d)\n", fingerprintId);
+static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerId, jint groupId) {
+    ALOG(LOG_VERBOSE, LOG_TAG, "nativeRemove(fid=%d, gid=%d)\n", fingerId, groupId);
     fingerprint_finger_id_t finger;
-    finger.gid = 0;
-    finger.fid = fingerprintId;
+    finger.fid = fingerId;
+    finger.gid = groupId;
     int ret = gContext.device->remove(gContext.device, finger);
     return reinterpret_cast<jint>(ret);
 }
@@ -172,9 +184,10 @@
 
 // TODO: clean up void methods
 static const JNINativeMethod g_methods[] = {
-    { "nativeEnroll", "(I)I", (void*)nativeEnroll },
+    { "nativeAuthenticate", "(JI)I", (void*)nativeAuthenticate },
+    { "nativeEnroll", "(II)I", (void*)nativeEnroll },
     { "nativeEnrollCancel", "()I", (void*)nativeEnrollCancel },
-    { "nativeRemove", "(I)I", (void*)nativeRemove },
+    { "nativeRemove", "(II)I", (void*)nativeRemove },
     { "nativeOpenHal", "()I", (void*)nativeOpenHal },
     { "nativeCloseHal", "()I", (void*)nativeCloseHal },
     { "nativeInit","(Landroid/os/MessageQueue;"
@@ -185,7 +198,7 @@
     jclass clazz = FindClassOrDie(env, FINGERPRINT_SERVICE);
     gFingerprintServiceClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
     gFingerprintServiceClassInfo.notify =
-            GetMethodIDOrDie(env, gFingerprintServiceClassInfo.clazz,"notify", "(III)V");
+            GetMethodIDOrDie(env, gFingerprintServiceClassInfo.clazz,"notify", "(IIII)V");
     int result = RegisterMethodsOrDie(env, FINGERPRINT_SERVICE, g_methods, NELEM(g_methods));
     ALOG(LOG_VERBOSE, LOG_TAG, "FingerprintManager JNI ready.\n");
     return result;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index ea59d4b..c766183 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -110,9 +110,9 @@
     /**
      * Creates an instance of the device owner object with the device initializer set.
      */
-    static DeviceOwner createWithDeviceInitializer(String packageName, String ownerName) {
+    static DeviceOwner createWithDeviceInitializer(ComponentName admin, String ownerName) {
         DeviceOwner owner = new DeviceOwner();
-        owner.mDeviceInitializer = new OwnerInfo(ownerName, packageName);
+        owner.mDeviceInitializer = new OwnerInfo(ownerName, admin);
         return owner;
     }
 
@@ -141,6 +141,10 @@
         mDeviceOwner = null;
     }
 
+    ComponentName getDeviceInitializerComponent() {
+        return mDeviceInitializer.admin;
+    }
+
     String getDeviceInitializerPackageName() {
         return mDeviceInitializer != null ? mDeviceInitializer.packageName : null;
     }
@@ -149,8 +153,8 @@
         return mDeviceInitializer != null ? mDeviceInitializer.name : null;
     }
 
-    void setDeviceInitializer(String packageName, String ownerName) {
-        mDeviceInitializer = new OwnerInfo(ownerName, packageName);
+    void setDeviceInitializer(ComponentName admin, String ownerName) {
+        mDeviceInitializer = new OwnerInfo(ownerName, admin);
     }
 
     void clearDeviceInitializer() {
@@ -235,7 +239,17 @@
                 } else if (tag.equals(TAG_DEVICE_INITIALIZER)) {
                     String name = parser.getAttributeValue(null, ATTR_NAME);
                     String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
-                    mDeviceInitializer = new OwnerInfo(name, packageName);
+                    String initializerComponentStr =
+                            parser.getAttributeValue(null, ATTR_COMPONENT_NAME);
+                    ComponentName admin =
+                            ComponentName.unflattenFromString(initializerComponentStr);
+                    if (admin != null) {
+                        mDeviceInitializer = new OwnerInfo(name, admin);
+                    } else {
+                        mDeviceInitializer = new OwnerInfo(name, packageName);
+                        Slog.e(TAG, "Error parsing device-owner file. Bad component name " +
+                                initializerComponentStr);
+                    }
                 } else if (tag.equals(TAG_PROFILE_OWNER)) {
                     String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
                     String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME);
@@ -303,6 +317,10 @@
                 if (mDeviceInitializer.name != null) {
                     out.attribute(null, ATTR_NAME, mDeviceInitializer.name);
                 }
+                if (mDeviceInitializer.admin != null) {
+                    out.attribute(
+                            null, ATTR_COMPONENT_NAME, mDeviceInitializer.admin.flattenToString());
+                }
                 out.endTag(null, TAG_DEVICE_INITIALIZER);
             }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d07cd98..bb3085e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -78,6 +78,8 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.ContactsContract.QuickContact;
+import android.provider.ContactsInternal;
 import android.provider.Settings;
 import android.security.Credentials;
 import android.security.IKeyChainAliasCallback;
@@ -146,6 +148,8 @@
 
     private static final String LOG_TAG = "DevicePolicyManagerService";
 
+    private static final boolean VERBOSE_LOG = false; // DO NOT SUBMIT WITH TRUE
+
     private static final String DEVICE_POLICIES_XML = "device_policies.xml";
 
     private static final String LOCK_TASK_COMPONENTS_XML = "lock-task-component";
@@ -276,15 +280,12 @@
         long mLastMaximumTimeToLock = -1;
         boolean mUserSetupComplete = false;
 
-        final HashMap<ComponentName, ActiveAdmin> mAdminMap
-                = new HashMap<ComponentName, ActiveAdmin>();
-        final ArrayList<ActiveAdmin> mAdminList
-                = new ArrayList<ActiveAdmin>();
-        final ArrayList<ComponentName> mRemovingAdmins
-                = new ArrayList<ComponentName>();
+        final HashMap<ComponentName, ActiveAdmin> mAdminMap = new HashMap<>();
+        final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
+        final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();
 
         // This is the list of component allowed to start lock task mode.
-        final List<String> mLockTaskPackages = new ArrayList<String>();
+        final List<String> mLockTaskPackages = new ArrayList<>();
 
         ComponentName mRestrictionsProvider;
 
@@ -295,7 +296,7 @@
         }
     }
 
-    final SparseArray<DevicePolicyData> mUserData = new SparseArray<DevicePolicyData>();
+    final SparseArray<DevicePolicyData> mUserData = new SparseArray<>();
 
     Handler mHandler = new Handler();
 
@@ -1140,70 +1141,85 @@
     ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
             throws SecurityException {
         final int callingUid = Binder.getCallingUid();
-        final int userHandle = UserHandle.getUserId(callingUid);
-        final DevicePolicyData policy = getUserData(userHandle);
 
-        List<ActiveAdmin> candidates = new ArrayList<ActiveAdmin>();
+        ActiveAdmin result = getActiveAdminWithPolicyForUidLocked(who, reqPolicy, callingUid);
+        if (result != null) {
+            return result;
+        }
 
-        // Build a list of admins for this uid matching the given ComponentName
+        if (who != null) {
+            final int userId = UserHandle.getUserId(callingUid);
+            final DevicePolicyData policy = getUserData(userId);
+            ActiveAdmin admin = policy.mAdminMap.get(who);
+            if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
+                throw new SecurityException("Admin " + admin.info.getComponent()
+                         + " does not own the device");
+            }
+            if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
+                throw new SecurityException("Admin " + admin.info.getComponent()
+                        + " does not own the profile");
+            }
+            throw new SecurityException("Admin " + admin.info.getComponent()
+                    + " did not specify uses-policy for: "
+                    + admin.info.getTagForPolicy(reqPolicy));
+        } else {
+            throw new SecurityException("No active admin owned by uid "
+                    + Binder.getCallingUid() + " for policy #" + reqPolicy);
+        }
+    }
+
+    private ActiveAdmin getActiveAdminWithPolicyForUidLocked(ComponentName who, int reqPolicy,
+            int uid) {
+        // Try to find an admin which can use reqPolicy
+        final int userId = UserHandle.getUserId(uid);
+        final DevicePolicyData policy = getUserData(userId);
         if (who != null) {
             ActiveAdmin admin = policy.mAdminMap.get(who);
             if (admin == null) {
                 throw new SecurityException("No active admin " + who);
             }
-            if (admin.getUid() != callingUid) {
+            if (admin.getUid() != uid) {
                 throw new SecurityException("Admin " + who + " is not owned by uid "
                         + Binder.getCallingUid());
             }
-            candidates.add(admin);
+            if (isActiveAdminWithPolicyForUserLocked(admin, reqPolicy, userId)) {
+                return admin;
+            }
         } else {
             for (ActiveAdmin admin : policy.mAdminList) {
-                if (admin.getUid() == callingUid) {
-                    candidates.add(admin);
-                }
-            }
-        }
-
-        // Try to find an admin which can use reqPolicy
-        for (ActiveAdmin admin : candidates) {
-            boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
-            boolean ownsProfile = (getProfileOwner(userHandle) != null
-                    && getProfileOwner(userHandle).getPackageName()
-                        .equals(admin.info.getPackageName()));
-            boolean ownsInitialization = isDeviceInitializer(admin.info.getPackageName())
-                    && !hasUserSetupCompleted(userHandle);
-
-            if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
-                if (ownsDevice || (userHandle == UserHandle.USER_OWNER && ownsInitialization)) {
-                    return admin;
-                }
-            } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
-                if (ownsDevice || ownsProfile || ownsInitialization) {
-                    return admin;
-                }
-            } else {
-                if (admin.info.usesPolicy(reqPolicy)) {
+                if (admin.getUid() == uid && isActiveAdminWithPolicyForUserLocked(admin, reqPolicy,
+                        userId)) {
                     return admin;
                 }
             }
         }
 
-        if (who != null) {
-            if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
-                throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
-                         + " does not own the device");
+        return null;
+    }
+
+    private boolean isActiveAdminWithPolicyForUserLocked(ActiveAdmin admin, int reqPolicy,
+            int userId) {
+        boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
+        boolean ownsProfile = (getProfileOwner(userId) != null
+                && getProfileOwner(userId).getPackageName()
+                    .equals(admin.info.getPackageName()));
+        boolean ownsInitialization = isDeviceInitializer(admin.info.getPackageName())
+                && !hasUserSetupCompleted(userId);
+
+        if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
+            if (ownsDevice || (userId == UserHandle.USER_OWNER && ownsInitialization)) {
+                return true;
             }
-            if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
-                throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
-                        + " does not own the profile");
+        } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
+            if (ownsDevice || ownsProfile || ownsInitialization) {
+                return true;
             }
-            throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
-                    + " did not specify uses-policy for: "
-                    + candidates.get(0).info.getTagForPolicy(reqPolicy));
         } else {
-            throw new SecurityException("No active admin owned by uid "
-                    + Binder.getCallingUid() + " for policy #" + reqPolicy);
+            if (admin.info.usesPolicy(reqPolicy)) {
+                return true;
+            }
         }
+        return false;
     }
 
     void sendAdminCommandLocked(ActiveAdmin admin, String action) {
@@ -1577,6 +1593,16 @@
         validatePasswordOwnerLocked(policy);
         syncDeviceCapabilitiesLocked(policy);
         updateMaximumTimeToLockLocked(policy);
+        updateLockTaskPackagesLocked(policy, userHandle);
+    }
+
+    private void updateLockTaskPackagesLocked(DevicePolicyData policy, int userId) {
+        IActivityManager am = ActivityManagerNative.getDefault();
+        try {
+            am.updateLockTaskPackages(userId, policy.mLockTaskPackages.toArray(new String[0]));
+        } catch (RemoteException e) {
+            // Not gonna happen.
+        }
     }
 
     static void validateQualityConstant(int quality) {
@@ -3106,6 +3132,8 @@
     }
 
     private void wipeDataLocked(boolean wipeExtRequested, String reason) {
+        // TODO: wipe all public volumes on device
+
         // If the SD card is encrypted and non-removable, we have to force a wipe.
         boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
 
@@ -3159,7 +3187,9 @@
                     }
                     PersistentDataBlockManager manager = (PersistentDataBlockManager)
                             mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
-                    manager.wipe();
+                    if (manager != null) {
+                        manager.wipe();
+                    }
                 }
                 boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0;
                 wipeDeviceOrUserLocked(wipeExtRequested, userHandle,
@@ -3986,12 +4016,12 @@
             if (mDeviceOwner == null) {
                 // Device owner state does not exist, create it.
                 mDeviceOwner = DeviceOwner.createWithDeviceInitializer(
-                        initializer.getPackageName(), ownerName);
+                        initializer, ownerName);
                 mDeviceOwner.writeOwnerFile();
                 return true;
             } else {
                 // Device owner already exists, update it.
-                mDeviceOwner.setDeviceInitializer(initializer.getPackageName(), ownerName);
+                mDeviceOwner.setDeviceInitializer(initializer, ownerName);
                 mDeviceOwner.writeOwnerFile();
                 return true;
             }
@@ -4037,6 +4067,19 @@
     }
 
     @Override
+    public ComponentName getDeviceInitializerComponent() {
+        if (!mHasFeature) {
+            return null;
+        }
+        synchronized (this) {
+            if (mDeviceOwner != null && mDeviceOwner.hasDeviceInitializer()) {
+                return mDeviceOwner.getDeviceInitializerComponent();
+            }
+        }
+        return null;
+    }
+
+    @Override
     public void clearDeviceInitializer(ComponentName who) {
         if (!mHasFeature) {
             return;
@@ -5029,7 +5072,10 @@
 
             long id = Binder.clearCallingIdentity();
             try {
-                return mUserManager.getApplicationRestrictions(packageName, userHandle);
+                Bundle bundle = mUserManager.getApplicationRestrictions(packageName, userHandle);
+                // if no restrictions were saved, mUserManager.getApplicationRestrictions
+                // returns null, but DPM method should return an empty Bundle as per JavaDoc
+                return bundle != null ? bundle : Bundle.EMPTY;
             } finally {
                 restoreCallingIdentity(id);
             }
@@ -5418,6 +5464,59 @@
         }
     }
 
+    @Override
+    public void startManagedQuickContact(String actualLookupKey, long actualContactId,
+            Intent originalIntent) {
+        final Intent intent = QuickContact.rebuildManagedQuickContactsIntent(
+                actualLookupKey, actualContactId, originalIntent);
+        final int callingUserId = UserHandle.getCallingUserId();
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (this) {
+                final int managedUserId = getManagedUserId(callingUserId);
+                if (managedUserId < 0) {
+                    return;
+                }
+                if (getCrossProfileCallerIdDisabledForUser(managedUserId)) {
+                    if (VERBOSE_LOG) {
+                        Log.v(LOG_TAG,
+                                "Cross-profile contacts access disabled for user " + managedUserId);
+                    }
+                    return;
+                }
+                ContactsInternal.startQuickContactWithErrorToastForUser(
+                        mContext, intent, new UserHandle(managedUserId));
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    /**
+     * @return the user ID of the managed user that is linked to the current user, if any.
+     * Otherwise -1.
+     */
+    public int getManagedUserId(int callingUserId) {
+        if (VERBOSE_LOG) {
+            Log.v(LOG_TAG, "getManagedUserId: callingUserId=" + callingUserId);
+        }
+
+        for (UserInfo ui : mUserManager.getProfiles(callingUserId)) {
+            if (ui.id == callingUserId || !ui.isManagedProfile()) {
+                continue; // Caller user self, or not a managed profile.  Skip.
+            }
+            if (VERBOSE_LOG) {
+                Log.v(LOG_TAG, "Managed user=" + ui.id);
+            }
+            return ui.id;
+        }
+        if (VERBOSE_LOG) {
+            Log.v(LOG_TAG, "Managed user not found.");
+        }
+        return -1;
+    }
+
     /**
      * Sets which packages may enter lock task mode.
      *
@@ -5441,6 +5540,7 @@
 
             // Store the settings persistently.
             saveSettingsLocked(userHandle);
+            updateLockTaskPackagesLocked(policy, userHandle);
         }
     }
 
@@ -5702,6 +5802,14 @@
             }
         }
 
+        @Override
+        public boolean isActiveAdminWithPolicy(int uid, int reqPolicy) {
+            final int userId = UserHandle.getUserId(uid);
+            synchronized(DevicePolicyManagerService.this) {
+                return getActiveAdminWithPolicyForUidLocked(null, reqPolicy, uid) != null;
+            }
+        }
+
         private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) {
             final List<OnCrossProfileWidgetProvidersChangeListener> listeners;
             synchronized (DevicePolicyManagerService.this) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ae2c54b..53da75b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -53,6 +53,7 @@
 import com.android.server.accounts.AccountManagerService;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.audio.AudioService;
+import com.android.server.camera.CameraService;
 import com.android.server.clipboard.ClipboardService;
 import com.android.server.content.ContentService;
 import com.android.server.devicepolicy.DevicePolicyManagerService;
@@ -66,7 +67,6 @@
 import com.android.server.media.MediaRouterService;
 import com.android.server.media.MediaSessionService;
 import com.android.server.media.projection.MediaProjectionManagerService;
-import com.android.server.MidiService;
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
 import com.android.server.notification.NotificationManagerService;
@@ -76,6 +76,7 @@
 import com.android.server.pm.LauncherAppsService;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.UserManagerService;
+import com.android.server.power.DeviceIdleController;
 import com.android.server.power.PowerManagerService;
 import com.android.server.power.ShutdownThread;
 import com.android.server.restrictions.RestrictionsManagerService;
@@ -124,6 +125,8 @@
             "com.android.server.print.PrintManagerService";
     private static final String USB_SERVICE_CLASS =
             "com.android.server.usb.UsbService$Lifecycle";
+    private static final String MIDI_SERVICE_CLASS =
+            "com.android.server.midi.MidiService$Lifecycle";
     private static final String WIFI_SERVICE_CLASS =
             "com.android.server.wifi.WifiService";
     private static final String WIFI_P2P_SERVICE_CLASS =
@@ -406,12 +409,10 @@
         AudioService audioService = null;
         MmsServiceBroker mmsService = null;
         EntropyMixer entropyMixer = null;
-        MidiService midiService = null;
+        CameraService cameraService = null;
 
         boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
-        boolean disableMedia = SystemProperties.getBoolean("config.disable_media", false);
         boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false);
-        boolean disableTelephony = SystemProperties.getBoolean("config.disable_telephony", false);
         boolean disableLocation = SystemProperties.getBoolean("config.disable_location", false);
         boolean disableSystemUI = SystemProperties.getBoolean("config.disable_systemui", false);
         boolean disableNonCoreServices = SystemProperties.getBoolean("config.disable_noncore", false);
@@ -437,6 +438,9 @@
 
             mContentResolver = context.getContentResolver();
 
+            Slog.i(TAG, "Camera Service");
+            mSystemServiceManager.startService(CameraService.class);
+
             // The AccountManager must come before the ContentService
             try {
                 // TODO: seems like this should be disable-able, but req'd by ContentService
@@ -520,7 +524,6 @@
         LockSettingsService lockSettings = null;
         AssetAtlasService atlas = null;
         MediaRouterService mediaRouter = null;
-        MidiService midi = null;
 
         // Bring up services needed for UI.
         if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
@@ -792,32 +795,33 @@
                 }
             }
 
-            if (!disableMedia && !"0".equals(SystemProperties.get("system_init.startaudioservice"))) {
-                try {
-                    Slog.i(TAG, "Audio Service");
-                    audioService = new AudioService(context);
-                    ServiceManager.addService(Context.AUDIO_SERVICE, audioService);
-                } catch (Throwable e) {
-                    reportWtf("starting Audio Service", e);
-                }
+            try {
+                Slog.i(TAG, "Audio Service");
+                audioService = new AudioService(context);
+                ServiceManager.addService(Context.AUDIO_SERVICE, audioService);
+            } catch (Throwable e) {
+                reportWtf("starting Audio Service", e);
             }
 
             if (!disableNonCoreServices) {
                 mSystemServiceManager.startService(DockObserver.class);
             }
 
-            if (!disableMedia) {
-                try {
-                    Slog.i(TAG, "Wired Accessory Manager");
-                    // Listen for wired headset changes
-                    inputManager.setWiredAccessoryCallbacks(
-                            new WiredAccessoryManager(context, inputManager));
-                } catch (Throwable e) {
-                    reportWtf("starting WiredAccessoryManager", e);
-                }
+            try {
+                Slog.i(TAG, "Wired Accessory Manager");
+                // Listen for wired headset changes
+                inputManager.setWiredAccessoryCallbacks(
+                        new WiredAccessoryManager(context, inputManager));
+            } catch (Throwable e) {
+                reportWtf("starting WiredAccessoryManager", e);
             }
 
             if (!disableNonCoreServices) {
+                if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_MIDI)) {
+                    // Start MIDI Manager service
+                    mSystemServiceManager.startService(MIDI_SERVICE_CLASS);
+                }
+
                 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
                         || mPackageManager.hasSystemFeature(
                                 PackageManager.FEATURE_USB_ACCESSORY)) {
@@ -835,16 +839,6 @@
                 }
             }
 
-            if (!disableNonCoreServices) {
-                try {
-                    Slog.i(TAG, "MIDI Service");
-                    ServiceManager.addService(Context.MIDI_SERVICE,
-                            new MidiService(context));
-                } catch (Throwable e) {
-                    reportWtf("starting MIDI Service", e);
-                }
-            }
-
             mSystemServiceManager.startService(TwilightService.class);
 
             mSystemServiceManager.startService(JobSchedulerService.class);
@@ -891,14 +885,12 @@
                 }
             }
 
-            if (!disableMedia) {
-                try {
-                    Slog.i(TAG, "CommonTimeManagementService");
-                    commonTimeMgmtService = new CommonTimeManagementService(context);
-                    ServiceManager.addService("commontime_management", commonTimeMgmtService);
-                } catch (Throwable e) {
-                    reportWtf("starting CommonTimeManagementService service", e);
-                }
+            try {
+                Slog.i(TAG, "CommonTimeManagementService");
+                commonTimeMgmtService = new CommonTimeManagementService(context);
+                ServiceManager.addService("commontime_management", commonTimeMgmtService);
+            } catch (Throwable e) {
+                reportWtf("starting CommonTimeManagementService service", e);
             }
 
             if (!disableNetwork) {
@@ -925,6 +917,11 @@
                 }
             }
 
+            if (!disableNonCoreServices) {
+                ServiceManager.addService(GraphicsStatsService.GRAPHICS_STATS_SERVICE,
+                        new GraphicsStatsService(context));
+            }
+
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
                 mSystemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS);
             }
diff --git a/services/midi/Android.mk b/services/midi/Android.mk
new file mode 100644
index 0000000..faac01c
--- /dev/null
+++ b/services/midi/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.midi
+
+LOCAL_SRC_FILES += \
+      $(call all-java-files-under,java)
+
+LOCAL_JAVA_LIBRARIES := services.core
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
similarity index 94%
rename from services/core/java/com/android/server/MidiService.java
rename to services/midi/java/com/android/server/midi/MidiService.java
index 3418930..1d2180e 100644
--- a/services/core/java/com/android/server/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.server.midi;
 
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +40,7 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.XmlUtils;
+import com.android.server.SystemService;
 
 import org.xmlpull.v1.XmlPullParser;
 
@@ -47,9 +48,25 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 
 public class MidiService extends IMidiManager.Stub {
+
+    public static class Lifecycle extends SystemService {
+        private MidiService mMidiService;
+
+        public Lifecycle(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStart() {
+            mMidiService = new MidiService(getContext());
+            publishBinderService(Context.MIDI_SERVICE, mMidiService);
+        }
+    }
+
     private static final String TAG = "MidiService";
 
     private final Context mContext;
@@ -269,7 +286,9 @@
 
         public void binderDied() {
             synchronized (mDevicesByInfo) {
-                removeDeviceLocked(this);
+                if (mDevicesByInfo.remove(mDeviceInfo) != null) {
+                    removeDeviceLocked(this);
+                }
             }
         }
 
@@ -368,6 +387,7 @@
         synchronized (mDevicesByInfo) {
             Device device = mDevicesByServer.get(server.asBinder());
             if (device != null) {
+                mDevicesByInfo.remove(device.getDeviceInfo());
                 removeDeviceLocked(device);
             }
         }
@@ -454,16 +474,14 @@
 
     // synchronize on mDevicesByInfo
     private void removeDeviceLocked(Device device) {
-        if (mDevicesByInfo.remove(device.getDeviceInfo()) != null) {
-            IMidiDeviceServer server = device.getDeviceServer();
-            if (server != null) {
-                mDevicesByServer.remove(server);
-            }
+        IMidiDeviceServer server = device.getDeviceServer();
+        if (server != null) {
+            mDevicesByServer.remove(server);
+        }
 
-            synchronized (mClients) {
-                for (Client c : mClients.values()) {
-                    c.deviceRemoved(device);
-                }
+        synchronized (mClients) {
+            for (Client c : mClients.values()) {
+                c.deviceRemoved(device);
             }
         }
     }
@@ -616,8 +634,11 @@
 
     private void removePackageDeviceServers(String packageName) {
         synchronized (mDevicesByInfo) {
-            for (Device device : mDevicesByInfo.values()) {
+            Iterator<Device> iterator = mDevicesByInfo.values().iterator();
+            while (iterator.hasNext()) {
+                Device device = iterator.next();
                 if (packageName.equals(device.getPackageName())) {
+                    iterator.remove();
                     removeDeviceLocked(device);
                 }
             }
@@ -634,15 +655,19 @@
 
         pw.println("Devices:");
         pw.increaseIndent();
-        for (Device device : mDevicesByInfo.values()) {
-            pw.println(device.toString());
+        synchronized (mDevicesByInfo) {
+            for (Device device : mDevicesByInfo.values()) {
+                pw.println(device.toString());
+            }
         }
         pw.decreaseIndent();
 
         pw.println("Clients:");
         pw.increaseIndent();
-        for (Client client : mClients.values()) {
-            pw.println(client.toString());
+        synchronized (mClients) {
+            for (Client client : mClients.values()) {
+                pw.println(client.toString());
+            }
         }
         pw.decreaseIndent();
     }
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index a232a6e..d41629d 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -611,10 +611,22 @@
     /**
      * Reads a string of specified length from the buffer.
      */
-    private static String readAsciiString(ByteBuffer buf, int byteCount) {
+    private static String readAsciiString(ByteBuffer buf, int byteCount, boolean nullOk) {
         byte[] bytes = new byte[byteCount];
         buf.get(bytes);
-        return new String(bytes, 0, bytes.length, StandardCharsets.US_ASCII);
+        int length = bytes.length;
+        if (!nullOk) {
+            // Stop at the first null byte. This is because some DHCP options (e.g., the domain
+            // name) are passed to netd via FrameworkListener, which refuses arguments containing
+            // null bytes. We don't do this by default because vendorInfo is an opaque string which
+            // could in theory contain null bytes.
+            for (length = 0; length < bytes.length; length++) {
+                if (bytes[length] == 0) {
+                    break;
+                }
+            }
+        }
+        return new String(bytes, 0, length, StandardCharsets.US_ASCII);
     }
 
     /**
@@ -797,7 +809,7 @@
                             break;
                         case DHCP_HOST_NAME:
                             expectedLen = optionLen;
-                            hostName = readAsciiString(packet, optionLen);
+                            hostName = readAsciiString(packet, optionLen, false);
                             break;
                         case DHCP_MTU:
                             expectedLen = 2;
@@ -805,7 +817,7 @@
                             break;
                         case DHCP_DOMAIN_NAME:
                             expectedLen = optionLen;
-                            domainName = readAsciiString(packet, optionLen);
+                            domainName = readAsciiString(packet, optionLen, false);
                             break;
                         case DHCP_BROADCAST_ADDRESS:
                             bcAddr = readIpAddress(packet);
@@ -834,7 +846,7 @@
                             break;
                         case DHCP_MESSAGE:
                             expectedLen = optionLen;
-                            message = readAsciiString(packet, optionLen);
+                            message = readAsciiString(packet, optionLen, false);
                             break;
                         case DHCP_MAX_MESSAGE_SIZE:
                             expectedLen = 2;
@@ -850,7 +862,7 @@
                             break;
                         case DHCP_VENDOR_CLASS_ID:
                             expectedLen = optionLen;
-                            vendorId = readAsciiString(packet, optionLen);
+                            vendorId = readAsciiString(packet, optionLen, true);
                             break;
                         case DHCP_CLIENT_IDENTIFIER: { // Client identifier
                             byte[] id = new byte[optionLen];
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index f25fc62..33979b1 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -10,6 +10,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     services.core \
     services.devicepolicy \
+    services.net \
     easymocklib \
     guava \
     mockito-target
diff --git a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
new file mode 100644
index 0000000..2658937
--- /dev/null
+++ b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.net.dhcp;
+
+import android.net.NetworkUtils;
+import android.system.OsConstants;
+import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
+import java.net.Inet4Address;
+import java.nio.ByteBuffer;
+
+import static android.net.dhcp.DhcpPacket.*;
+
+
+public class DhcpPacketTest extends TestCase {
+
+    private static Inet4Address SERVER_ADDR =
+            (Inet4Address) NetworkUtils.numericToInetAddress("192.0.2.1");
+    private static Inet4Address CLIENT_ADDR =
+            (Inet4Address) NetworkUtils.numericToInetAddress("192.0.2.234");
+    private static byte[] CLIENT_MAC = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+
+    class TestDhcpPacket extends DhcpPacket {
+        private byte mType;
+        // TODO: Make this a map of option numbers to bytes instead.
+        private byte[] mDomainBytes, mVendorInfoBytes;
+
+        public TestDhcpPacket(byte type, byte[] domainBytes, byte[] vendorInfoBytes) {
+            super(0xdeadbeef, INADDR_ANY, CLIENT_ADDR, INADDR_ANY, INADDR_ANY, CLIENT_MAC, true);
+            mType = type;
+            mDomainBytes = domainBytes;
+            mVendorInfoBytes = vendorInfoBytes;
+        }
+
+        public ByteBuffer buildPacket(int encap, short unusedDestUdp, short unusedSrcUdp) {
+            ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
+            fillInPacket(encap, CLIENT_ADDR, SERVER_ADDR,
+                         DHCP_CLIENT, DHCP_SERVER, result, DHCP_BOOTREPLY, false);
+            return result;
+        }
+
+        public void finishPacket(ByteBuffer buffer) {
+            addTlv(buffer, DHCP_MESSAGE_TYPE, mType);
+            if (mDomainBytes != null) {
+                addTlv(buffer, DHCP_DOMAIN_NAME, mDomainBytes);
+            }
+            if (mVendorInfoBytes != null) {
+                addTlv(buffer, DHCP_VENDOR_CLASS_ID, mVendorInfoBytes);
+            }
+            addTlvEnd(buffer);
+        }
+
+        // Convenience method.
+        public ByteBuffer build() {
+            // ENCAP_BOOTP packets don't contain ports, so just pass in 0.
+            ByteBuffer pkt = buildPacket(ENCAP_BOOTP, (short) 0, (short) 0);
+            pkt.flip();
+            return pkt;
+        }
+    }
+
+    private void assertDomainAndVendorInfoParses(
+            String expectedDomain, byte[] domainBytes,
+            String expectedVendorInfo, byte[] vendorInfoBytes) {
+        ByteBuffer packet = new TestDhcpPacket(DHCP_MESSAGE_TYPE_OFFER,
+                domainBytes, vendorInfoBytes).build();
+        DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_BOOTP);
+        assertEquals(expectedDomain, offerPacket.mDomainName);
+        assertEquals(expectedVendorInfo, offerPacket.mVendorId);
+    }
+
+    @SmallTest
+    public void testDomainName() throws Exception {
+        byte[] nullByte = new byte[] { 0x00 };
+        byte[] twoNullBytes = new byte[] { 0x00, 0x00 };
+        byte[] nonNullDomain = new byte[] {
+            (byte) 'g', (byte) 'o', (byte) 'o', (byte) '.', (byte) 'g', (byte) 'l'
+        };
+        byte[] trailingNullDomain = new byte[] {
+            (byte) 'g', (byte) 'o', (byte) 'o', (byte) '.', (byte) 'g', (byte) 'l', 0x00
+        };
+        byte[] embeddedNullsDomain = new byte[] {
+            (byte) 'g', (byte) 'o', (byte) 'o', 0x00, 0x00, (byte) 'g', (byte) 'l'
+        };
+        byte[] metered = "ANDROID_METERED".getBytes("US-ASCII");
+
+        byte[] meteredEmbeddedNull = metered.clone();
+        meteredEmbeddedNull[7] = (char) 0;
+
+        byte[] meteredTrailingNull = metered.clone();
+        meteredTrailingNull[meteredTrailingNull.length - 1] = (char) 0;
+
+        assertDomainAndVendorInfoParses("", nullByte, "\u0000", nullByte);
+        assertDomainAndVendorInfoParses("", twoNullBytes, "\u0000\u0000", twoNullBytes);
+        assertDomainAndVendorInfoParses("goo.gl", nonNullDomain, "ANDROID_METERED", metered);
+        assertDomainAndVendorInfoParses("goo", embeddedNullsDomain,
+                                        "ANDROID\u0000METERED", meteredEmbeddedNull);
+        assertDomainAndVendorInfoParses("goo.gl", trailingNullDomain,
+                                        "ANDROID_METERE\u0000", meteredTrailingNull);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 4dc1131..a3f3a5d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -134,7 +134,7 @@
     public void testSettingsReadOld() {
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
-        Settings settings = new Settings(getContext(), getContext().getFilesDir(), new Object());
+        Settings settings = new Settings(getContext().getFilesDir(), new Object());
         assertEquals(true, settings.readLPw(null, null, 0, false));
         assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_3));
         assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_1));
@@ -152,12 +152,12 @@
     public void testNewPackageRestrictionsFile() {
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
-        Settings settings = new Settings(getContext(), getContext().getFilesDir(), new Object());
+        Settings settings = new Settings(getContext().getFilesDir(), new Object());
         assertEquals(true, settings.readLPw(null, null, 0, false));
         settings.writeLPr();
 
         // Create Settings again to make it read from the new files
-        settings = new Settings(getContext(), getContext().getFilesDir(), new Object());
+        settings = new Settings(getContext().getFilesDir(), new Object());
         assertEquals(true, settings.readLPw(null, null, 0, false));
 
         PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_2);
@@ -168,7 +168,7 @@
     public void testEnableDisable() {
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
-        Settings settings = new Settings(getContext(), getContext().getFilesDir(), new Object());
+        Settings settings = new Settings(getContext().getFilesDir(), new Object());
         assertEquals(true, settings.readLPw(null, null, 0, false));
 
         // Enable/Disable a package
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
new file mode 100644
index 0000000..eb7eb15
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.pm;
+
+import android.os.Bundle;
+import android.os.FileUtils;
+import android.os.Parcelable;
+import android.test.AndroidTestCase;
+import android.util.AtomicFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+public class UserManagerServiceTest extends AndroidTestCase {
+    private static String[] STRING_ARRAY = new String[] {"<tag", "<![CDATA["};
+    private File restrictionsFile;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        restrictionsFile = new File(mContext.getCacheDir(), "restrictions.xml");
+        restrictionsFile.delete();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        restrictionsFile.delete();
+        super.tearDown();
+    }
+
+    public void testWriteReadApplicationRestrictions() throws IOException {
+        AtomicFile atomicFile = new AtomicFile(restrictionsFile);
+        Bundle bundle = createBundle();
+        UserManagerService.writeApplicationRestrictionsLocked(bundle, atomicFile);
+        assertTrue(atomicFile.getBaseFile().exists());
+        String s = FileUtils.readTextFile(restrictionsFile, 10000, "");
+        System.out.println("restrictionsFile: " + s);
+        bundle = UserManagerService.readApplicationRestrictionsLocked(atomicFile);
+        System.out.println("readApplicationRestrictionsLocked bundle: " + bundle);
+        assertBundle(bundle);
+    }
+
+    private Bundle createBundle() {
+        Bundle result = new Bundle();
+        // Tests for 6 allowed types: Integer, Boolean, String, String[], Bundle and Parcelable[]
+        result.putBoolean("boolean_0", false);
+        result.putBoolean("boolean_1", true);
+        result.putInt("integer", 100);
+        result.putString("empty", "");
+        result.putString("string", "text");
+        result.putStringArray("string[]", STRING_ARRAY);
+
+        Bundle bundle = new Bundle();
+        bundle.putString("bundle_string", "bundle_string");
+        bundle.putInt("bundle_int", 1);
+        result.putBundle("bundle", bundle);
+
+        Bundle[] bundleArray = new Bundle[2];
+        bundleArray[0] = new Bundle();
+        bundleArray[0].putString("bundle_array_string", "bundle_array_string");
+        bundleArray[0].putBundle("bundle_array_bundle", bundle);
+        bundleArray[1] = new Bundle();
+        bundleArray[1].putString("bundle_array_string2", "bundle_array_string2");
+        result.putParcelableArray("bundle_array", bundleArray);
+        return result;
+    }
+
+    private void assertBundle(Bundle bundle) {
+        assertFalse(bundle.getBoolean("boolean_0"));
+        assertTrue(bundle.getBoolean("boolean_1"));
+        assertEquals(100, bundle.getInt("integer"));
+        assertEquals("", bundle.getString("empty"));
+        assertEquals("text", bundle.getString("string"));
+        assertEquals(Arrays.asList(STRING_ARRAY), Arrays.asList(bundle.getStringArray("string[]")));
+        Parcelable[] bundle_array = bundle.getParcelableArray("bundle_array");
+        assertEquals(2, bundle_array.length);
+        Bundle bundle1 = (Bundle) bundle_array[0];
+        assertEquals("bundle_array_string", bundle1.getString("bundle_array_string"));
+        assertNotNull(bundle1.getBundle("bundle_array_bundle"));
+        Bundle bundle2 = (Bundle) bundle_array[1];
+        assertEquals("bundle_array_string2", bundle2.getString("bundle_array_string2"));
+        Bundle childBundle = bundle.getBundle("bundle");
+        assertEquals("bundle_string", childBundle.getString("bundle_string"));
+        assertEquals(1, childBundle.getInt("bundle_int"));
+    }
+
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 235567c..4498b84 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -18,6 +18,7 @@
 
 import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageStatsManager;
+import android.os.Build;
 import android.util.AtomicFile;
 import android.util.Slog;
 
@@ -35,7 +36,7 @@
  * Provides an interface to query for UsageStat data from an XML database.
  */
 class UsageStatsDatabase {
-    private static final int CURRENT_VERSION = 2;
+    private static final int CURRENT_VERSION = 3;
 
     private static final String TAG = "UsageStatsDatabase";
     private static final boolean DEBUG = UsageStatsService.DEBUG;
@@ -47,6 +48,8 @@
     private final TimeSparseArray<AtomicFile>[] mSortedStatFiles;
     private final UnixCalendar mCal;
     private final File mVersionFile;
+    private boolean mFirstUpdate;
+    private boolean mNewUpdate;
 
     public UsageStatsDatabase(File dir) {
         mIntervalDirs = new File[] {
@@ -73,7 +76,7 @@
                 }
             }
 
-            checkVersionLocked();
+            checkVersionAndBuildLocked();
             indexFilesLocked();
 
             // Delete files that are in the future.
@@ -194,10 +197,35 @@
         }
     }
 
-    private void checkVersionLocked() {
+    /**
+     * Is this the first update to the system from L to M?
+     */
+    boolean isFirstUpdate() {
+        return mFirstUpdate;
+    }
+
+    /**
+     * Is this a system update since we started tracking build fingerprint in the version file?
+     */
+    boolean isNewUpdate() {
+        return mNewUpdate;
+    }
+
+    private void checkVersionAndBuildLocked() {
         int version;
+        String buildFingerprint;
+        String currentFingerprint = getBuildFingerprint();
+        mFirstUpdate = true;
+        mNewUpdate = true;
         try (BufferedReader reader = new BufferedReader(new FileReader(mVersionFile))) {
             version = Integer.parseInt(reader.readLine());
+            buildFingerprint = reader.readLine();
+            if (buildFingerprint != null) {
+                mFirstUpdate = false;
+            }
+            if (currentFingerprint.equals(buildFingerprint)) {
+                mNewUpdate = false;
+            }
         } catch (NumberFormatException | IOException e) {
             version = 0;
         }
@@ -205,9 +233,15 @@
         if (version != CURRENT_VERSION) {
             Slog.i(TAG, "Upgrading from version " + version + " to " + CURRENT_VERSION);
             doUpgradeLocked(version);
+        }
 
+        if (version != CURRENT_VERSION || mNewUpdate) {
             try (BufferedWriter writer = new BufferedWriter(new FileWriter(mVersionFile))) {
                 writer.write(Integer.toString(CURRENT_VERSION));
+                writer.write("\n");
+                writer.write(currentFingerprint);
+                writer.write("\n");
+                writer.flush();
             } catch (IOException e) {
                 Slog.e(TAG, "Failed to write new version");
                 throw new RuntimeException(e);
@@ -215,6 +249,12 @@
         }
     }
 
+    private String getBuildFingerprint() {
+        return Build.VERSION.RELEASE + ";"
+                + Build.VERSION.CODENAME + ";"
+                + Build.VERSION.INCREMENTAL;
+    }
+
     private void doUpgradeLocked(int thisVersion) {
         if (thisVersion < 2) {
             // Delete all files if we are version 0. This is a pre-release version,
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 5eefe6a..cc0ab81 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -21,8 +21,10 @@
 import android.app.usage.ConfigurationStats;
 import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageEvents;
+import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManagerInternal;
+import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -32,6 +34,8 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
+import android.database.ContentObserver;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
@@ -42,6 +46,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -53,6 +58,7 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -74,6 +80,7 @@
     static final int MSG_REPORT_EVENT = 0;
     static final int MSG_FLUSH_TO_DISK = 1;
     static final int MSG_REMOVE_USER = 2;
+    static final int MSG_INFORM_LISTENERS = 3;
 
     private final Object mLock = new Object();
     Handler mHandler;
@@ -85,6 +92,12 @@
     long mRealTimeSnapshot;
     long mSystemTimeSnapshot;
 
+    private static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = 1L * 24 * 60 * 60 * 1000; // 1 day
+    private long mAppIdleDurationMillis;
+
+    private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
+            mPackageAccessListeners = new ArrayList<>();
+
     public UsageStatsService(Context context) {
         super(context);
     }
@@ -112,11 +125,24 @@
 
         mRealTimeSnapshot = SystemClock.elapsedRealtime();
         mSystemTimeSnapshot = System.currentTimeMillis();
+        // Look at primary user's secure setting for this. TODO: Maybe apply different
+        // thresholds for different users.
+        mAppIdleDurationMillis = Settings.Secure.getLongForUser(getContext().getContentResolver(),
+                Settings.Secure.APP_IDLE_DURATION, DEFAULT_APP_IDLE_THRESHOLD_MILLIS,
+                UserHandle.USER_OWNER);
 
         publishLocalService(UsageStatsManagerInternal.class, new LocalService());
         publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
     }
 
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_SYSTEM_SERVICES_READY) {
+            // Observe changes to the threshold
+            new SettingsObserver(mHandler).registerObserver();
+        }
+    }
+
     private class UserRemovedReceiver extends BroadcastReceiver {
 
         @Override
@@ -235,7 +261,19 @@
 
             final UserUsageStatsService service =
                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
+            final long lastUsed = service.getLastPackageAccessTime(event.mPackage);
+            final boolean previouslyIdle = hasPassedIdleDuration(lastUsed);
             service.reportEvent(event);
+            // Inform listeners if necessary
+            if ((event.mEventType == Event.MOVE_TO_FOREGROUND
+                    || event.mEventType == Event.MOVE_TO_BACKGROUND
+                    || event.mEventType == Event.INTERACTION)) {
+                if (previouslyIdle) {
+                    // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
+                            /* idle = */ 0, event.mPackage));
+                }
+            }
         }
     }
 
@@ -308,6 +346,53 @@
         }
     }
 
+    /**
+     * Called by LocalService stub.
+     */
+    long getLastPackageAccessTime(String packageName, int userId) {
+        synchronized (mLock) {
+            final long timeNow = checkAndGetTimeLocked();
+            // android package is always considered non-idle.
+            // TODO: Add a generic whitelisting mechanism
+            if (packageName.equals("android")) {
+                return timeNow;
+            }
+            final UserUsageStatsService service =
+                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
+            return service.getLastPackageAccessTime(packageName);
+        }
+    }
+
+    void addListener(AppIdleStateChangeListener listener) {
+        synchronized (mLock) {
+            if (!mPackageAccessListeners.contains(listener)) {
+                mPackageAccessListeners.add(listener);
+            }
+        }
+    }
+
+    void removeListener(AppIdleStateChangeListener listener) {
+        synchronized (mLock) {
+            mPackageAccessListeners.remove(listener);
+        }
+    }
+
+    private boolean hasPassedIdleDuration(long lastUsed) {
+        final long now = System.currentTimeMillis();
+        return lastUsed < now - mAppIdleDurationMillis;
+    }
+
+    boolean isAppIdle(String packageName, int userId) {
+        final long lastUsed = getLastPackageAccessTime(packageName, userId);
+        return hasPassedIdleDuration(lastUsed);
+    }
+
+    void informListeners(String packageName, int userId, boolean isIdle) {
+        for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
+            listener.onAppIdleStateChanged(packageName, userId, isIdle);
+        }
+    }
+
     private static boolean validRange(long currentTime, long beginTime, long endTime) {
         return beginTime <= currentTime && beginTime < endTime;
     }
@@ -366,6 +451,10 @@
                     removeUser(msg.arg1);
                     break;
 
+                case MSG_INFORM_LISTENERS:
+                    informListeners((String) msg.obj, msg.arg1, msg.arg2 == 1);
+                    break;
+
                 default:
                     super.handleMessage(msg);
                     break;
@@ -373,6 +462,29 @@
         }
     }
 
+    /**
+     * Observe settings changes for Settings.Secure.APP_IDLE_DURATION.
+     */
+    private class SettingsObserver extends ContentObserver {
+
+        SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        void registerObserver() {
+            getContext().getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.APP_IDLE_DURATION), false, this, UserHandle.USER_OWNER);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, int userId) {
+            mAppIdleDurationMillis = Settings.Secure.getLongForUser(getContext().getContentResolver(),
+                    Settings.Secure.APP_IDLE_DURATION, DEFAULT_APP_IDLE_THRESHOLD_MILLIS,
+                    UserHandle.USER_OWNER);
+            // TODO: Check if we need to update idle states of all the apps
+        }
+    }
+
     private class BinderService extends IUsageStatsManager.Stub {
 
         private boolean hasPermission(String callingPackage) {
@@ -523,11 +635,32 @@
         }
 
         @Override
+        public boolean isAppIdle(String packageName, int userId) {
+            return UsageStatsService.this.isAppIdle(packageName, userId);
+        }
+
+        @Override
+        public long getLastPackageAccessTime(String packageName, int userId) {
+            return UsageStatsService.this.getLastPackageAccessTime(packageName, userId);
+        }
+
+        @Override
         public void prepareShutdown() {
             // This method *WILL* do IO work, but we must block until it is finished or else
             // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
             // we are shutting down.
             shutdown();
         }
+
+        @Override
+        public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
+            UsageStatsService.this.addListener(listener);
+        }
+
+        @Override
+        public void removeAppIdleStateChangeListener(
+                AppIdleStateChangeListener listener) {
+            UsageStatsService.this.removeListener(listener);
+        }
     }
 }
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 75fa030..0a9481a 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -19,8 +19,11 @@
 import android.app.usage.ConfigurationStats;
 import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
+import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.os.SystemClock;
 import android.content.Context;
@@ -60,18 +63,21 @@
     private final UnixCalendar mDailyExpiryDate;
     private final StatsUpdatedListener mListener;
     private final String mLogPrefix;
+    private final int mUserId;
 
     interface StatsUpdatedListener {
         void onStatsUpdated();
     }
 
-    UserUsageStatsService(Context context, int userId, File usageStatsDir, StatsUpdatedListener listener) {
+    UserUsageStatsService(Context context, int userId, File usageStatsDir,
+            StatsUpdatedListener listener) {
         mContext = context;
         mDailyExpiryDate = new UnixCalendar(0);
         mDatabase = new UsageStatsDatabase(usageStatsDir);
         mCurrentStats = new IntervalStats[UsageStatsManager.INTERVAL_COUNT];
         mListener = listener;
         mLogPrefix = "User[" + Integer.toString(userId) + "] ";
+        mUserId = userId;
     }
 
     void init(final long currentTimeMillis) {
@@ -127,6 +133,35 @@
 
             stat.updateConfigurationStats(null, stat.lastTimeSaved);
         }
+
+        if (mDatabase.isNewUpdate()) {
+            initializeDefaultsForApps(currentTimeMillis, mDatabase.isFirstUpdate());
+        }
+    }
+
+    /**
+     * If any of the apps don't have a last-used entry, add one now.
+     * @param currentTimeMillis the current time
+     * @param firstUpdate if it is the first update, touch all installed apps, otherwise only
+     *        touch the system apps
+     */
+    private void initializeDefaultsForApps(long currentTimeMillis, boolean firstUpdate) {
+        PackageManager pm = mContext.getPackageManager();
+        List<PackageInfo> packages = pm.getInstalledPackages(0, mUserId);
+        final int packageCount = packages.size();
+        for (int i = 0; i < packageCount; i++) {
+            final PackageInfo pi = packages.get(i);
+            String packageName = pi.packageName;
+            if (pi.applicationInfo != null && (firstUpdate || pi.applicationInfo.isSystemApp())
+                    && getLastPackageAccessTime(packageName) == -1) {
+                for (IntervalStats stats : mCurrentStats) {
+                    stats.update(packageName, currentTimeMillis, Event.INTERACTION);
+                    mStatsChanged = true;
+                }
+            }
+        }
+        // Persist the new OTA-related access stats.
+        persistActiveStats();
     }
 
     void onTimeChanged(long oldTime, long newTime) {
@@ -161,7 +196,9 @@
         if (currentDailyStats.events == null) {
             currentDailyStats.events = new TimeSparseArray<>();
         }
-        currentDailyStats.events.put(event.mTimeStamp, event);
+        if (event.mEventType != UsageEvents.Event.INTERACTION) {
+            currentDailyStats.events.put(event.mTimeStamp, event);
+        }
 
         for (IntervalStats stats : mCurrentStats) {
             if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
@@ -328,6 +365,16 @@
         return new UsageEvents(results, table);
     }
 
+    long getLastPackageAccessTime(String packageName) {
+        final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY];
+        UsageStats packageUsage;
+        if ((packageUsage = yearly.packageStats.get(packageName)) == null) {
+            return -1;
+        } else {
+            return packageUsage.getLastTimeUsed();
+        }
+    }
+
     void persistActiveStats() {
         if (mStatsChanged) {
             Slog.i(TAG, mLogPrefix + "Flushing usage stats to disk");
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 23e1970..2728af1 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -17,6 +17,7 @@
 package com.android.server.usb;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
@@ -55,6 +56,7 @@
 
     private final Context mContext;
     private IAudioService mAudioService;
+    private final boolean mHasMidiFeature;
 
     private final AlsaCardsParser mCardsParser = new AlsaCardsParser();
     private final AlsaDevicesParser mDevicesParser = new AlsaDevicesParser();
@@ -126,6 +128,7 @@
 
     /* package */ UsbAlsaManager(Context context) {
         mContext = context;
+        mHasMidiFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
 
         // initial scan
         mCardsParser.scan();
@@ -389,7 +392,7 @@
             // mDevicesParser.scan()
 
             boolean hasMidi = mDevicesParser.hasMIDIDevices(addedCard);
-            if (hasMidi) {
+            if (hasMidi && mHasMidiFeature) {
                 int device = mDevicesParser.getDefaultDeviceNum(addedCard);
                 AlsaDevice alsaDevice = waitForAlsaDevice(addedCard, device, AlsaDevice.TYPE_MIDI);
                 if (alsaDevice != null) {
@@ -459,7 +462,11 @@
     }
 
    /* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
-        if (enabled) {
+        if (!mHasMidiFeature) {
+            return;
+        }
+
+        if (enabled && mPeripheralMidiDevice == null) {
             Bundle properties = new Bundle();
             Resources r = mContext.getResources();
             properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, r.getString(
@@ -469,7 +476,7 @@
             properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, card);
             properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, device);
             mPeripheralMidiDevice = UsbMidiDevice.create(mContext, properties, card, device);
-        } else if (mPeripheralMidiDevice != null) {
+        } else if (!enabled && mPeripheralMidiDevice != null) {
             IoUtils.closeQuietly(mPeripheralMidiDevice);
             mPeripheralMidiDevice = null;
         }
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 41cf2ef..6adb8be 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -126,6 +126,8 @@
     private boolean mAdbEnabled;
     private boolean mAudioSourceEnabled;
     private boolean mMidiEnabled;
+    private int mMidiCard;
+    private int mMidiDevice;
     private Map<String, List<Pair<String, String>>> mOemModeMap;
     private String[] mAccessoryStrings;
     private UsbDebuggingManager mDebuggingManager;
@@ -363,18 +365,6 @@
                 updateState(state);
                 mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
 
-                // Upgrade step for previous versions that used persist.service.adb.enable
-                String value = SystemProperties.get("persist.service.adb.enable", "");
-                if (value.length() > 0) {
-                    char enable = value.charAt(0);
-                    if (enable == '1') {
-                        setAdbEnabled(true);
-                    } else if (enable == '0') {
-                        setAdbEnabled(false);
-                    }
-                    SystemProperties.set("persist.service.adb.enable", "");
-                }
-
                 // register observer to listen for settings changes
                 mContentResolver.registerContentObserver(
                         Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
@@ -623,26 +613,24 @@
         private void updateMidiFunction() {
             boolean enabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MIDI);
             if (enabled != mMidiEnabled) {
-                int card = -1;
-                int device = -1;
-
                 if (enabled) {
                     Scanner scanner = null;
                     try {
                         scanner = new Scanner(new File(MIDI_ALSA_PATH));
-                        card = scanner.nextInt();
-                        device = scanner.nextInt();
+                        mMidiCard = scanner.nextInt();
+                        mMidiDevice = scanner.nextInt();
                     } catch (FileNotFoundException e) {
                         Slog.e(TAG, "could not open MIDI PCM file", e);
+                        enabled = false;
                     } finally {
                         if (scanner != null) {
                             scanner.close();
                         }
                     }
                 }
-                mUsbAlsaManager.setPeripheralMidiState(enabled, card, device);
                 mMidiEnabled = enabled;
             }
+            mUsbAlsaManager.setPeripheralMidiState(mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
         }
 
         @Override
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index f23bb93..6ece888 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.media.midi.MidiDeviceInfo;
 import android.media.midi.MidiDeviceServer;
-import android.media.midi.MidiDispatcher;
 import android.media.midi.MidiManager;
 import android.media.midi.MidiReceiver;
 import android.media.midi.MidiSender;
@@ -30,6 +29,9 @@
 import android.system.StructPollfd;
 import android.util.Log;
 
+import com.android.internal.midi.MidiEventScheduler;
+import com.android.internal.midi.MidiEventScheduler.MidiEvent;
+
 import libcore.io.IoUtils;
 
 import java.io.Closeable;
@@ -43,10 +45,12 @@
 
     private MidiDeviceServer mServer;
 
-    private final MidiReceiver[] mInputPortReceivers;
+    private final MidiEventScheduler mEventScheduler;
 
     private static final int BUFFER_SIZE = 512;
 
+    private final FileDescriptor[] mFileDescriptors;
+
     // for polling multiple FileDescriptors for MIDI events
     private final StructPollfd[] mPollFDs;
     // streams for reading from ALSA driver
@@ -69,7 +73,7 @@
             return null;
         }
 
-        UsbMidiDevice midiDevice = new UsbMidiDevice(fileDescriptors, fileDescriptors);
+        UsbMidiDevice midiDevice = new UsbMidiDevice(fileDescriptors);
         if (!midiDevice.register(context, properties)) {
             IoUtils.closeQuietly(midiDevice);
             Log.e(TAG, "createDeviceServer failed");
@@ -78,14 +82,15 @@
         return midiDevice;
     }
 
-    private UsbMidiDevice(FileDescriptor[] inputFiles, FileDescriptor[] outputFiles) {
-        int inputCount = inputFiles.length;
-        int outputCount = outputFiles.length;
+    private UsbMidiDevice(FileDescriptor[] fileDescriptors) {
+        mFileDescriptors = fileDescriptors;
+        int inputCount = fileDescriptors.length;
+        int outputCount = fileDescriptors.length;
 
         mPollFDs = new StructPollfd[inputCount];
         mInputStreams = new FileInputStream[inputCount];
         for (int i = 0; i < inputCount; i++) {
-            FileDescriptor fd = inputFiles[i];
+            FileDescriptor fd = fileDescriptors[i];
             StructPollfd pollfd = new StructPollfd();
             pollfd.fd = fd;
             pollfd.events = (short)OsConstants.POLLIN;
@@ -95,21 +100,9 @@
 
         mOutputStreams = new FileOutputStream[outputCount];
         for (int i = 0; i < outputCount; i++) {
-            mOutputStreams[i] = new FileOutputStream(outputFiles[i]);
+            mOutputStreams[i] = new FileOutputStream(fileDescriptors[i]);
         }
-
-        mInputPortReceivers = new MidiReceiver[inputCount];
-        for (int port = 0; port < inputCount; port++) {
-            final int portF = port;
-            mInputPortReceivers[port] = new MidiReceiver() {
-                @Override
-                public void onReceive(byte[] data, int offset, int count, long timestamp)
-                        throws IOException {
-                    // FIXME - timestamps are ignored, future posting not supported yet.
-                    mOutputStreams[portF].write(data, offset, count);
-                }
-            };
-        }
+        mEventScheduler = new MidiEventScheduler(inputCount);
     }
 
     private boolean register(Context context, Bundle properties) {
@@ -119,16 +112,22 @@
             return false;
         }
 
+        int inputCount = mInputStreams.length;
         int outputCount = mOutputStreams.length;
-        mServer = midiManager.createDeviceServer(mInputPortReceivers, outputCount,
+        MidiReceiver[] inputPortReceivers = new MidiReceiver[inputCount];
+        for (int port = 0; port < inputCount; port++) {
+            inputPortReceivers[port] = mEventScheduler.getReceiver(port);
+        }
+
+        mServer = midiManager.createDeviceServer(inputPortReceivers, outputCount,
                 null, null, properties, MidiDeviceInfo.TYPE_USB, null);
         if (mServer == null) {
             return false;
         }
         final MidiReceiver[] outputReceivers = mServer.getOutputPortReceivers();
 
-        // FIXME can we only run this when we have a dispatcher that has listeners?
-        new Thread() {
+        // Create input thread
+        new Thread("UsbMidiDevice input thread") {
             @Override
             public void run() {
                 byte[] buffer = new byte[BUFFER_SIZE];
@@ -158,6 +157,33 @@
                 } catch (ErrnoException e) {
                     Log.d(TAG, "reader thread exiting");
                 }
+                Log.d(TAG, "input thread exit");
+            }
+        }.start();
+
+        // Create output thread
+        new Thread("UsbMidiDevice output thread") {
+            @Override
+            public void run() {
+                while (true) {
+                    MidiEvent event;
+                    try {
+                        event = (MidiEvent)mEventScheduler.waitNextEvent();
+                    } catch (InterruptedException e) {
+                        // try again
+                        continue;
+                    }
+                    if (event == null) {
+                        break;
+                    }
+                    try {
+                        mOutputStreams[event.portNumber].write(event.data, 0, event.count);
+                    } catch (IOException e) {
+                        Log.e(TAG, "write failed for port " + event.portNumber);
+                    }
+                    mEventScheduler.addEventToPool(event);
+                }
+                Log.d(TAG, "output thread exit");
             }
         }.start();
 
@@ -166,6 +192,8 @@
 
     @Override
     public void close() throws IOException {
+        mEventScheduler.close();
+
         if (mServer != null) {
             mServer.close();
         }
@@ -176,8 +204,10 @@
         for (int i = 0; i < mOutputStreams.length; i++) {
             mOutputStreams[i].close();
         }
+        nativeClose(mFileDescriptors);
     }
 
     private static native int nativeGetSubdeviceCount(int card, int device);
     private static native FileDescriptor[] nativeOpen(int card, int device, int subdeviceCount);
+    private static native void nativeClose(FileDescriptor[] fileDescriptors);
 }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index f032ccf..8a28d51 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -50,6 +50,7 @@
 import android.util.Slog;
 
 import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
@@ -396,7 +397,8 @@
                 final int callingUid = Binder.getCallingUid();
                 final long caller = Binder.clearCallingIdentity();
                 try {
-                    mImpl.showSessionLocked(callingPid, callingUid, args, flags);
+                    mImpl.showSessionLocked(callingPid, callingUid, args, flags,
+                            null /* showCallback */);
                 } finally {
                     Binder.restoreCallingIdentity(caller);
                 }
@@ -434,7 +436,8 @@
                 final int callingUid = Binder.getCallingUid();
                 final long caller = Binder.clearCallingIdentity();
                 try {
-                    return mImpl.showSessionLocked(callingPid, callingUid, sessionArgs, flags);
+                    return mImpl.showSessionLocked(callingPid, callingUid, sessionArgs, flags,
+                            null /* showCallback */);
                 } finally {
                     Binder.restoreCallingIdentity(caller);
                 }
@@ -518,13 +521,7 @@
 
         @Override
         public KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
-            synchronized (this) {
-                if (mContext.checkCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
-                        != PackageManager.PERMISSION_GRANTED) {
-                    throw new SecurityException("Caller does not hold the permission "
-                            + Manifest.permission.MANAGE_VOICE_KEYPHRASES);
-                }
-            }
+            enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
 
             if (bcp47Locale == null) {
                 throw new IllegalArgumentException("Illegal argument(s) in getKeyphraseSoundModel");
@@ -541,15 +538,9 @@
 
         @Override
         public int updateKeyphraseSoundModel(KeyphraseSoundModel model) {
-            synchronized (this) {
-                if (mContext.checkCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
-                        != PackageManager.PERMISSION_GRANTED) {
-                    throw new SecurityException("Caller does not hold the permission "
-                            + Manifest.permission.MANAGE_VOICE_KEYPHRASES);
-                }
-                if (model == null) {
-                    throw new IllegalArgumentException("Model must not be null");
-                }
+            enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
+            if (model == null) {
+                throw new IllegalArgumentException("Model must not be null");
             }
 
             final long caller = Binder.clearCallingIdentity();
@@ -572,13 +563,7 @@
 
         @Override
         public int deleteKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
-            synchronized (this) {
-                if (mContext.checkCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
-                        != PackageManager.PERMISSION_GRANTED) {
-                    throw new SecurityException("Caller does not hold the permission "
-                            + Manifest.permission.MANAGE_VOICE_KEYPHRASES);
-                }
-            }
+            enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
 
             if (bcp47Locale == null) {
                 throw new IllegalArgumentException(
@@ -707,6 +692,54 @@
         }
 
         @Override
+        public ComponentName getActiveServiceComponentName() {
+            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
+            synchronized (this) {
+                return mImpl != null ? mImpl.mComponent : null;
+            }
+        }
+
+        @Override
+        public void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback) {
+            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
+            synchronized (this) {
+                if (mImpl == null) {
+                    Slog.w(TAG, "showSessionForActiveService without running voice interaction"
+                            + "service");
+                    return;
+                }
+                final int callingPid = Binder.getCallingPid();
+                final int callingUid = Binder.getCallingUid();
+                final long caller = Binder.clearCallingIdentity();
+                try {
+                    mImpl.showSessionLocked(callingPid, callingUid, new Bundle() /* sessionArgs */,
+                            VoiceInteractionService.START_SOURCE_ASSIST_GESTURE
+                                    | VoiceInteractionService.START_WITH_ASSIST
+                                    | VoiceInteractionService.START_WITH_SCREENSHOT,
+                            showCallback);
+                } finally {
+                    Binder.restoreCallingIdentity(caller);
+                }
+            }
+        }
+
+        @Override
+        public boolean isSessionRunning() {
+            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
+            synchronized (this) {
+                return mImpl != null && mImpl.mActiveSession != null;
+            }
+        }
+
+        @Override
+        public boolean activeServiceSupportsAssistGesture() {
+            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
+            synchronized (this) {
+                return mImpl != null && mImpl.mInfo.getSupportsAssistGesture();
+            }
+        }
+
+        @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -726,6 +759,12 @@
             mSoundTriggerHelper.dump(fd, pw, args);
         }
 
+        private void enforceCallingPermission(String permission) {
+            if (mContext.checkCallingPermission(permission) != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Caller does not hold the permission " + permission);
+            }
+        }
+
         class SettingsObserver extends ContentObserver {
             SettingsObserver(Handler handler) {
                 super(handler);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 5a91b88..bca757b 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -39,6 +39,7 @@
 import android.util.Slog;
 import android.view.IWindowManager;
 
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
 
 import java.io.FileDescriptor;
@@ -134,16 +135,20 @@
         mContext.registerReceiver(mBroadcastReceiver, filter, null, handler);
     }
 
-    public boolean showSessionLocked(int callingPid, int callingUid, Bundle args, int flags) {
+    public boolean showSessionLocked(int callingPid, int callingUid, Bundle args, int flags,
+            IVoiceInteractionSessionShowCallback showCallback) {
         if (mActiveSession == null) {
             mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName,
                     mUser, mContext, this, callingPid, callingUid);
         }
-        return mActiveSession.showLocked(args, flags);
+        return mActiveSession.showLocked(args, flags, showCallback);
     }
 
     public boolean hideSessionLocked(int callingPid, int callingUid) {
-        return mActiveSession.hideLocked();
+        if (mActiveSession != null) {
+            return mActiveSession.hideLocked();
+        }
+        return false;
     }
 
     public boolean deliverNewSessionLocked(int callingPid, int callingUid, IBinder token,
@@ -163,6 +168,10 @@
                 Slog.w(TAG, "startVoiceActivity does not match active session");
                 return ActivityManager.START_CANCELED;
             }
+            if (!mActiveSession.mShown) {
+                Slog.w(TAG, "startVoiceActivity not allowed on hidden session");
+                return ActivityManager.START_CANCELED;
+            }
             intent = new Intent(intent);
             intent.addCategory(Intent.CATEGORY_VOICE);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 7a379c2..607df2d 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
+import android.app.AppOpsManager;
 import android.app.AssistContent;
 import android.app.IActivityManager;
 import android.content.ClipData;
@@ -41,10 +42,12 @@
 import android.view.IWindowManager;
 import android.view.WindowManager;
 import com.android.internal.app.IAssistScreenshotReceiver;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.os.IResultReceiver;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 
 final class VoiceInteractionSessionConnection implements ServiceConnection {
     final static String TAG = "VoiceInteractionServiceManager";
@@ -60,6 +63,7 @@
     final int mCallingUid;
     final IActivityManager mAm;
     final IWindowManager mIWindowManager;
+    final AppOpsManager mAppOps;
     final IBinder mPermissionOwner;
     boolean mShown;
     Bundle mShowArgs;
@@ -74,6 +78,26 @@
     Bundle mAssistData;
     boolean mHaveScreenshot;
     Bitmap mScreenshot;
+    ArrayList<IVoiceInteractionSessionShowCallback> mPendingShowCallbacks = new ArrayList<>();
+
+    IVoiceInteractionSessionShowCallback mShowCallback =
+            new IVoiceInteractionSessionShowCallback.Stub() {
+        @Override
+        public void onFailed() throws RemoteException {
+            synchronized (mLock) {
+                notifyPendingShowCallbacksFailedLocked();
+            }
+        }
+
+        @Override
+        public void onShown() throws RemoteException {
+            synchronized (mLock) {
+                // TODO: Figure out whether this is good enough or whether we need to hook into
+                // Window manager to actually wait for the window to be drawn.
+                notifyPendingShowCallbacksShownLocked();
+            }
+        }
+    };
 
     public interface Callback {
         public void sessionConnectionGone(VoiceInteractionSessionConnection connection);
@@ -126,6 +150,7 @@
         mAm = ActivityManagerNative.getDefault();
         mIWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
+        mAppOps = context.getSystemService(AppOpsManager.class);
         IBinder permOwner = null;
         try {
             permOwner = mAm.newUriPermissionOwner("voicesession:"
@@ -137,7 +162,8 @@
         mBindIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
         mBindIntent.setComponent(mSessionComponentName);
         mBound = mContext.bindServiceAsUser(mBindIntent, this,
-                Context.BIND_AUTO_CREATE|Context.BIND_ALLOW_OOM_MANAGEMENT, new UserHandle(mUser));
+                Context.BIND_AUTO_CREATE|Context.BIND_WAIVE_PRIORITY
+                        |Context.BIND_ALLOW_OOM_MANAGEMENT, new UserHandle(mUser));
         if (mBound) {
             try {
                 mIWindowManager.addWindowToken(mToken,
@@ -151,7 +177,8 @@
         }
     }
 
-    public boolean showLocked(Bundle args, int flags) {
+    public boolean showLocked(Bundle args, int flags,
+            IVoiceInteractionSessionShowCallback showCallback) {
         if (mBound) {
             if (!mFullyBound) {
                 mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
@@ -163,34 +190,54 @@
             mShowFlags = flags;
             mHaveAssistData = false;
             if ((flags&VoiceInteractionService.START_WITH_ASSIST) != 0) {
-                try {
-                    mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
-                            mAssistReceiver);
-                } catch (RemoteException e) {
+                if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid,
+                        mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED) {
+                    try {
+                        mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
+                                mAssistReceiver);
+                    } catch (RemoteException e) {
+                    }
+                } else {
+                    mHaveAssistData = true;
+                    mAssistData = null;
                 }
             } else {
                 mAssistData = null;
             }
             mHaveScreenshot = false;
             if ((flags&VoiceInteractionService.START_WITH_SCREENSHOT) != 0) {
-                try {
-                    mIWindowManager.requestAssistScreenshot(mScreenshotReceiver);
-                } catch (RemoteException e) {
+                if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_SCREENSHOT, mCallingUid,
+                        mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED) {
+                    try {
+                        mIWindowManager.requestAssistScreenshot(mScreenshotReceiver);
+                    } catch (RemoteException e) {
+                    }
+                } else {
+                    mHaveScreenshot = true;
+                    mScreenshot = null;
                 }
             } else {
                 mScreenshot = null;
             }
             if (mSession != null) {
                 try {
-                    mSession.show(mShowArgs, mShowFlags);
+                    mSession.show(mShowArgs, mShowFlags, showCallback);
                     mShowArgs = null;
                     mShowFlags = 0;
                 } catch (RemoteException e) {
                 }
                 deliverSessionDataLocked();
+            } else if (showCallback != null) {
+                mPendingShowCallbacks.add(showCallback);
             }
             return true;
         }
+        if (showCallback != null) {
+            try {
+                showCallback.onFailed();
+            } catch (RemoteException e) {
+            }
+        }
         return false;
     }
 
@@ -304,6 +351,12 @@
                             mUser);
                 } catch (RemoteException e) {
                 }
+                if (mSession != null) {
+                    try {
+                        mAm.finishVoiceTask(mSession);
+                    } catch (RemoteException e) {
+                    }
+                }
             }
             if (mFullyBound) {
                 mContext.unbindService(mFullConnection);
@@ -320,7 +373,7 @@
         mInteractor = interactor;
         if (mShown) {
             try {
-                session.show(mShowArgs, mShowFlags);
+                session.show(mShowArgs, mShowFlags, mShowCallback);
                 mShowArgs = null;
                 mShowFlags = 0;
             } catch (RemoteException e) {
@@ -330,6 +383,26 @@
         return true;
     }
 
+    private void notifyPendingShowCallbacksShownLocked() {
+        for (int i = 0; i < mPendingShowCallbacks.size(); i++) {
+            try {
+                mPendingShowCallbacks.get(i).onShown();
+            } catch (RemoteException e) {
+            }
+        }
+        mPendingShowCallbacks.clear();
+    }
+
+    private void notifyPendingShowCallbacksFailedLocked() {
+        for (int i = 0; i < mPendingShowCallbacks.size(); i++) {
+            try {
+                mPendingShowCallbacks.get(i).onFailed();
+            } catch (RemoteException e) {
+            }
+        }
+        mPendingShowCallbacks.clear();
+    }
+
     @Override
     public void onServiceConnected(ComponentName name, IBinder service) {
         synchronized (mLock) {
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 22b7bb1..6fa653d 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -223,7 +223,7 @@
 
         //**********************************************************************************************
         // Next CAPABILITY value: 0x00080000
-        //**********************************************************************************************
+        //******************************************************************************************
 
         private final Uri mHandle;
         private final int mHandlePresentation;
@@ -323,7 +323,7 @@
                 builder.append(" CAPABILITY_SHOW_CALLBACK_NUMBER");
             }
             if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
-                builder.append(" CAPABILITY_SPEED_UP_IMS_MT_AUDIO");
+                builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
             }
             builder.append("]");
             return builder.toString();
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index a335e47..082474b 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -171,7 +171,7 @@
      * Connection is using WIFI.
      * @hide
      */
-    public static final int CAPABILITY_WIFI = 0x000010000;
+    public static final int CAPABILITY_WIFI = 0x00010000;
 
     /**
      * Indicates that the current device callback number should be shown.
@@ -292,7 +292,7 @@
             builder.append(" CAPABILITY_SHOW_CALLBACK_NUMBER");
         }
         if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
-            builder.append(" CAPABILITY_SPEED_UP_IMS_MT_AUDIO");
+            builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
         }
         builder.append("]");
         return builder.toString();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b44fa6c..d8bb0d7 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -258,11 +258,19 @@
      * <p>
      * Output: nothing.
      */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    @SdkConstant(SdkConstantType.SERVICE_ACTION)
     public static final String ACTION_RESPOND_VIA_MESSAGE =
             "android.intent.action.RESPOND_VIA_MESSAGE";
 
     /**
+     * The emergency dialer may choose to present activities with intent filters for this
+     * action as emergency assistance buttons that launch the activity when clicked.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_EMERGENCY_ASSISTANCE =
+            "android.telephony.action.EMERGENCY_ASSISTANCE";
+
+    /**
      * The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
      * for a String containing the new call state.
      *
@@ -3308,11 +3316,11 @@
      * @return the preferred network type, defined in RILConstants.java.
      * @hide
      */
-    public int getPreferredNetworkType() {
+    public int getPreferredNetworkType(int subId) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null)
-                return telephony.getPreferredNetworkType();
+                return telephony.getPreferredNetworkType(subId);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "getPreferredNetworkType RemoteException", ex);
         } catch (NullPointerException ex) {
@@ -3322,6 +3330,27 @@
     }
 
     /**
+     * Sets the network selection mode to automatic.
+     * <p>
+     * Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     *
+     * @hide
+     */
+    public void setNetworkSelectionModeAutomatic(int subId) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null)
+                telephony.setNetworkSelectionModeAutomatic(subId);
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "setNetworkSelectionModeAutomatic RemoteException", ex);
+        } catch (NullPointerException ex) {
+            Rlog.e(TAG, "setNetworkSelectionModeAutomatic NPE", ex);
+        }
+    }
+
+    /**
      * Set the preferred network type.
      * Used for device configuration by some CDMA operators.
      * <p>
@@ -3329,15 +3358,16 @@
      *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
      * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
      *
+     * @param subId the id of the subscription to set the preferred network type for.
      * @param networkType the preferred network type, defined in RILConstants.java.
      * @return true on success; false on any failure.
      * @hide
      */
-    public boolean setPreferredNetworkType(int networkType) {
+    public boolean setPreferredNetworkType(int subId, int networkType) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null)
-                return telephony.setPreferredNetworkType(networkType);
+                return telephony.setPreferredNetworkType(subId, networkType);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "setPreferredNetworkType RemoteException", ex);
         } catch (NullPointerException ex) {
@@ -3356,7 +3386,8 @@
      * @return true on success; false on any failure.
      */
     public boolean setPreferredNetworkTypeToGlobal() {
-        return setPreferredNetworkType(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
+        return setPreferredNetworkType(getDefaultSubscription(),
+                RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
     }
 
     /**
@@ -3951,7 +3982,10 @@
      */
     public boolean canChangeDtmfToneLength() {
         try {
-            return getITelephony().canChangeDtmfToneLength();
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.canChangeDtmfToneLength();
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#canChangeDtmfToneLength", e);
         }
@@ -3965,7 +3999,10 @@
      */
     public boolean isWorldPhone() {
         try {
-            return getITelephony().isWorldPhone();
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.isWorldPhone();
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#isWorldPhone", e);
         }
@@ -3979,7 +4016,10 @@
      */
     public boolean isTtyModeSupported() {
         try {
-            return getITelephony().isTtyModeSupported();
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.isTtyModeSupported();
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#isTtyModeSupported", e);
         }
@@ -3994,7 +4034,10 @@
      */
     public boolean isHearingAidCompatibilitySupported() {
         try {
-            return getITelephony().isHearingAidCompatibilitySupported();
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.isHearingAidCompatibilitySupported();
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#isHearingAidCompatibilitySupported", e);
         }
@@ -4057,6 +4100,34 @@
    }
 
    /**
+    * Returns the Status of Volte
+    *@hide
+    */
+   public boolean isVolteEnabled() {
+       try {
+           return getITelephony().isVolteEnabled();
+       } catch (RemoteException ex) {
+           return false;
+       } catch (NullPointerException ex) {
+           return false;
+       }
+   }
+
+   /**
+    * Returns the Status of Wi-Fi Calling
+    *@hide
+    */
+   public boolean isWifiCallingEnabled() {
+       try {
+           return getITelephony().isWifiCallingEnabled();
+       } catch (RemoteException ex) {
+           return false;
+       } catch (NullPointerException ex) {
+           return false;
+       }
+   }
+
+   /**
     * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the default phone.
     *
     * @hide
@@ -4412,4 +4483,22 @@
 
         return retval;
     }
+
+    /**
+     * Resets telephony manager settings back to factory defaults.
+     *
+     * @hide
+     */
+    public void factoryReset(int subId) {
+        if (SubscriptionManager.isUsableSubIdValue(subId)) {
+            // Enable data
+            setDataEnabled(subId, true);
+            // Set network selection mode to automatic
+            setNetworkSelectionModeAutomatic(subId);
+            // Set preferred mobile network type to the best available
+            setPreferredNetworkType(subId, RILConstants.PREFERRED_NETWORK_MODE);
+            // Turn off roaming
+            SubscriptionManager.from(mContext).setDataRoaming(0, subId);
+        }
+    }
 }
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index 8740e19..239c16a 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -270,7 +270,7 @@
         return "{ serviceType=" + mServiceType +
                 ", callType=" + mCallType +
                 ", restrictCause=" + mRestrictCause +
-                ", callExtras=" + mCallExtras.toString() +
+                //", callExtras=" + mCallExtras.toString() +
                 ", mediaProfile=" + mMediaProfile.toString() + " }";
     }
 
diff --git a/telephony/java/com/android/ims/internal/IImsUt.aidl b/telephony/java/com/android/ims/internal/IImsUt.aidl
index 50a0169..c531ea5 100644
--- a/telephony/java/com/android/ims/internal/IImsUt.aidl
+++ b/telephony/java/com/android/ims/internal/IImsUt.aidl
@@ -79,12 +79,13 @@
     /**
      * Updates the configuration of the call forward.
      */
-    int updateCallForward(int action, int condition, String number, int timeSeconds);
+    int updateCallForward(int action, int condition, String number,
+            int serviceClass, int timeSeconds);
 
     /**
      * Updates the configuration of the call waiting.
      */
-    int updateCallWaiting(boolean enable);
+    int updateCallWaiting(boolean enable, int serviceClass);
 
     /**
      * Updates the configuration of the CLIR supplementary service.
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index f9e15f3..a24859b 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -653,9 +653,10 @@
      * Get the preferred network type.
      * Used for device configuration by some CDMA operators.
      *
+     * @param subId the id of the subscription to query.
      * @return the preferred network type, defined in RILConstants.java.
      */
-    int getPreferredNetworkType();
+    int getPreferredNetworkType(int subId);
 
     /**
      * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning
@@ -667,13 +668,21 @@
     int getTetherApnRequired();
 
     /**
+     * Set the network selection mode to automatic.
+     *
+     * @param subId the id of the subscription to update.
+     */
+    void setNetworkSelectionModeAutomatic(int subId);
+
+    /**
      * Set the preferred network type.
      * Used for device configuration by some CDMA operators.
      *
+     * @param subId the id of the subscription to update.
      * @param networkType the preferred network type, defined in RILConstants.java.
      * @return true on success; false on any failure.
      */
-    boolean setPreferredNetworkType(int networkType);
+    boolean setPreferredNetworkType(int subId, int networkType);
 
     /**
      * User enable/disable Mobile Data.
@@ -901,6 +910,18 @@
     boolean isImsRegistered();
 
     /**
+     * Returns the Status of Wi-Fi Calling
+     *@hide
+     */
+    boolean isWifiCallingEnabled();
+
+     /**
+     * Returns the Status of Volte
+     *@hide
+     */
+    boolean isVolteEnabled();
+
+    /**
       * Returns the unique device ID of phone, for example, the IMEI for
       * GSM and the MEID for CDMA phones. Return null if device ID is not available.
       *
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 67a8c2b..c8b6846 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -31,6 +31,7 @@
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
+import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.KeySet;
 import android.content.pm.ManifestDigest;
 import android.content.pm.PackageInfo;
@@ -484,14 +485,19 @@
         throw new UnsupportedOperationException();
     }
 
-    /**
-     * @hide - to match hiding in superclass
-     */
+    /** {@hide} */
     @Override
     public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
         throw new UnsupportedOperationException();
     }
 
+    /** {@hide} */
+    @Override
+    public void movePackageAndData(String packageName, String volumeUuid,
+            IPackageMoveObserver observer) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public String getInstallerPackageName(String packageName) {
         throw new UnsupportedOperationException();
@@ -725,6 +731,38 @@
      * @hide
      */
     @Override
+    public void verifyIntentFilter(int id, int verificationCode, List<String> outFailedDomains) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public int getIntentVerificationStatus(String packageName, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean updateIntentVerificationStatus(String packageName, int status, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
     public VerifierDeviceIdentity getVerifierDeviceIdentity() {
         throw new UnsupportedOperationException();
     }
diff --git a/tests/Assistant/Android.mk b/tests/Assist/Android.mk
similarity index 71%
copy from tests/Assistant/Android.mk
copy to tests/Assist/Android.mk
index bf8cc29..f31c4dd 100644
--- a/tests/Assistant/Android.mk
+++ b/tests/Assist/Android.mk
@@ -1,11 +1,10 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
+LOCAL_MODULE_TAGS := tests
+
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_PACKAGE_NAME := Assistant
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
+LOCAL_PACKAGE_NAME := Assist
 
 include $(BUILD_PACKAGE)
diff --git a/tests/Assist/AndroidManifest.xml b/tests/Assist/AndroidManifest.xml
new file mode 100644
index 0000000..4eceed9
--- /dev/null
+++ b/tests/Assist/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.test.assist">
+
+    <application>
+        <service android:name="AssistInteractionService"
+                android:label="Test Assist Interaction Service"
+                android:permission="android.permission.BIND_VOICE_INTERACTION"
+                android:process=":interactor">
+            <meta-data android:name="android.voice_interaction"
+                       android:resource="@xml/interaction_service" />
+            <intent-filter>
+                <action android:name="android.service.voice.VoiceInteractionService" />
+            </intent-filter>
+            <meta-data
+                android:name="com.android.systemui.action_assist_icon"
+                android:resource="@drawable/assistant" />
+        </service>
+        <service android:name="AssistInteractionSessionService"
+                android:permission="android.permission.BIND_VOICE_INTERACTION"
+                android:process=":session">
+        </service>
+    </application>
+</manifest>
diff --git a/tests/Assist/res/drawable/assistant.xml b/tests/Assist/res/drawable/assistant.xml
new file mode 100644
index 0000000..2a89dda
--- /dev/null
+++ b/tests/Assist/res/drawable/assistant.xml
@@ -0,0 +1,27 @@
+<!--
+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="48.0dp"
+        android:height="48.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+    <path
+        android:pathData="M0 0h48v48H0z"
+        android:fillColor="#00000000"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M38.0,4.0L10.0,4.0C7.79,4.0 6.0,5.79 6.0,8.0l0.0,28.0c0.0,2.21 1.79,4.0 4.0,4.0l8.0,0.0l6.0,6.0 6.0,-6.0l8.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L36.0,8.0c0.0,-2.21 -1.79,-4.0 -4.0,-4.0zM27.75,25.75L24.0,34.0l-3.75,-8.25L12.0,22.0l8.25,-3.75L24.0,10.0l3.75,8.25L36.0,22.0l-8.25,3.75z"/>
+</vector>
diff --git a/tests/Assist/res/drawable/navbar_scrim.xml b/tests/Assist/res/drawable/navbar_scrim.xml
new file mode 100644
index 0000000..52ed76d
--- /dev/null
+++ b/tests/Assist/res/drawable/navbar_scrim.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ 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
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <gradient
+            android:type="linear"
+            android:angle="90"
+            android:startColor="#33000000"
+            android:endColor="#00000000" />
+</shape>
\ No newline at end of file
diff --git a/tests/Assist/res/drawable/round_rect.xml b/tests/Assist/res/drawable/round_rect.xml
new file mode 100644
index 0000000..55937a0
--- /dev/null
+++ b/tests/Assist/res/drawable/round_rect.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="#e0e0e0">
+    <item>
+        <shape>
+            <solid android:color="#ffffff" />
+            <corners android:radius="2dp" />
+        </shape>
+    </item>
+</ripple>
\ No newline at end of file
diff --git a/tests/Assist/res/layout/assist.xml b/tests/Assist/res/layout/assist.xml
new file mode 100644
index 0000000..8c4be2d
--- /dev/null
+++ b/tests/Assist/res/layout/assist.xml
@@ -0,0 +1,71 @@
+<?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
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_width="match_parent"
+             android:layout_height="match_parent"
+             android:orientation="vertical">
+
+    <com.android.test.assist.ScrimView
+        android:id="@+id/scrim"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#60000000"/>
+
+    <View
+        android:id="@+id/background"
+        android:layout_width="match_parent"
+        android:layout_height="350dp"
+        android:layout_gravity="bottom"
+        android:background="#e0e0e0"/>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="350dp"
+        android:orientation="vertical"
+        android:layout_gravity="bottom">
+
+        <FrameLayout
+            android:id="@+id/card1"
+            android:layout_width="match_parent"
+            android:layout_height="150dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
+            android:layout_marginTop="16dp"
+            android:elevation="3dp"
+            android:background="@drawable/round_rect">
+        </FrameLayout>
+
+        <View
+            android:id="@+id/card2"
+            android:layout_width="match_parent"
+            android:layout_height="200dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
+            android:layout_marginTop="16dp"
+            android:elevation="3dp"
+            android:background="@drawable/round_rect"/>
+
+    </LinearLayout>
+
+    <com.android.test.assist.ScrimView
+        android:id="@+id/navbar_scrim"
+        android:layout_width="match_parent"
+        android:layout_height="150dp"
+        android:layout_gravity="bottom"
+        android:background="@drawable/navbar_scrim"/>
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/Assist/res/values/strings.xml b/tests/Assist/res/values/strings.xml
new file mode 100644
index 0000000..5331457
--- /dev/null
+++ b/tests/Assist/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+
+    <string name="start">Start</string>
+    <string name="confirm">Confirm</string>
+    <string name="abort">Abort</string>
+    <string name="complete">Complete</string>
+    <string name="abortVoice">Abort Voice</string>
+    <string name="completeVoice">Complete Voice</string>
+    <string name="pickVoice">Pick Voice</string>
+    <string name="cancelVoice">Cancel</string>
+
+</resources>
diff --git a/tests/Assist/res/xml/interaction_service.xml b/tests/Assist/res/xml/interaction_service.xml
new file mode 100644
index 0000000..2fd50aa
--- /dev/null
+++ b/tests/Assist/res/xml/interaction_service.xml
@@ -0,0 +1,21 @@
+<?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
+  -->
+
+<voice-interaction-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:sessionService="com.android.test.assist.AssistInteractionSessionService"
+    android:recognitionService="com.android.test.assist.AssistRecognitionService"
+    android:supportsAssistGesture="true"/>
diff --git a/tests/Assist/res/xml/recognition_service.xml b/tests/Assist/res/xml/recognition_service.xml
new file mode 100644
index 0000000..5b52c3c
--- /dev/null
+++ b/tests/Assist/res/xml/recognition_service.xml
@@ -0,0 +1,18 @@
+<?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
+  -->
+
+<recognition-service/>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/tests/Assist/src/com/android/test/assist/AssistInteractionService.java
similarity index 67%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to tests/Assist/src/com/android/test/assist/AssistInteractionService.java
index 272c321..e6a6713 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/tests/Assist/src/com/android/test/assist/AssistInteractionService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
@@ -11,11 +11,13 @@
  * 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.systemui.statusbar;
+package com.android.test.assist;
 
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
+import android.service.voice.VoiceInteractionService;
+
+public class AssistInteractionService extends VoiceInteractionService {
+
 }
diff --git a/tests/Assist/src/com/android/test/assist/AssistInteractionSession.java b/tests/Assist/src/com/android/test/assist/AssistInteractionSession.java
new file mode 100644
index 0000000..0b522c0
--- /dev/null
+++ b/tests/Assist/src/com/android/test/assist/AssistInteractionSession.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.test.assist;
+
+import android.animation.Animator;
+import android.animation.RevealAnimator;
+import android.animation.ValueAnimator;
+import android.app.VoiceInteractor;
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Handler;
+import android.service.voice.VoiceInteractionService;
+import android.service.voice.VoiceInteractionSession;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.ViewTreeObserver;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+/**
+ * Sample session to show test assist transition.
+ */
+public class AssistInteractionSession extends VoiceInteractionSession {
+
+    private View mScrim;
+    private View mBackground;
+    private View mNavbarScrim;
+    private View mCard1;
+    private View mCard2;
+
+    private float mDensity;
+
+    public AssistInteractionSession(Context context) {
+        super(context);
+    }
+
+    public AssistInteractionSession(Context context, Handler handler) {
+        super(context, handler);
+    }
+
+    @Override
+    public void onConfirm(Caller caller,
+            Request request, CharSequence prompt, Bundle extras) {
+
+    }
+
+    @Override
+    public void onPickOption(Caller caller,
+            Request request, CharSequence prompt,
+            VoiceInteractor.PickOptionRequest.Option[] options, Bundle extras) {
+
+    }
+
+    @Override
+    public void onCommand(Caller caller,
+            Request request, String command, Bundle extras) {
+
+    }
+
+    @Override
+    public void onCreate(Bundle args) {
+        super.onCreate(args);
+
+        // Simulate slowness of Assist app
+        try {
+            Thread.sleep(1000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void onCancel(Request request) {
+
+    }
+
+    @Override
+    public View onCreateContentView() {
+        View v = getLayoutInflater().inflate(R.layout.assist, null);
+        mScrim = v.findViewById(R.id.scrim);
+        mBackground = v.findViewById(R.id.background);
+        mDensity = mScrim.getResources().getDisplayMetrics().density;
+        mCard1 = v.findViewById(R.id.card1);
+        mCard2 = v.findViewById(R.id.card2);
+        mNavbarScrim = v.findViewById(R.id.navbar_scrim);
+        return v;
+    }
+
+    @Override
+    public void onShow(Bundle args, int showFlags) {
+        super.onShow(args, showFlags);
+        if ((showFlags & VoiceInteractionService.START_SOURCE_ASSIST_GESTURE) != 0) {
+            mBackground.getViewTreeObserver().addOnPreDrawListener(
+                    new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            mBackground.getViewTreeObserver().removeOnPreDrawListener(this);
+                            playAssistAnimation();
+                            return true;
+                        }
+                    });
+        }
+    }
+
+    private void playAssistAnimation() {
+        Interpolator linearOutSlowIn = AnimationUtils.loadInterpolator(mBackground.getContext(),
+                android.R.interpolator.linear_out_slow_in);
+        Interpolator fastOutSlowIn = AnimationUtils.loadInterpolator(mBackground.getContext(),
+                android.R.interpolator.fast_out_slow_in);
+        mScrim.setAlpha(0f);
+        mScrim.animate()
+                .alpha(1f)
+                .setStartDelay(100)
+                .setDuration(500);
+        mBackground.setTranslationY(50 * mDensity);
+        mBackground.animate()
+                .translationY(0)
+                .setDuration(300)
+                .setInterpolator(linearOutSlowIn);
+        int centerX = mBackground.getWidth()/2;
+        int centerY = (int) (mBackground.getHeight()/5*3.8f);
+        int radius = (int) Math.sqrt(centerX*centerX + centerY*centerY) + 1;
+        Animator animator = ViewAnimationUtils.createCircularReveal(mBackground, centerX, centerY,
+                0, radius);
+        animator.setDuration(300);
+        animator.setInterpolator(fastOutSlowIn);
+        animator.start();
+
+        ValueAnimator colorAnim = ValueAnimator.ofArgb(Color.WHITE, 0xffe0e0e0);
+        colorAnim.setDuration(300);
+        colorAnim.setInterpolator(fastOutSlowIn);
+        colorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                mBackground.setBackgroundColor((Integer) animation.getAnimatedValue());
+            }
+        });
+        colorAnim.start();
+
+
+        mCard1.setY(mBackground.getHeight());
+        mCard2.setTranslationY(mCard1.getTranslationY());
+        mCard1.animate()
+                .translationY(0)
+                .setDuration(500)
+                .setInterpolator(linearOutSlowIn)
+                .setStartDelay(100);
+        mCard2.animate()
+                .translationY(0)
+                .setInterpolator(linearOutSlowIn)
+                .setStartDelay(150)
+                .setDuration(500);
+
+        mNavbarScrim.setAlpha(0f);
+        mNavbarScrim.animate()
+                .alpha(1f)
+                .setDuration(500)
+                .setStartDelay(100);
+    }
+
+    @Override
+    public void onHide() {
+        super.onHide();
+    }
+}
diff --git a/tests/Assist/src/com/android/test/assist/AssistInteractionSessionService.java b/tests/Assist/src/com/android/test/assist/AssistInteractionSessionService.java
new file mode 100644
index 0000000..3c483d6
--- /dev/null
+++ b/tests/Assist/src/com/android/test/assist/AssistInteractionSessionService.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.test.assist;
+
+import android.os.Bundle;
+import android.service.voice.VoiceInteractionSession;
+import android.service.voice.VoiceInteractionSessionService;
+
+public class AssistInteractionSessionService extends VoiceInteractionSessionService {
+    @Override
+    public VoiceInteractionSession onNewSession(Bundle args) {
+        return new AssistInteractionSession(this);
+    }
+}
diff --git a/tests/Assist/src/com/android/test/assist/AssistRecognitionService.java b/tests/Assist/src/com/android/test/assist/AssistRecognitionService.java
new file mode 100644
index 0000000..6e5faa1
--- /dev/null
+++ b/tests/Assist/src/com/android/test/assist/AssistRecognitionService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.test.assist;
+
+import android.content.Intent;
+import android.speech.RecognitionService;
+
+/**
+ * Stub recognition service needed to be a complete voice interactor.
+ */
+public class AssistRecognitionService extends RecognitionService {
+
+    @Override
+    protected void onStartListening(Intent recognizerIntent, Callback listener) {
+    }
+
+    @Override
+    protected void onCancel(Callback listener) {
+    }
+
+    @Override
+    protected void onStopListening(Callback listener) {
+    }
+}
diff --git a/tests/Assist/src/com/android/test/assist/ScrimView.java b/tests/Assist/src/com/android/test/assist/ScrimView.java
new file mode 100644
index 0000000..1b7387b
--- /dev/null
+++ b/tests/Assist/src/com/android/test/assist/ScrimView.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.test.assist;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class ScrimView extends View {
+
+    public ScrimView(Context context) {
+        super(context);
+    }
+
+    public ScrimView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ScrimView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+}
diff --git a/tests/Assistant/Android.mk b/tests/CameraPrewarmTest/Android.mk
similarity index 81%
copy from tests/Assistant/Android.mk
copy to tests/CameraPrewarmTest/Android.mk
index bf8cc29..b6316f0 100644
--- a/tests/Assistant/Android.mk
+++ b/tests/CameraPrewarmTest/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_PACKAGE_NAME := Assistant
+LOCAL_PACKAGE_NAME := CameraPrewarmTest
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
diff --git a/tests/CameraPrewarmTest/AndroidManifest.xml b/tests/CameraPrewarmTest/AndroidManifest.xml
new file mode 100644
index 0000000..eb40200
--- /dev/null
+++ b/tests/CameraPrewarmTest/AndroidManifest.xml
@@ -0,0 +1,52 @@
+<?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
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.google.android.test.cameraprewarm">
+    <application android:label="@string/activity_title">
+
+        <activity android:name=".CameraActivity"
+                android:theme="@android:style/Theme.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.media.action.STILL_IMAGE_CAMERA" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".SecureCameraActivity"
+                android:theme="@android:style/Theme.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <receiver android:name=".PrewarmReceiver" >
+            <intent-filter>
+                <action android:name="android.media.action.STILL_IMAGE_CAMERA_PREWARM" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.media.action.STILL_IMAGE_CAMERA_COOLDOWN" />
+            </intent-filter>
+        </receiver>
+
+    </application>
+</manifest>
diff --git a/tests/CameraPrewarmTest/res/layout/camera_activity.xml b/tests/CameraPrewarmTest/res/layout/camera_activity.xml
new file mode 100644
index 0000000..64437bc
--- /dev/null
+++ b/tests/CameraPrewarmTest/res/layout/camera_activity.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
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="center">
+</LinearLayout>
+
diff --git a/tests/CameraPrewarmTest/res/values/strings.xml b/tests/CameraPrewarmTest/res/values/strings.xml
new file mode 100644
index 0000000..11f7ac7
--- /dev/null
+++ b/tests/CameraPrewarmTest/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?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
+  -->
+
+<resources>
+    <string name="activity_title">Assistant</string>
+    <string name="search_label">Orilla Search Engine</string>
+</resources>
diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
new file mode 100644
index 0000000..4d22234
--- /dev/null
+++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
@@ -0,0 +1,37 @@
+/*
+ * 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.google.android.test.cameraprewarm;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.google.android.test.cameraprewarm.R;
+
+public class CameraActivity extends Activity {
+
+    public final static String TAG = "PrewarmTest";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.camera_activity);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+        Log.i(TAG, "Activity created");
+    }
+}
diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java
new file mode 100644
index 0000000..d49f96d
--- /dev/null
+++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java
@@ -0,0 +1,35 @@
+/*
+ * 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.google.android.test.cameraprewarm;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.MediaStore;
+import android.util.Log;
+
+public class PrewarmReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (intent.getAction().equals(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM)) {
+            Log.i(CameraActivity.TAG, "Prewarm received");
+        } else if (intent.getAction().equals(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN)){
+            Log.i(CameraActivity.TAG, "Cooldown received");
+        }
+    }
+}
diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/SecureCameraActivity.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/SecureCameraActivity.java
new file mode 100644
index 0000000..530fe00
--- /dev/null
+++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/SecureCameraActivity.java
@@ -0,0 +1,35 @@
+/*
+ * 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.google.android.test.cameraprewarm;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.google.android.test.cameraprewarm.R;
+
+public class SecureCameraActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.camera_activity);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+        Log.i(CameraActivity.TAG, "Activity created");
+    }
+}
diff --git a/tests/Assistant/Android.mk b/tests/LegacyAssistant/Android.mk
similarity index 82%
rename from tests/Assistant/Android.mk
rename to tests/LegacyAssistant/Android.mk
index bf8cc29..0ad48d1 100644
--- a/tests/Assistant/Android.mk
+++ b/tests/LegacyAssistant/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_PACKAGE_NAME := Assistant
+LOCAL_PACKAGE_NAME := LegacyAssistant
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
diff --git a/tests/Assistant/AndroidManifest.xml b/tests/LegacyAssistant/AndroidManifest.xml
similarity index 95%
rename from tests/Assistant/AndroidManifest.xml
rename to tests/LegacyAssistant/AndroidManifest.xml
index b5d4d51..7ae51037 100644
--- a/tests/Assistant/AndroidManifest.xml
+++ b/tests/LegacyAssistant/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.google.android.test.assistant">
+    package="com.google.android.test.legacyassistant">
 
     <application android:label="@string/activity_title">
 
diff --git a/tests/Assistant/res/drawable-hdpi/ic_action_assist_activated.png b/tests/LegacyAssistant/res/drawable-hdpi/ic_action_assist_activated.png
similarity index 100%
rename from tests/Assistant/res/drawable-hdpi/ic_action_assist_activated.png
rename to tests/LegacyAssistant/res/drawable-hdpi/ic_action_assist_activated.png
Binary files differ
diff --git a/tests/Assistant/res/drawable-hdpi/ic_action_assist_normal.png b/tests/LegacyAssistant/res/drawable-hdpi/ic_action_assist_normal.png
similarity index 100%
rename from tests/Assistant/res/drawable-hdpi/ic_action_assist_normal.png
rename to tests/LegacyAssistant/res/drawable-hdpi/ic_action_assist_normal.png
Binary files differ
diff --git a/tests/Assistant/res/drawable-mdpi/ic_action_assist_activated.png b/tests/LegacyAssistant/res/drawable-mdpi/ic_action_assist_activated.png
similarity index 100%
rename from tests/Assistant/res/drawable-mdpi/ic_action_assist_activated.png
rename to tests/LegacyAssistant/res/drawable-mdpi/ic_action_assist_activated.png
Binary files differ
diff --git a/tests/Assistant/res/drawable-mdpi/ic_action_assist_normal.png b/tests/LegacyAssistant/res/drawable-mdpi/ic_action_assist_normal.png
similarity index 100%
rename from tests/Assistant/res/drawable-mdpi/ic_action_assist_normal.png
rename to tests/LegacyAssistant/res/drawable-mdpi/ic_action_assist_normal.png
Binary files differ
diff --git a/tests/Assistant/res/drawable-xhdpi/ic_action_assist_activated.png b/tests/LegacyAssistant/res/drawable-xhdpi/ic_action_assist_activated.png
similarity index 100%
rename from tests/Assistant/res/drawable-xhdpi/ic_action_assist_activated.png
rename to tests/LegacyAssistant/res/drawable-xhdpi/ic_action_assist_activated.png
Binary files differ
diff --git a/tests/Assistant/res/drawable-xhdpi/ic_action_assist_normal.png b/tests/LegacyAssistant/res/drawable-xhdpi/ic_action_assist_normal.png
similarity index 100%
rename from tests/Assistant/res/drawable-xhdpi/ic_action_assist_normal.png
rename to tests/LegacyAssistant/res/drawable-xhdpi/ic_action_assist_normal.png
Binary files differ
diff --git a/tests/Assistant/res/drawable/ic_action_assist.xml b/tests/LegacyAssistant/res/drawable/ic_action_assist.xml
similarity index 100%
rename from tests/Assistant/res/drawable/ic_action_assist.xml
rename to tests/LegacyAssistant/res/drawable/ic_action_assist.xml
diff --git a/tests/Assistant/res/layout/assist_intent_activity.xml b/tests/LegacyAssistant/res/layout/assist_intent_activity.xml
similarity index 100%
rename from tests/Assistant/res/layout/assist_intent_activity.xml
rename to tests/LegacyAssistant/res/layout/assist_intent_activity.xml
diff --git a/tests/Assistant/res/values/strings.xml b/tests/LegacyAssistant/res/values/strings.xml
similarity index 100%
rename from tests/Assistant/res/values/strings.xml
rename to tests/LegacyAssistant/res/values/strings.xml
diff --git a/tests/Assistant/src/com/google/android/test/assistant/AssistActivity.java b/tests/LegacyAssistant/src/com/google/android/test/legacyassistant/AssistActivity.java
similarity index 89%
rename from tests/Assistant/src/com/google/android/test/assistant/AssistActivity.java
rename to tests/LegacyAssistant/src/com/google/android/test/legacyassistant/AssistActivity.java
index 51894a1..b3dbb15 100644
--- a/tests/Assistant/src/com/google/android/test/assistant/AssistActivity.java
+++ b/tests/LegacyAssistant/src/com/google/android/test/legacyassistant/AssistActivity.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.google.android.test.assistant;
+package com.google.android.test.legacyassistant;
 
 import android.app.Activity;
 import android.os.Bundle;
-import com.google.android.test.assistant.R;
+import com.google.android.test.legacyassistant.R;
 
 public class AssistActivity extends Activity {
 
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml
new file mode 100644
index 0000000..88bf777
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale0.xml
@@ -0,0 +1,57 @@
+<!--
+ 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:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:pivotX="0"
+        android:pivotY="0"
+        android:rotation="90" >
+        <group
+            android:scaleX="1.5"
+            android:scaleY="1" >
+            <group
+                android:pivotX="0"
+                android:pivotY="0"
+                android:rotation="-90" >
+                <group
+                    android:scaleX="1.5"
+                    android:scaleY="1" >
+                    <path
+                        android:name="twoLines"
+                        android:fillColor="#FFFF0000"
+                        android:pathData="M 100, 0 l 0, 100, -100, 0 z"
+                        android:strokeColor="#FF00FF00"
+                        android:strokeWidth="10" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml
new file mode 100644
index 0000000..530c73b
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale1.xml
@@ -0,0 +1,52 @@
+<!--
+ 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:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:scaleX="-1"
+        android:scaleY="-1" >
+        <group
+            android:scaleX="-1"
+            android:scaleY="-1" >
+            <group
+                android:pivotX="100"
+                android:pivotY="100"
+                android:rotation="45" >
+                <path
+                    android:name="twoLines"
+                    android:fillColor="#FFFF0000"
+                    android:pathData="M 100, 0 l 0, 100, -100, 0 z"
+                    android:strokeColor="#FF00FF00"
+                    android:strokeWidth="10" />
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml
new file mode 100644
index 0000000..200eb61
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale2.xml
@@ -0,0 +1,48 @@
+<!--
+ 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:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:scaleX="2"
+        android:scaleY="0.5" >
+        <group
+            android:pivotX="100"
+            android:pivotY="100"
+            android:rotation="45" >
+            <path
+                android:name="twoLines"
+                android:fillColor="#FFFF0000"
+                android:pathData="M 100, 0 l 0, 100, -100, 0 z"
+                android:strokeColor="#FF00FF00"
+                android:strokeWidth="10" />
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_scale3.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale3.xml
new file mode 100644
index 0000000..a40fc9c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_scale3.xml
@@ -0,0 +1,62 @@
+<!--
+ 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:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:pivotX="0"
+        android:pivotY="0"
+        android:rotation="45" >
+        <group
+            android:pivotX="0"
+            android:pivotY="0"
+            android:rotation="90" >
+            <group
+                android:scaleX="1.5"
+                android:scaleY="1" >
+                <group
+                    android:pivotX="0"
+                    android:pivotY="0"
+                    android:rotation="-90" >
+                    <group
+                        android:scaleX="1.5"
+                        android:scaleY="1" >
+                        <path
+                            android:name="twoLines"
+                            android:fillColor="#FFFF0000"
+                            android:pathData="M 100, 0 l 0, 100, -100, 0 z"
+                            android:strokeColor="#FF00FF00"
+                            android:strokeWidth="10" />
+                    </group>
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
index ecc7782..56c8119 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java
@@ -14,9 +14,12 @@
 
 package com.android.test.dynamic;
 
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
 import android.app.Activity;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.os.Bundle;
+import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 import android.widget.GridLayout;
@@ -52,6 +55,26 @@
             button.setWidth(400);
             button.setHeight(400);
             button.setBackgroundResource(icon[i]);
+            AnimatedVectorDrawable d = (AnimatedVectorDrawable) button.getBackground();
+            d.addListener(new AnimatorListener() {
+                    @Override
+                public void onAnimationStart(Animator animation) {
+                    Log.v(LOGCAT, "Animator start");
+                }
+                    @Override
+                public void onAnimationRepeat(Animator animation) {
+                    Log.v(LOGCAT, "Animator repeat");
+                }
+                    @Override
+                public void onAnimationEnd(Animator animation) {
+                    Log.v(LOGCAT, "Animator end");
+                }
+                    @Override
+                public void onAnimationCancel(Animator animation) {
+                    Log.v(LOGCAT, "Animator cancel");
+                }
+            });
+
             container.addView(button);
             button.setOnClickListener(this);
         }
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index d029050..b4a93f6 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -65,6 +65,10 @@
             R.drawable.vector_drawable28,
             R.drawable.vector_drawable29,
             R.drawable.vector_drawable30,
+            R.drawable.vector_drawable_scale0,
+            R.drawable.vector_drawable_scale1,
+            R.drawable.vector_drawable_scale2,
+            R.drawable.vector_drawable_scale3,
     };
 
     public static VectorDrawable create(Resources resources, int rid) {
diff --git a/tests/VoiceInteraction/res/layout/main.xml b/tests/VoiceInteraction/res/layout/main.xml
index 3d7a418..092d37d 100644
--- a/tests/VoiceInteraction/res/layout/main.xml
+++ b/tests/VoiceInteraction/res/layout/main.xml
@@ -26,6 +26,14 @@
         android:text="@string/start"
         />
 
+    <com.android.test.voiceinteraction.AsyncStructure
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="64dp"
+            android:paddingBottom="64dp"
+            android:text="@string/asyncStructure"
+            />
+
 </LinearLayout>
 
 
diff --git a/tests/VoiceInteraction/res/layout/test_interaction.xml b/tests/VoiceInteraction/res/layout/test_interaction.xml
index 8c8151d..6209bd08 100644
--- a/tests/VoiceInteraction/res/layout/test_interaction.xml
+++ b/tests/VoiceInteraction/res/layout/test_interaction.xml
@@ -34,32 +34,49 @@
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
 
-    <Button android:id="@+id/complete"
-        android:layout_width="wrap_content"
+    <LinearLayout android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginTop="16dp"
-        android:text="@string/completeVoice"
+        android:orientation="horizontal">
+
+        <Button android:id="@+id/complete"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/completeVoice"
+            />
+
+        <Button android:id="@+id/abort"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/abortVoice"
+            />
+
+        <Button android:id="@+id/pick"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/pickVoice"
+            />
+
+    </LinearLayout>
+
+    <LinearLayout android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:layout_marginBottom="16dp"
+        android:orientation="horizontal">
+
+        <Button android:id="@+id/cancel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/cancelVoice"
         />
 
-    <Button android:id="@+id/pick"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="16dp"
-        android:text="@string/pickVoice"
+        <Button android:id="@+id/jump"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/jumpOut"
         />
 
-    <Button android:id="@+id/abort"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="16dp"
-        android:text="@string/abortVoice"
-        />
-
-    <Button android:id="@+id/cancel"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="16dp"
-        android:text="@string/cancelVoice"
-    />
+    </LinearLayout>
 
 </LinearLayout>
diff --git a/tests/VoiceInteraction/res/values/strings.xml b/tests/VoiceInteraction/res/values/strings.xml
index 5331457..6289929 100644
--- a/tests/VoiceInteraction/res/values/strings.xml
+++ b/tests/VoiceInteraction/res/values/strings.xml
@@ -17,6 +17,7 @@
 <resources>
 
     <string name="start">Start</string>
+    <string name="asyncStructure">(Async structure goes here)</string>
     <string name="confirm">Confirm</string>
     <string name="abort">Abort</string>
     <string name="complete">Complete</string>
@@ -24,5 +25,6 @@
     <string name="completeVoice">Complete Voice</string>
     <string name="pickVoice">Pick Voice</string>
     <string name="cancelVoice">Cancel</string>
+    <string name="jumpOut">Jump out</string>
 
 </resources>
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
index bdc1276..8a72341 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
@@ -46,6 +46,7 @@
 
     public void setAssistStructure(AssistStructure as) {
         mAssistStructure = as;
+        mAssistStructure.dump();
         mTextRects.clear();
         final int N = as.getWindowNodeCount();
         if (N > 0) {
@@ -55,6 +56,7 @@
                         windowNode.getTop());
             }
         }
+        Log.d(TAG, "Building text rects in " + this + ": found " + mTextRects.size());
         invalidate();
     }
 
@@ -69,10 +71,11 @@
         }
         int left = parentLeft+root.getLeft();
         int top = parentTop+root.getTop();
-        Log.d(TAG, "View " + root.getClassName() + ": " + left + ", " + top);
-        if (root.getText() != null) {
+        if (root.getText() != null || root.getContentDescription() != null) {
             Rect r = new Rect(left, top, left+root.getWidth(), top+root.getHeight());
-            Log.d(TAG, "Text Rect " + r.toShortString() + ": " + root.getText());
+            Log.d(TAG, "View " + root.getClassName() + " " + left + "," + top + " tr "
+                    + r.toShortString() + ": "
+                    + (root.getText() != null ? root.getText() : root.getContentDescription()));
             mTextRects.add(r);
         }
         final int N = root.getChildCount();
@@ -91,6 +94,7 @@
         super.onDraw(canvas);
         getLocationOnScreen(mTmpLocation);
         final int N = mTextRects.size();
+        Log.d(TAG, "Drawing text rects in " + this + ": found " + mTextRects.size());
         for (int i=0; i<N; i++) {
             Rect r = mTextRects.get(i);
             canvas.drawRect(r.left-mTmpLocation[0], r.top-mTmpLocation[1],
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AsyncStructure.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AsyncStructure.java
new file mode 100644
index 0000000..73e04e5
--- /dev/null
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AsyncStructure.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.voiceinteraction;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewAssistStructure;
+import android.widget.TextView;
+
+/**
+ * Test for asynchronously creating additional assist structure.
+ */
+public class AsyncStructure extends TextView {
+    public AsyncStructure(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void onProvideVirtualAssistStructure(ViewAssistStructure structure) {
+        structure.setChildCount(1);
+        final ViewAssistStructure child = structure.asyncNewChild(0);
+        final int width = getWidth();
+        final int height = getHeight();
+        (new Thread() {
+            @Override
+            public void run() {
+                // Simulate taking a long time to build this.
+                try {
+                    sleep(2000);
+                } catch (InterruptedException e) {
+                }
+                child.setClassName(AsyncStructure.class.getName());
+                child.setVisibility(View.VISIBLE);
+                child.setDimens(width / 4, height / 4, 0, 0, width / 2, height / 2);
+                child.setEnabled(true);
+                child.setContentDescription("This is some async content");
+                child.setText("We could have lots and lots of async text!");
+                child.asyncCommit();
+            }
+        }).start();
+    }
+}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index bc18ca9..3c5c201 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -16,6 +16,7 @@
 
 package com.android.test.voiceinteraction;
 
+import android.app.ActivityManager;
 import android.app.AssistContent;
 import android.app.AssistStructure;
 import android.app.VoiceInteractor;
@@ -69,6 +70,8 @@
     @Override
     public void onCreate(Bundle args, int startFlags) {
         super.onCreate(args);
+        ActivityManager am = getContext().getSystemService(ActivityManager.class);
+        am.setWatchHeapLimit(40*1024*1024);
     }
 
     @Override
@@ -142,7 +145,6 @@
             if (assistContext != null) {
                 mAssistStructure = AssistStructure.getAssistStructure(assistContext);
                 if (mAssistStructure != null) {
-                    mAssistStructure.dump();
                     if (mAssistVisualizer != null) {
                         mAssistVisualizer.setAssistStructure(mAssistStructure);
                     }
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
index e195c30..9d24c59 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
@@ -19,6 +19,7 @@
 import android.app.Activity;
 import android.app.VoiceInteractor;
 import android.content.ComponentName;
+import android.content.Intent;
 import android.os.Bundle;
 import android.service.voice.VoiceInteractionService;
 import android.util.Log;
@@ -37,6 +38,7 @@
     Button mAbortButton;
     Button mCompleteButton;
     Button mPickButton;
+    Button mJumpOutButton;
     Button mCancelButton;
 
     @Override
@@ -64,6 +66,8 @@
         mCompleteButton.setOnClickListener(this);
         mPickButton = (Button)findViewById(R.id.pick);
         mPickButton.setOnClickListener(this);
+        mJumpOutButton = (Button)findViewById(R.id.jump);
+        mJumpOutButton.setOnClickListener(this);
         mCancelButton = (Button)findViewById(R.id.cancel);
         mCancelButton.setOnClickListener(this);
 
@@ -165,6 +169,13 @@
                 }
             };
             mInteractor.submitRequest(req);
+        } else if (v == mJumpOutButton) {
+            Log.i(TAG, "Jump out");
+            Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.addCategory(Intent.CATEGORY_LAUNCHER);
+            intent.setComponent(new ComponentName(this, VoiceInteractionMain.class));
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            startActivity(intent);
         } else if (v == mCancelButton && mCurrentRequest != null) {
             Log.i(TAG, "Cancel request");
             mCurrentRequest.cancel();
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 36299c2..38d10cf 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -22,7 +22,7 @@
 
 // STATUST: mingw does seem to redefine UNKNOWN_ERROR from our enum value, so a cast is necessary.
 
-#if HAVE_PRINTF_ZD
+#if !defined(_WIN32)
 #  define ZD "%zd"
 #  define ZD_TYPE ssize_t
 #  define STATUST(x) x
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 941a288..24f8168 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -20,7 +20,7 @@
 
 // SSIZE: mingw does not have signed size_t == ssize_t.
 // STATUST: mingw does seem to redefine UNKNOWN_ERROR from our enum value, so a cast is necessary.
-#if HAVE_PRINTF_ZD
+#if !defined(_WIN32)
 #  define SSIZE(x) x
 #  define STATUST(x) x
 #else
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index a18e9f1..9908c44 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -13,7 +13,7 @@
 #include "ResourceTable.h"
 
 // SSIZE: mingw does not have signed size_t == ssize_t.
-#if HAVE_PRINTF_ZD
+#if !defined(_WIN32)
 #  define ZD "%zd"
 #  define ZD_TYPE ssize_t
 #  define SSIZE(x) x
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index d2cd2d6..6902a30 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -18,7 +18,7 @@
 
 // SSIZE: mingw does not have signed size_t == ssize_t.
 // STATUST: mingw does seem to redefine UNKNOWN_ERROR from our enum value, so a cast is necessary.
-#if HAVE_PRINTF_ZD
+#if !defined(_WIN32)
 #  define SSIZE(x) x
 #  define STATUST(x) x
 #else
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
new file mode 100644
index 0000000..9cea176
--- /dev/null
+++ b/tools/aapt2/Android.mk
@@ -0,0 +1,139 @@
+#
+# 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.
+#
+
+# This tool is prebuilt if we're doing an app-only build.
+ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
+
+# ==========================================================
+# Setup some common variables for the different build
+# targets here.
+# ==========================================================
+LOCAL_PATH:= $(call my-dir)
+
+main := Main.cpp
+sources := \
+	BigBuffer.cpp \
+	BinaryResourceParser.cpp \
+	ConfigDescription.cpp \
+	Files.cpp \
+	JavaClassGenerator.cpp \
+	Linker.cpp \
+	Locale.cpp \
+	Logger.cpp \
+	ManifestParser.cpp \
+	ManifestValidator.cpp \
+	ResChunkPullParser.cpp \
+	Resolver.cpp \
+	Resource.cpp \
+	ResourceParser.cpp \
+	ResourceTable.cpp \
+	ResourceValues.cpp \
+	SdkConstants.cpp \
+	StringPool.cpp \
+	TableFlattener.cpp \
+	Util.cpp \
+	ScopedXmlPullParser.cpp \
+	SourceXmlPullParser.cpp \
+	XliffXmlPullParser.cpp \
+	XmlFlattener.cpp
+
+testSources := \
+	BigBuffer_test.cpp \
+	Compat_test.cpp \
+	ConfigDescription_test.cpp \
+	JavaClassGenerator_test.cpp \
+	Linker_test.cpp \
+	Locale_test.cpp \
+	ManifestParser_test.cpp \
+	Maybe_test.cpp \
+	ResourceParser_test.cpp \
+	Resource_test.cpp \
+	ResourceTable_test.cpp \
+	ScopedXmlPullParser_test.cpp \
+	StringPiece_test.cpp \
+	StringPool_test.cpp \
+	Util_test.cpp \
+	XliffXmlPullParser_test.cpp \
+	XmlFlattener_test.cpp
+
+cIncludes :=
+hostLdLibs :=
+
+hostStaticLibs := \
+	libandroidfw \
+	libutils \
+	liblog \
+	libcutils \
+	libexpat \
+	libziparchive-host
+
+ifneq ($(strip $(USE_MINGW)),)
+	hostStaticLibs += libz
+else
+	hostLdLibs += -lz
+endif
+
+cFlags := -Wall -Werror -Wno-unused-parameter -UNDEBUG
+cppFlags := -std=c++11 -Wno-missing-field-initializers
+
+# ==========================================================
+# Build the host static library: libaapt2
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libaapt2
+
+LOCAL_SRC_FILES := $(sources)
+LOCAL_C_INCLUDES += $(cIncludes)
+LOCAL_CFLAGS += $(cFlags)
+LOCAL_CPPFLAGS += $(cppFlags)
+
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+
+# ==========================================================
+# Build the host tests: libaapt2_tests
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libaapt2_tests
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(testSources)
+
+LOCAL_C_INCLUDES += $(cIncludes)
+LOCAL_STATIC_LIBRARIES += libaapt2 $(hostStaticLibs)
+LOCAL_LDLIBS += $(hostLdLibs)
+LOCAL_CFLAGS += $(cFlags)
+LOCAL_CPPFLAGS += $(cppFlags)
+
+include $(BUILD_HOST_NATIVE_TEST)
+
+# ==========================================================
+# Build the host executable: aapt2
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := aapt2
+
+LOCAL_SRC_FILES := $(main)
+
+LOCAL_C_INCLUDES += $(cIncludes)
+LOCAL_STATIC_LIBRARIES += libaapt2 $(hostStaticLibs)
+LOCAL_LDLIBS += $(hostLdLibs)
+LOCAL_CFLAGS += $(cFlags)
+LOCAL_CPPFLAGS += $(cppFlags)
+
+include $(BUILD_HOST_EXECUTABLE)
+
+endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/aapt2/AppInfo.h b/tools/aapt2/AppInfo.h
new file mode 100644
index 0000000..30047f7
--- /dev/null
+++ b/tools/aapt2/AppInfo.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_APP_INFO_H
+#define AAPT_APP_INFO_H
+
+#include <string>
+
+namespace aapt {
+
+/**
+ * Holds basic information about the app being built. Most of this information
+ * will come from the app's AndroidManifest.
+ */
+struct AppInfo {
+    /**
+     * App's package name.
+     */
+    std::u16string package;
+};
+
+} // namespace aapt
+
+#endif // AAPT_APP_INFO_H
diff --git a/tools/aapt2/BigBuffer.cpp b/tools/aapt2/BigBuffer.cpp
new file mode 100644
index 0000000..8f57172
--- /dev/null
+++ b/tools/aapt2/BigBuffer.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#include "BigBuffer.h"
+
+#include <algorithm>
+#include <memory>
+#include <vector>
+
+namespace aapt {
+
+void* BigBuffer::nextBlockImpl(size_t size) {
+    if (!mBlocks.empty()) {
+        Block& block = mBlocks.back();
+        if (block.mBlockSize - block.size >= size) {
+            void* outBuffer = block.buffer.get() + block.size;
+            block.size += size;
+            mSize += size;
+            return outBuffer;
+        }
+    }
+
+    const size_t actualSize = std::max(mBlockSize, size);
+
+    Block block = {};
+
+    // Zero-allocate the block's buffer.
+    block.buffer = std::unique_ptr<uint8_t[]>(new uint8_t[actualSize]());
+    assert(block.buffer);
+
+    block.size = size;
+    block.mBlockSize = actualSize;
+
+    mBlocks.push_back(std::move(block));
+    mSize += size;
+    return mBlocks.back().buffer.get();
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/BigBuffer.h b/tools/aapt2/BigBuffer.h
new file mode 100644
index 0000000..8b6569c
--- /dev/null
+++ b/tools/aapt2/BigBuffer.h
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_BIG_BUFFER_H
+#define AAPT_BIG_BUFFER_H
+
+#include <cassert>
+#include <cstring>
+#include <memory>
+#include <vector>
+
+namespace aapt {
+
+/**
+ * Inspired by protobuf's ZeroCopyOutputStream, offers blocks of memory
+ * in which to write without knowing the full size of the entire payload.
+ * This is essentially a list of memory blocks. As one fills up, another
+ * block is allocated and appended to the end of the list.
+ */
+class BigBuffer {
+public:
+    /**
+     * A contiguous block of allocated memory.
+     */
+    struct Block {
+        /**
+         * Pointer to the memory.
+         */
+        std::unique_ptr<uint8_t[]> buffer;
+
+        /**
+         * Size of memory that is currently occupied. The actual
+         * allocation may be larger.
+         */
+        size_t size;
+
+    private:
+        friend class BigBuffer;
+
+        /**
+         * The size of the memory block allocation.
+         */
+        size_t mBlockSize;
+    };
+
+    typedef std::vector<Block>::const_iterator const_iterator;
+
+    /**
+     * Create a BigBuffer with block allocation sizes
+     * of blockSize.
+     */
+    BigBuffer(size_t blockSize);
+
+    BigBuffer(const BigBuffer&) = delete; // No copying.
+
+    BigBuffer(BigBuffer&& rhs);
+
+    /**
+     * Number of occupied bytes in all the allocated blocks.
+     */
+    size_t size() const;
+
+    /**
+     * Returns a pointer to an array of T, where T is
+     * a POD type. The elements are zero-initialized.
+     */
+    template <typename T>
+    T* nextBlock(size_t count = 1);
+
+    /**
+     * Moves the specified BigBuffer into this one. When this method
+     * returns, buffer is empty.
+     */
+    void appendBuffer(BigBuffer&& buffer);
+
+    /**
+     * Pads the block with 'bytes' bytes of zero values.
+     */
+    void pad(size_t bytes);
+
+    /**
+     * Pads the block so that it aligns on a 4 byte boundary.
+     */
+    void align4();
+
+    const_iterator begin() const;
+    const_iterator end() const;
+
+private:
+    /**
+     * Returns a pointer to a buffer of the requested size.
+     * The buffer is zero-initialized.
+     */
+    void* nextBlockImpl(size_t size);
+
+    size_t mBlockSize;
+    size_t mSize;
+    std::vector<Block> mBlocks;
+};
+
+inline BigBuffer::BigBuffer(size_t blockSize) : mBlockSize(blockSize), mSize(0) {
+}
+
+inline BigBuffer::BigBuffer(BigBuffer&& rhs) :
+        mBlockSize(rhs.mBlockSize), mSize(rhs.mSize), mBlocks(std::move(rhs.mBlocks)) {
+}
+
+inline size_t BigBuffer::size() const {
+    return mSize;
+}
+
+template <typename T>
+inline T* BigBuffer::nextBlock(size_t count) {
+    assert(count != 0);
+    return reinterpret_cast<T*>(nextBlockImpl(sizeof(T) * count));
+}
+
+inline void BigBuffer::appendBuffer(BigBuffer&& buffer) {
+    std::move(buffer.mBlocks.begin(), buffer.mBlocks.end(), std::back_inserter(mBlocks));
+    mSize += buffer.mSize;
+    buffer.mBlocks.clear();
+    buffer.mSize = 0;
+}
+
+inline void BigBuffer::pad(size_t bytes) {
+    nextBlock<char>(bytes);
+}
+
+inline void BigBuffer::align4() {
+    const size_t unaligned = mSize % 4;
+    if (unaligned != 0) {
+        pad(4 - unaligned);
+    }
+}
+
+inline BigBuffer::const_iterator BigBuffer::begin() const {
+    return mBlocks.begin();
+}
+
+inline BigBuffer::const_iterator BigBuffer::end() const {
+    return mBlocks.end();
+}
+
+} // namespace aapt
+
+#endif // AAPT_BIG_BUFFER_H
diff --git a/tools/aapt2/BigBuffer_test.cpp b/tools/aapt2/BigBuffer_test.cpp
new file mode 100644
index 0000000..01ee8d7
--- /dev/null
+++ b/tools/aapt2/BigBuffer_test.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#include "BigBuffer.h"
+
+#include <gtest/gtest.h>
+
+namespace aapt {
+
+TEST(BigBufferTest, AllocateSingleBlock) {
+    BigBuffer buffer(4);
+
+    EXPECT_NE(nullptr, buffer.nextBlock<char>(2));
+    EXPECT_EQ(2u, buffer.size());
+}
+
+TEST(BigBufferTest, ReturnSameBlockIfNextAllocationFits) {
+    BigBuffer buffer(16);
+
+    char* b1 = buffer.nextBlock<char>(8);
+    EXPECT_NE(nullptr, b1);
+
+    char* b2 = buffer.nextBlock<char>(4);
+    EXPECT_NE(nullptr, b2);
+
+    EXPECT_EQ(b1 + 8, b2);
+}
+
+TEST(BigBufferTest, AllocateExactSizeBlockIfLargerThanBlockSize) {
+    BigBuffer buffer(16);
+
+    EXPECT_NE(nullptr, buffer.nextBlock<char>(32));
+    EXPECT_EQ(32u, buffer.size());
+}
+
+TEST(BigBufferTest, AppendAndMoveBlock) {
+    BigBuffer buffer(16);
+
+    uint32_t* b1 = buffer.nextBlock<uint32_t>();
+    ASSERT_NE(nullptr, b1);
+    *b1 = 33;
+
+    {
+        BigBuffer buffer2(16);
+        b1 = buffer2.nextBlock<uint32_t>();
+        ASSERT_NE(nullptr, b1);
+        *b1 = 44;
+
+        buffer.appendBuffer(std::move(buffer2));
+        EXPECT_EQ(0u, buffer2.size());
+        EXPECT_EQ(buffer2.begin(), buffer2.end());
+    }
+
+    EXPECT_EQ(2 * sizeof(uint32_t), buffer.size());
+
+    auto b = buffer.begin();
+    ASSERT_NE(b, buffer.end());
+    ASSERT_EQ(sizeof(uint32_t), b->size);
+    ASSERT_EQ(33u, *reinterpret_cast<uint32_t*>(b->buffer.get()));
+    ++b;
+
+    ASSERT_NE(b, buffer.end());
+    ASSERT_EQ(sizeof(uint32_t), b->size);
+    ASSERT_EQ(44u, *reinterpret_cast<uint32_t*>(b->buffer.get()));
+    ++b;
+
+    ASSERT_EQ(b, buffer.end());
+}
+
+TEST(BigBufferTest, PadAndAlignProperly) {
+    BigBuffer buffer(16);
+
+    ASSERT_NE(buffer.nextBlock<char>(2), nullptr);
+    ASSERT_EQ(2u, buffer.size());
+    buffer.pad(2);
+    ASSERT_EQ(4u, buffer.size());
+    buffer.align4();
+    ASSERT_EQ(4u, buffer.size());
+    buffer.pad(2);
+    ASSERT_EQ(6u, buffer.size());
+    buffer.align4();
+    ASSERT_EQ(8u, buffer.size());
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/BinaryResourceParser.cpp b/tools/aapt2/BinaryResourceParser.cpp
new file mode 100644
index 0000000..3eb96bc
--- /dev/null
+++ b/tools/aapt2/BinaryResourceParser.cpp
@@ -0,0 +1,798 @@
+/*
+ * 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.
+ */
+
+#include "BinaryResourceParser.h"
+#include "Logger.h"
+#include "ResChunkPullParser.h"
+#include "ResourceParser.h"
+#include "ResourceTable.h"
+#include "ResourceTypeExtensions.h"
+#include "ResourceValues.h"
+#include "Source.h"
+#include "Util.h"
+
+#include <androidfw/ResourceTypes.h>
+#include <androidfw/TypeWrappers.h>
+#include <map>
+#include <string>
+
+namespace aapt {
+
+using namespace android;
+
+template <typename T>
+inline static const T* convertTo(const ResChunk_header* chunk) {
+    if (chunk->headerSize < sizeof(T)) {
+        return nullptr;
+    }
+    return reinterpret_cast<const T*>(chunk);
+}
+
+inline static const uint8_t* getChunkData(const ResChunk_header& chunk) {
+    return reinterpret_cast<const uint8_t*>(&chunk) + chunk.headerSize;
+}
+
+inline static size_t getChunkDataLen(const ResChunk_header& chunk) {
+    return chunk.size - chunk.headerSize;
+}
+
+/*
+ * Visitor that converts a reference's resource ID to a resource name,
+ * given a mapping from resource ID to resource name.
+ */
+struct ReferenceIdToNameVisitor : ValueVisitor {
+    ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceName>& cache) : mCache(cache) {
+    }
+
+    void visit(Reference& reference, ValueVisitorArgs&) override {
+        idToName(reference);
+    }
+
+    void visit(Attribute& attr, ValueVisitorArgs&) override {
+        for (auto& entry : attr.symbols) {
+            idToName(entry.symbol);
+        }
+    }
+
+    void visit(Style& style, ValueVisitorArgs&) override {
+        if (style.parent.id.isValid()) {
+            idToName(style.parent);
+        }
+
+        for (auto& entry : style.entries) {
+            idToName(entry.key);
+            entry.value->accept(*this, {});
+        }
+    }
+
+    void visit(Styleable& styleable, ValueVisitorArgs&) override {
+        for (auto& attr : styleable.entries) {
+            idToName(attr);
+        }
+    }
+
+    void visit(Array& array, ValueVisitorArgs&) override {
+        for (auto& item : array.items) {
+            item->accept(*this, {});
+        }
+    }
+
+    void visit(Plural& plural, ValueVisitorArgs&) override {
+        for (auto& item : plural.values) {
+            if (item) {
+                item->accept(*this, {});
+            }
+        }
+    }
+
+private:
+    void idToName(Reference& reference) {
+        if (!reference.id.isValid()) {
+            return;
+        }
+
+        auto cacheIter = mCache.find(reference.id);
+        if (cacheIter == std::end(mCache)) {
+            Logger::note() << "failed to find " << reference.id << std::endl;
+        } else {
+            reference.name = cacheIter->second;
+            reference.id = 0;
+        }
+    }
+
+    const std::map<ResourceId, ResourceName>& mCache;
+};
+
+
+BinaryResourceParser::BinaryResourceParser(std::shared_ptr<ResourceTable> table,
+                                           const Source& source,
+                                           const void* data,
+                                           size_t len) :
+        mTable(table), mSource(source), mData(data), mDataLen(len) {
+}
+
+bool BinaryResourceParser::parse() {
+    ResChunkPullParser parser(mData, mDataLen);
+
+    bool error = false;
+    while(ResChunkPullParser::isGoodEvent(parser.next())) {
+        if (parser.getChunk()->type != android::RES_TABLE_TYPE) {
+            Logger::warn(mSource)
+                    << "unknown chunk of type '"
+                    << parser.getChunk()->type
+                    << "'."
+                    << std::endl;
+            continue;
+        }
+
+        error |= !parseTable(parser.getChunk());
+    }
+
+    if (parser.getEvent() == ResChunkPullParser::Event::BadDocument) {
+        Logger::error(mSource)
+                << "bad document: "
+                << parser.getLastError()
+                << "."
+                << std::endl;
+        return false;
+    }
+    return !error;
+}
+
+bool BinaryResourceParser::getSymbol(const void* data, ResourceNameRef* outSymbol) {
+    if (!mSymbolEntries || mSymbolEntryCount == 0) {
+        return false;
+    }
+
+    if (reinterpret_cast<uintptr_t>(data) < reinterpret_cast<uintptr_t>(mData)) {
+        return false;
+    }
+
+    // We only support 32 bit offsets right now.
+    const uintptr_t offset = reinterpret_cast<uintptr_t>(data) -
+            reinterpret_cast<uintptr_t>(mData);
+    if (offset > std::numeric_limits<uint32_t>::max()) {
+        return false;
+    }
+
+    for (size_t i = 0; i < mSymbolEntryCount; i++) {
+        if (mSymbolEntries[i].offset == offset) {
+            // This offset is a symbol!
+            const StringPiece16 str = util::getString(mSymbolPool,
+                                                      mSymbolEntries[i].stringIndex);
+            StringPiece16 typeStr;
+            ResourceParser::extractResourceName(str, &outSymbol->package, &typeStr,
+                                                &outSymbol->entry);
+            const ResourceType* type = parseResourceType(typeStr);
+            if (!type) {
+                return false;
+            }
+            outSymbol->type = *type;
+
+            // Since we scan the symbol table in order, we can start looking for the
+            // next symbol from this point.
+            mSymbolEntryCount -= i + 1;
+            mSymbolEntries += i + 1;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool BinaryResourceParser::parseSymbolTable(const ResChunk_header* chunk) {
+    const SymbolTable_header* symbolTableHeader = convertTo<SymbolTable_header>(chunk);
+    if (!symbolTableHeader) {
+        Logger::error(mSource)
+                << "could not parse chunk as SymbolTable_header."
+                << std::endl;
+        return false;
+    }
+
+    const size_t entrySizeBytes = symbolTableHeader->count * sizeof(SymbolTable_entry);
+    if (entrySizeBytes > getChunkDataLen(symbolTableHeader->header)) {
+        Logger::error(mSource)
+                << "entries extend beyond chunk."
+                << std::endl;
+        return false;
+    }
+
+    mSymbolEntries = reinterpret_cast<const SymbolTable_entry*>(
+            getChunkData(symbolTableHeader->header));
+    mSymbolEntryCount = symbolTableHeader->count;
+
+    ResChunkPullParser parser(getChunkData(symbolTableHeader->header) + entrySizeBytes,
+                              getChunkDataLen(symbolTableHeader->header) - entrySizeBytes);
+    if (!ResChunkPullParser::isGoodEvent(parser.next())) {
+        Logger::error(mSource)
+                << "failed to parse chunk: "
+                << parser.getLastError()
+                << "."
+                << std::endl;
+        return false;
+    }
+
+    if (parser.getChunk()->type != android::RES_STRING_POOL_TYPE) {
+        Logger::error(mSource)
+                << "expected Symbol string pool."
+                << std::endl;
+        return false;
+    }
+
+    if (mSymbolPool.setTo(parser.getChunk(), parser.getChunk()->size) != NO_ERROR) {
+        Logger::error(mSource)
+                << "failed to parse symbol string pool with code: "
+                << mSymbolPool.getError()
+                << "."
+                << std::endl;
+        return false;
+    }
+    return true;
+}
+
+bool BinaryResourceParser::parseTable(const ResChunk_header* chunk) {
+    const ResTable_header* tableHeader = convertTo<ResTable_header>(chunk);
+    if (!tableHeader) {
+        Logger::error(mSource)
+                << "could not parse chunk as ResTable_header."
+                << std::endl;
+        return false;
+    }
+
+    ResChunkPullParser parser(getChunkData(tableHeader->header),
+                              getChunkDataLen(tableHeader->header));
+    while (ResChunkPullParser::isGoodEvent(parser.next())) {
+        switch (parser.getChunk()->type) {
+        case android::RES_STRING_POOL_TYPE:
+            if (mValuePool.getError() == NO_INIT) {
+                if (mValuePool.setTo(parser.getChunk(), parser.getChunk()->size) !=
+                        NO_ERROR) {
+                    Logger::error(mSource)
+                            << "failed to parse value string pool with code: "
+                            << mValuePool.getError()
+                            << "."
+                            << std::endl;
+                    return false;
+                }
+
+                // Reserve some space for the strings we are going to add.
+                mTable->getValueStringPool().hintWillAdd(
+                        mValuePool.size(), mValuePool.styleCount());
+            } else {
+                Logger::warn(mSource)
+                    << "unexpected string pool."
+                    << std::endl;
+            }
+            break;
+
+        case RES_TABLE_SYMBOL_TABLE_TYPE:
+            if (!parseSymbolTable(parser.getChunk())) {
+                return false;
+            }
+            break;
+
+        case RES_TABLE_SOURCE_POOL_TYPE: {
+            if (mSourcePool.setTo(getChunkData(*parser.getChunk()),
+                        getChunkDataLen(*parser.getChunk())) != NO_ERROR) {
+                Logger::error(mSource)
+                        << "failed to parse source pool with code: "
+                        << mSourcePool.getError()
+                        << "."
+                        << std::endl;
+                return false;
+            }
+            break;
+        }
+
+        case android::RES_TABLE_PACKAGE_TYPE:
+            if (!parsePackage(parser.getChunk())) {
+                return false;
+            }
+            break;
+
+        default:
+            Logger::warn(mSource)
+                << "unexpected chunk of type "
+                << parser.getChunk()->type
+                << "."
+                << std::endl;
+            break;
+        }
+    }
+
+    if (parser.getEvent() == ResChunkPullParser::Event::BadDocument) {
+        Logger::error(mSource)
+            << "bad resource table: " << parser.getLastError()
+            << "."
+            << std::endl;
+        return false;
+    }
+    return true;
+}
+
+bool BinaryResourceParser::parsePackage(const ResChunk_header* chunk) {
+    if (mValuePool.getError() != NO_ERROR) {
+        Logger::error(mSource)
+                << "no value string pool for ResTable."
+                << std::endl;
+        return false;
+    }
+
+    const ResTable_package* packageHeader = convertTo<ResTable_package>(chunk);
+    if (!packageHeader) {
+        Logger::error(mSource)
+                << "could not parse chunk as ResTable_header."
+                << std::endl;
+        return false;
+    }
+
+    if (mTable->getPackageId() == ResourceTable::kUnsetPackageId) {
+        // This is the first time the table has it's package ID set.
+        mTable->setPackageId(packageHeader->id);
+    } else if (mTable->getPackageId() != packageHeader->id) {
+        Logger::error(mSource)
+                << "ResTable_package has package ID "
+                << std::hex << packageHeader->id << std::dec
+                << " but ResourceTable has package ID "
+                << std::hex << mTable->getPackageId() << std::dec
+                << std::endl;
+        return false;
+    }
+
+    size_t len = strnlen16(reinterpret_cast<const char16_t*>(packageHeader->name),
+            sizeof(packageHeader->name) / sizeof(packageHeader->name[0]));
+    mTable->setPackage(StringPiece16(reinterpret_cast<const char16_t*>(packageHeader->name), len));
+
+    ResChunkPullParser parser(getChunkData(packageHeader->header),
+                              getChunkDataLen(packageHeader->header));
+    while (ResChunkPullParser::isGoodEvent(parser.next())) {
+        switch (parser.getChunk()->type) {
+        case android::RES_STRING_POOL_TYPE:
+            if (mTypePool.getError() == NO_INIT) {
+                if (mTypePool.setTo(parser.getChunk(), parser.getChunk()->size) !=
+                        NO_ERROR) {
+                    Logger::error(mSource)
+                            << "failed to parse type string pool with code "
+                            << mTypePool.getError()
+                            << "."
+                            << std::endl;
+                    return false;
+                }
+            } else if (mKeyPool.getError() == NO_INIT) {
+                if (mKeyPool.setTo(parser.getChunk(), parser.getChunk()->size) !=
+                        NO_ERROR) {
+                    Logger::error(mSource)
+                            << "failed to parse key string pool with code "
+                            << mKeyPool.getError()
+                            << "."
+                            << std::endl;
+                    return false;
+                }
+            } else {
+                Logger::warn(mSource)
+                        << "unexpected string pool."
+                        << std::endl;
+            }
+            break;
+
+        case android::RES_TABLE_TYPE_SPEC_TYPE:
+            if (!parseTypeSpec(parser.getChunk())) {
+                return false;
+            }
+            break;
+
+        case android::RES_TABLE_TYPE_TYPE:
+            if (!parseType(parser.getChunk())) {
+                return false;
+            }
+            break;
+
+        default:
+            Logger::warn(mSource)
+                    << "unexpected chunk of type "
+                    << parser.getChunk()->type
+                    << "."
+                    << std::endl;
+            break;
+        }
+    }
+
+    if (parser.getEvent() == ResChunkPullParser::Event::BadDocument) {
+        Logger::error(mSource)
+                << "bad package: "
+                << parser.getLastError()
+                << "."
+                << std::endl;
+        return false;
+    }
+
+    // Now go through the table and change resource ID references to
+    // symbolic references.
+
+    ReferenceIdToNameVisitor visitor(mIdIndex);
+    for (auto& type : *mTable) {
+        for (auto& entry : type->entries) {
+            for (auto& configValue : entry->values) {
+                configValue.value->accept(visitor, {});
+            }
+        }
+    }
+    return true;
+}
+
+bool BinaryResourceParser::parseTypeSpec(const ResChunk_header* chunk) {
+    if (mTypePool.getError() != NO_ERROR) {
+        Logger::error(mSource)
+                << "no type string pool available for ResTable_typeSpec."
+                << std::endl;
+        return false;
+    }
+
+    const ResTable_typeSpec* typeSpec = convertTo<ResTable_typeSpec>(chunk);
+    if (!typeSpec) {
+        Logger::error(mSource)
+                << "could not parse chunk as ResTable_typeSpec."
+                << std::endl;
+        return false;
+    }
+
+    if (typeSpec->id == 0) {
+        Logger::error(mSource)
+                << "ResTable_typeSpec has invalid id: "
+                << typeSpec->id
+                << "."
+                << std::endl;
+        return false;
+    }
+    return true;
+}
+
+bool BinaryResourceParser::parseType(const ResChunk_header* chunk) {
+    if (mTypePool.getError() != NO_ERROR) {
+        Logger::error(mSource)
+                << "no type string pool available for ResTable_typeSpec."
+                << std::endl;
+        return false;
+    }
+
+    if (mKeyPool.getError() != NO_ERROR) {
+        Logger::error(mSource)
+                << "no key string pool available for ResTable_type."
+                << std::endl;
+        return false;
+    }
+
+    const ResTable_type* type = convertTo<ResTable_type>(chunk);
+    if (!type) {
+        Logger::error(mSource)
+                << "could not parse chunk as ResTable_type."
+                << std::endl;
+        return false;
+    }
+
+    if (type->id == 0) {
+        Logger::error(mSource)
+                << "ResTable_type has invalid id: "
+                << type->id
+                << "."
+                << std::endl;
+        return false;
+    }
+
+    const ConfigDescription config(type->config);
+    const StringPiece16 typeName = util::getString(mTypePool, type->id - 1);
+
+    const ResourceType* parsedType = parseResourceType(typeName);
+    if (!parsedType) {
+        Logger::error(mSource)
+                << "invalid type name '"
+                << typeName
+                << "' for type with ID "
+                << uint32_t(type->id)
+                << "." << std::endl;
+        return false;
+    }
+
+    android::TypeVariant tv(type);
+    for (auto it = tv.beginEntries(); it != tv.endEntries(); ++it) {
+        if (!*it) {
+            continue;
+        }
+
+        const ResTable_entry* entry = *it;
+        const ResourceName name = {
+                mTable->getPackage(),
+                *parsedType,
+                util::getString(mKeyPool, entry->key.index).toString()
+        };
+
+        const ResourceId resId = { mTable->getPackageId(), type->id, it.index() };
+
+        std::unique_ptr<Value> resourceValue;
+        const ResTable_entry_source* sourceBlock = nullptr;
+        if (entry->flags & ResTable_entry::FLAG_COMPLEX) {
+            const ResTable_map_entry* mapEntry = static_cast<const ResTable_map_entry*>(entry);
+            if (mapEntry->size - sizeof(*mapEntry) == sizeof(*sourceBlock)) {
+                const uint8_t* data = reinterpret_cast<const uint8_t*>(mapEntry);
+                data += mapEntry->size - sizeof(*sourceBlock);
+                sourceBlock = reinterpret_cast<const ResTable_entry_source*>(data);
+            }
+
+            // TODO(adamlesinski): Check that the entry count is valid.
+            resourceValue = parseMapEntry(name, config, mapEntry);
+        } else {
+            if (entry->size - sizeof(*entry) == sizeof(*sourceBlock)) {
+                const uint8_t* data = reinterpret_cast<const uint8_t*>(entry);
+                data += entry->size - sizeof(*sourceBlock);
+                sourceBlock = reinterpret_cast<const ResTable_entry_source*>(data);
+            }
+
+            const Res_value* value = reinterpret_cast<const Res_value*>(
+                    reinterpret_cast<const uint8_t*>(entry) + entry->size);
+            resourceValue = parseValue(name, config, value, entry->flags);
+        }
+
+        if (!resourceValue) {
+            // TODO(adamlesinski): For now this is ok, but it really shouldn't be.
+            continue;
+        }
+
+        SourceLine source = mSource.line(0);
+        if (sourceBlock) {
+            size_t len;
+            const char* str = mSourcePool.string8At(sourceBlock->pathIndex, &len);
+            if (str) {
+                source.path.assign(str, len);
+            }
+            source.line = sourceBlock->line;
+        }
+
+        if (!mTable->addResource(name, config, source, std::move(resourceValue))) {
+            return false;
+        }
+
+        if ((entry->flags & ResTable_entry::FLAG_PUBLIC) != 0) {
+            if (!mTable->markPublic(name, resId, mSource.line(0))) {
+                return false;
+            }
+        }
+
+        // Add this resource name->id mapping to the index so
+        // that we can resolve all ID references to name references.
+        auto cacheIter = mIdIndex.find(resId);
+        if (cacheIter == mIdIndex.end()) {
+            mIdIndex.insert({ resId, name });
+        }
+    }
+    return true;
+}
+
+std::unique_ptr<Item> BinaryResourceParser::parseValue(const ResourceNameRef& name,
+                                                       const ConfigDescription& config,
+                                                       const Res_value* value,
+                                                       uint16_t flags) {
+    if (value->dataType == Res_value::TYPE_STRING) {
+        StringPiece16 str = util::getString(mValuePool, value->data);
+
+        const ResStringPool_span* spans = mValuePool.styleAt(value->data);
+        if (spans != nullptr) {
+            StyleString styleStr = { str.toString() };
+            while (spans->name.index != ResStringPool_span::END) {
+                styleStr.spans.push_back(Span{
+                        util::getString(mValuePool, spans->name.index).toString(),
+                        spans->firstChar,
+                        spans->lastChar
+                });
+                spans++;
+            }
+            return util::make_unique<StyledString>(
+                    mTable->getValueStringPool().makeRef(
+                            styleStr, StringPool::Context{1, config}));
+        } else {
+            // There are no styles associated with this string, so treat it as
+            // a simple string.
+            return util::make_unique<String>(
+                    mTable->getValueStringPool().makeRef(
+                            str, StringPool::Context{1, config}));
+        }
+    }
+
+    if (value->dataType == Res_value::TYPE_REFERENCE ||
+            value->dataType == Res_value::TYPE_ATTRIBUTE) {
+        const Reference::Type type = (value->dataType == Res_value::TYPE_REFERENCE) ?
+                    Reference::Type::kResource : Reference::Type::kAttribute;
+
+        if (value->data != 0) {
+            // This is a normal reference.
+            return util::make_unique<Reference>(value->data, type);
+        }
+
+        // This reference has an invalid ID. Check if it is an unresolved symbol.
+        ResourceNameRef symbol;
+        if (getSymbol(&value->data, &symbol)) {
+            return util::make_unique<Reference>(symbol, type);
+        }
+
+        // This is not an unresolved symbol, so it must be the magic @null reference.
+        Res_value nullType = {};
+        nullType.dataType = Res_value::TYPE_NULL;
+        nullType.data = Res_value::DATA_NULL_UNDEFINED;
+        return util::make_unique<BinaryPrimitive>(nullType);
+    }
+
+    if (value->dataType == ExtendedTypes::TYPE_SENTINEL) {
+        return util::make_unique<Sentinel>();
+    }
+
+    if (value->dataType == ExtendedTypes::TYPE_RAW_STRING) {
+        return util::make_unique<RawString>(
+                mTable->getValueStringPool().makeRef(util::getString(mValuePool, value->data),
+                                                    StringPool::Context{ 1, config }));
+    }
+
+    if (name.type == ResourceType::kId ||
+            (value->dataType == Res_value::TYPE_NULL &&
+            value->data == Res_value::DATA_NULL_UNDEFINED &&
+            (flags & ResTable_entry::FLAG_WEAK) != 0)) {
+        return util::make_unique<Id>();
+    }
+
+    // Treat this as a raw binary primitive.
+    return util::make_unique<BinaryPrimitive>(*value);
+}
+
+std::unique_ptr<Value> BinaryResourceParser::parseMapEntry(const ResourceNameRef& name,
+                                                           const ConfigDescription& config,
+                                                           const ResTable_map_entry* map) {
+    switch (name.type) {
+        case ResourceType::kStyle:
+            return parseStyle(name, config, map);
+        case ResourceType::kAttr:
+            return parseAttr(name, config, map);
+        case ResourceType::kArray:
+            return parseArray(name, config, map);
+        case ResourceType::kStyleable:
+            return parseStyleable(name, config, map);
+        case ResourceType::kPlurals:
+            return parsePlural(name, config, map);
+        default:
+            break;
+    }
+    return {};
+}
+
+std::unique_ptr<Style> BinaryResourceParser::parseStyle(const ResourceNameRef& name,
+                                                        const ConfigDescription& config,
+                                                        const ResTable_map_entry* map) {
+    std::unique_ptr<Style> style = util::make_unique<Style>();
+    if (map->parent.ident == 0) {
+        // The parent is either not set or it is an unresolved symbol.
+        // Check to see if it is a symbol.
+        ResourceNameRef symbol;
+        if (getSymbol(&map->parent.ident, &symbol)) {
+            style->parent.name = symbol.toResourceName();
+        }
+    } else {
+         // The parent is a regular reference to a resource.
+        style->parent.id = map->parent.ident;
+    }
+
+    for (const ResTable_map& mapEntry : map) {
+        style->entries.emplace_back();
+        Style::Entry& styleEntry = style->entries.back();
+
+        if (mapEntry.name.ident == 0) {
+            // The map entry's key (attribute) is not set. This must be
+            // a symbol reference, so resolve it.
+            ResourceNameRef symbol;
+            bool result = getSymbol(&mapEntry.name.ident, &symbol);
+            assert(result);
+            styleEntry.key.name = symbol.toResourceName();
+        } else {
+            // The map entry's key (attribute) is a regular reference.
+            styleEntry.key.id = mapEntry.name.ident;
+        }
+
+        // Parse the attribute's value.
+        styleEntry.value = parseValue(name, config, &mapEntry.value, 0);
+        assert(styleEntry.value);
+    }
+    return style;
+}
+
+std::unique_ptr<Attribute> BinaryResourceParser::parseAttr(const ResourceNameRef& name,
+                                                           const ConfigDescription& config,
+                                                           const ResTable_map_entry* map) {
+    const bool isWeak = (map->flags & ResTable_entry::FLAG_WEAK) != 0;
+    std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(isWeak);
+
+    // First we must discover what type of attribute this is. Find the type mask.
+    auto typeMaskIter = std::find_if(begin(map), end(map), [](const ResTable_map& entry) -> bool {
+        return entry.name.ident == ResTable_map::ATTR_TYPE;
+    });
+
+    if (typeMaskIter != end(map)) {
+        attr->typeMask = typeMaskIter->value.data;
+    }
+
+    if (attr->typeMask & (ResTable_map::TYPE_ENUM | ResTable_map::TYPE_FLAGS)) {
+        for (const ResTable_map& mapEntry : map) {
+            if (Res_INTERNALID(mapEntry.name.ident)) {
+                continue;
+            }
+
+            attr->symbols.push_back(Attribute::Symbol{
+                    Reference(mapEntry.name.ident),
+                    mapEntry.value.data
+            });
+        }
+    }
+
+    // TODO(adamlesinski): Find min, max, i80n, etc attributes.
+    return attr;
+}
+
+std::unique_ptr<Array> BinaryResourceParser::parseArray(const ResourceNameRef& name,
+                                                        const ConfigDescription& config,
+                                                        const ResTable_map_entry* map) {
+    std::unique_ptr<Array> array = util::make_unique<Array>();
+    for (const ResTable_map& mapEntry : map) {
+        array->items.push_back(parseValue(name, config, &mapEntry.value, 0));
+    }
+    return array;
+}
+
+std::unique_ptr<Styleable> BinaryResourceParser::parseStyleable(const ResourceNameRef& name,
+                                                                const ConfigDescription& config,
+                                                                const ResTable_map_entry* map) {
+    std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
+    for (const ResTable_map& mapEntry : map) {
+        styleable->entries.emplace_back(mapEntry.name.ident);
+    }
+    return styleable;
+}
+
+std::unique_ptr<Plural> BinaryResourceParser::parsePlural(const ResourceNameRef& name,
+                                                          const ConfigDescription& config,
+                                                          const ResTable_map_entry* map) {
+    std::unique_ptr<Plural> plural = util::make_unique<Plural>();
+    for (const ResTable_map& mapEntry : map) {
+        std::unique_ptr<Item> item = parseValue(name, config, &mapEntry.value, 0);
+
+        switch (mapEntry.name.ident) {
+            case android::ResTable_map::ATTR_ZERO:
+                plural->values[Plural::Zero] = std::move(item);
+                break;
+            case android::ResTable_map::ATTR_ONE:
+                plural->values[Plural::One] = std::move(item);
+                break;
+            case android::ResTable_map::ATTR_TWO:
+                plural->values[Plural::Two] = std::move(item);
+                break;
+            case android::ResTable_map::ATTR_FEW:
+                plural->values[Plural::Few] = std::move(item);
+                break;
+            case android::ResTable_map::ATTR_MANY:
+                plural->values[Plural::Many] = std::move(item);
+                break;
+            case android::ResTable_map::ATTR_OTHER:
+                plural->values[Plural::Other] = std::move(item);
+                break;
+        }
+    }
+    return plural;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/BinaryResourceParser.h b/tools/aapt2/BinaryResourceParser.h
new file mode 100644
index 0000000..9268078
--- /dev/null
+++ b/tools/aapt2/BinaryResourceParser.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_BINARY_RESOURCE_PARSER_H
+#define AAPT_BINARY_RESOURCE_PARSER_H
+
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "Source.h"
+
+#include <androidfw/ResourceTypes.h>
+#include <string>
+
+namespace aapt {
+
+struct SymbolTable_entry;
+
+/*
+ * Parses a binary resource table (resources.arsc) and adds the entries
+ * to a ResourceTable. This is different than the libandroidfw ResTable
+ * in that it scans the table from top to bottom and doesn't require
+ * support for random access. It is also able to parse non-runtime
+ * chunks and types.
+ */
+class BinaryResourceParser {
+public:
+    /*
+     * Creates a parser, which will read `len` bytes from `data`, and
+     * add any resources parsed to `table`. `source` is for logging purposes.
+     */
+    BinaryResourceParser(std::shared_ptr<ResourceTable> table, const Source& source,
+                         const void* data, size_t len);
+
+    BinaryResourceParser(const BinaryResourceParser&) = delete; // No copy.
+
+    /*
+     * Parses the binary resource table and returns true if successful.
+     */
+    bool parse();
+
+private:
+    // Helper method to retrieve the symbol name for a given table offset specified
+    // as a pointer.
+    bool getSymbol(const void* data, ResourceNameRef* outSymbol);
+
+    bool parseTable(const android::ResChunk_header* chunk);
+    bool parseSymbolTable(const android::ResChunk_header* chunk);
+
+    // Looks up the resource ID in the reference and converts it to a name if available.
+    bool idToName(Reference* reference);
+
+    bool parsePackage(const android::ResChunk_header* chunk);
+    bool parseTypeSpec(const android::ResChunk_header* chunk);
+    bool parseType(const android::ResChunk_header* chunk);
+
+    std::unique_ptr<Item> parseValue(const ResourceNameRef& name,
+            const ConfigDescription& config, const android::Res_value* value, uint16_t flags);
+
+    std::unique_ptr<Value> parseMapEntry(const ResourceNameRef& name,
+            const ConfigDescription& config, const android::ResTable_map_entry* map);
+
+    std::unique_ptr<Style> parseStyle(const ResourceNameRef& name,
+            const ConfigDescription& config, const android::ResTable_map_entry* map);
+
+    std::unique_ptr<Attribute> parseAttr(const ResourceNameRef& name,
+            const ConfigDescription& config, const android::ResTable_map_entry* map);
+
+    std::unique_ptr<Array> parseArray(const ResourceNameRef& name,
+            const ConfigDescription& config, const android::ResTable_map_entry* map);
+
+    std::unique_ptr<Plural> parsePlural(const ResourceNameRef& name,
+            const ConfigDescription& config, const android::ResTable_map_entry* map);
+
+    std::unique_ptr<Styleable> parseStyleable(const ResourceNameRef& name,
+            const ConfigDescription& config, const android::ResTable_map_entry* map);
+
+    std::shared_ptr<ResourceTable> mTable;
+
+    const Source mSource;
+
+    const void* mData;
+    const size_t mDataLen;
+
+    // The package name of the resource table.
+    std::u16string mPackage;
+
+    // The array of symbol entries. Each element points to an offset
+    // in the table and an index into the symbol table string pool.
+    const SymbolTable_entry* mSymbolEntries = nullptr;
+
+    // Number of symbol entries.
+    size_t mSymbolEntryCount = 0;
+
+    // The symbol table string pool. Holds the names of symbols
+    // referenced in this table but not defined nor resolved to an
+    // ID.
+    android::ResStringPool mSymbolPool;
+
+    // The source string pool. Resource entries may have an extra
+    // field that points into this string pool, which denotes where
+    // the resource was parsed from originally.
+    android::ResStringPool mSourcePool;
+
+    // The standard value string pool for resource values.
+    android::ResStringPool mValuePool;
+
+    // The string pool that holds the names of the types defined
+    // in this table.
+    android::ResStringPool mTypePool;
+
+    // The string pool that holds the names of the entries defined
+    // in this table.
+    android::ResStringPool mKeyPool;
+
+    // A mapping of resource ID to resource name. When we finish parsing
+    // we use this to convert all resource IDs to symbolic references.
+    std::map<ResourceId, ResourceName> mIdIndex;
+};
+
+} // namespace aapt
+
+namespace android {
+
+/**
+ * Iterator functionality for ResTable_map_entry.
+ */
+
+inline const ResTable_map* begin(const ResTable_map_entry* map) {
+    return reinterpret_cast<const ResTable_map*>(
+            reinterpret_cast<const uint8_t*>(map) + map->size);
+}
+
+inline const ResTable_map* end(const ResTable_map_entry* map) {
+    return reinterpret_cast<const ResTable_map*>(
+            reinterpret_cast<const uint8_t*>(map) + map->size) + map->count;
+}
+
+} // namespace android
+
+#endif // AAPT_BINARY_RESOURCE_PARSER_H
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/tools/aapt2/Compat_test.cpp
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to tools/aapt2/Compat_test.cpp
index 272c321..96aee44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/tools/aapt2/Compat_test.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * 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.
@@ -14,8 +14,20 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
+#include <gtest/gtest.h>
 
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
+namespace aapt {
+
+TEST(CompatTest, VersionAttributesInStyle) {
 }
+
+TEST(CompatTest, VersionAttributesInXML) {
+}
+
+TEST(CompatTest, DoNotOverrideExistingVersionedFiles) {
+}
+
+TEST(CompatTest, VersionAttributesInStyleWithCorrectPrecedence) {
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ConfigDescription.cpp b/tools/aapt2/ConfigDescription.cpp
new file mode 100644
index 0000000..6ddf94a
--- /dev/null
+++ b/tools/aapt2/ConfigDescription.cpp
@@ -0,0 +1,752 @@
+/*
+ * 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.
+ */
+
+#include "ConfigDescription.h"
+#include "Locale.h"
+#include "SdkConstants.h"
+#include "StringPiece.h"
+#include "Util.h"
+
+#include <androidfw/ResourceTypes.h>
+#include <string>
+#include <vector>
+
+namespace aapt {
+
+using android::ResTable_config;
+
+static const char* kWildcardName = "any";
+
+static bool parseMcc(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->mcc = 0;
+        return true;
+    }
+    const char* c = name;
+    if (tolower(*c) != 'm') return false;
+    c++;
+    if (tolower(*c) != 'c') return false;
+    c++;
+    if (tolower(*c) != 'c') return false;
+    c++;
+
+    const char* val = c;
+
+    while (*c >= '0' && *c <= '9') {
+        c++;
+    }
+    if (*c != 0) return false;
+    if (c-val != 3) return false;
+
+    int d = atoi(val);
+    if (d != 0) {
+        if (out) out->mcc = d;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseMnc(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->mcc = 0;
+        return true;
+    }
+    const char* c = name;
+    if (tolower(*c) != 'm') return false;
+    c++;
+    if (tolower(*c) != 'n') return false;
+    c++;
+    if (tolower(*c) != 'c') return false;
+    c++;
+
+    const char* val = c;
+
+    while (*c >= '0' && *c <= '9') {
+        c++;
+    }
+    if (*c != 0) return false;
+    if (c-val == 0 || c-val > 3) return false;
+
+    if (out) {
+        out->mnc = atoi(val);
+        if (out->mnc == 0) {
+            out->mnc = ACONFIGURATION_MNC_ZERO;
+        }
+    }
+
+    return true;
+}
+
+static bool parseLayoutDirection(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
+                | ResTable_config::LAYOUTDIR_ANY;
+        return true;
+    } else if (strcmp(name, "ldltr") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
+                | ResTable_config::LAYOUTDIR_LTR;
+        return true;
+    } else if (strcmp(name, "ldrtl") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
+                | ResTable_config::LAYOUTDIR_RTL;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseScreenLayoutSize(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
+                | ResTable_config::SCREENSIZE_ANY;
+        return true;
+    } else if (strcmp(name, "small") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
+                | ResTable_config::SCREENSIZE_SMALL;
+        return true;
+    } else if (strcmp(name, "normal") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
+                | ResTable_config::SCREENSIZE_NORMAL;
+        return true;
+    } else if (strcmp(name, "large") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
+                | ResTable_config::SCREENSIZE_LARGE;
+        return true;
+    } else if (strcmp(name, "xlarge") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
+                | ResTable_config::SCREENSIZE_XLARGE;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseScreenLayoutLong(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
+                | ResTable_config::SCREENLONG_ANY;
+        return true;
+    } else if (strcmp(name, "long") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
+                | ResTable_config::SCREENLONG_YES;
+        return true;
+    } else if (strcmp(name, "notlong") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
+                | ResTable_config::SCREENLONG_NO;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseOrientation(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->orientation = out->ORIENTATION_ANY;
+        return true;
+    } else if (strcmp(name, "port") == 0) {
+        if (out) out->orientation = out->ORIENTATION_PORT;
+        return true;
+    } else if (strcmp(name, "land") == 0) {
+        if (out) out->orientation = out->ORIENTATION_LAND;
+        return true;
+    } else if (strcmp(name, "square") == 0) {
+        if (out) out->orientation = out->ORIENTATION_SQUARE;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseUiModeType(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->uiMode =
+                (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+                | ResTable_config::UI_MODE_TYPE_ANY;
+        return true;
+    } else if (strcmp(name, "desk") == 0) {
+      if (out) out->uiMode =
+              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+              | ResTable_config::UI_MODE_TYPE_DESK;
+        return true;
+    } else if (strcmp(name, "car") == 0) {
+      if (out) out->uiMode =
+              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+              | ResTable_config::UI_MODE_TYPE_CAR;
+        return true;
+    } else if (strcmp(name, "television") == 0) {
+      if (out) out->uiMode =
+              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+              | ResTable_config::UI_MODE_TYPE_TELEVISION;
+        return true;
+    } else if (strcmp(name, "appliance") == 0) {
+      if (out) out->uiMode =
+              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+              | ResTable_config::UI_MODE_TYPE_APPLIANCE;
+        return true;
+    } else if (strcmp(name, "watch") == 0) {
+      if (out) out->uiMode =
+              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+              | ResTable_config::UI_MODE_TYPE_WATCH;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseUiModeNight(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->uiMode =
+                (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
+                | ResTable_config::UI_MODE_NIGHT_ANY;
+        return true;
+    } else if (strcmp(name, "night") == 0) {
+        if (out) out->uiMode =
+                (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
+                | ResTable_config::UI_MODE_NIGHT_YES;
+        return true;
+    } else if (strcmp(name, "notnight") == 0) {
+      if (out) out->uiMode =
+              (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
+              | ResTable_config::UI_MODE_NIGHT_NO;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseDensity(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->density = ResTable_config::DENSITY_DEFAULT;
+        return true;
+    }
+
+    if (strcmp(name, "anydpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_ANY;
+        return true;
+    }
+
+    if (strcmp(name, "nodpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_NONE;
+        return true;
+    }
+
+    if (strcmp(name, "ldpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_LOW;
+        return true;
+    }
+
+    if (strcmp(name, "mdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_MEDIUM;
+        return true;
+    }
+
+    if (strcmp(name, "tvdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_TV;
+        return true;
+    }
+
+    if (strcmp(name, "hdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_HIGH;
+        return true;
+    }
+
+    if (strcmp(name, "xhdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_XHIGH;
+        return true;
+    }
+
+    if (strcmp(name, "xxhdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_XXHIGH;
+        return true;
+    }
+
+    if (strcmp(name, "xxxhdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_XXXHIGH;
+        return true;
+    }
+
+    char* c = (char*)name;
+    while (*c >= '0' && *c <= '9') {
+        c++;
+    }
+
+    // check that we have 'dpi' after the last digit.
+    if (toupper(c[0]) != 'D' ||
+            toupper(c[1]) != 'P' ||
+            toupper(c[2]) != 'I' ||
+            c[3] != 0) {
+        return false;
+    }
+
+    // temporarily replace the first letter with \0 to
+    // use atoi.
+    char tmp = c[0];
+    c[0] = '\0';
+
+    int d = atoi(name);
+    c[0] = tmp;
+
+    if (d != 0) {
+        if (out) out->density = d;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseTouchscreen(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->touchscreen = out->TOUCHSCREEN_ANY;
+        return true;
+    } else if (strcmp(name, "notouch") == 0) {
+        if (out) out->touchscreen = out->TOUCHSCREEN_NOTOUCH;
+        return true;
+    } else if (strcmp(name, "stylus") == 0) {
+        if (out) out->touchscreen = out->TOUCHSCREEN_STYLUS;
+        return true;
+    } else if (strcmp(name, "finger") == 0) {
+        if (out) out->touchscreen = out->TOUCHSCREEN_FINGER;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseKeysHidden(const char* name, ResTable_config* out) {
+    uint8_t mask = 0;
+    uint8_t value = 0;
+    if (strcmp(name, kWildcardName) == 0) {
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_ANY;
+    } else if (strcmp(name, "keysexposed") == 0) {
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_NO;
+    } else if (strcmp(name, "keyshidden") == 0) {
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_YES;
+    } else if (strcmp(name, "keyssoft") == 0) {
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_SOFT;
+    }
+
+    if (mask != 0) {
+        if (out) out->inputFlags = (out->inputFlags&~mask) | value;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseKeyboard(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->keyboard = out->KEYBOARD_ANY;
+        return true;
+    } else if (strcmp(name, "nokeys") == 0) {
+        if (out) out->keyboard = out->KEYBOARD_NOKEYS;
+        return true;
+    } else if (strcmp(name, "qwerty") == 0) {
+        if (out) out->keyboard = out->KEYBOARD_QWERTY;
+        return true;
+    } else if (strcmp(name, "12key") == 0) {
+        if (out) out->keyboard = out->KEYBOARD_12KEY;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseNavHidden(const char* name, ResTable_config* out) {
+    uint8_t mask = 0;
+    uint8_t value = 0;
+    if (strcmp(name, kWildcardName) == 0) {
+        mask = ResTable_config::MASK_NAVHIDDEN;
+        value = ResTable_config::NAVHIDDEN_ANY;
+    } else if (strcmp(name, "navexposed") == 0) {
+        mask = ResTable_config::MASK_NAVHIDDEN;
+        value = ResTable_config::NAVHIDDEN_NO;
+    } else if (strcmp(name, "navhidden") == 0) {
+        mask = ResTable_config::MASK_NAVHIDDEN;
+        value = ResTable_config::NAVHIDDEN_YES;
+    }
+
+    if (mask != 0) {
+        if (out) out->inputFlags = (out->inputFlags&~mask) | value;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseNavigation(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->navigation = out->NAVIGATION_ANY;
+        return true;
+    } else if (strcmp(name, "nonav") == 0) {
+        if (out) out->navigation = out->NAVIGATION_NONAV;
+        return true;
+    } else if (strcmp(name, "dpad") == 0) {
+        if (out) out->navigation = out->NAVIGATION_DPAD;
+        return true;
+    } else if (strcmp(name, "trackball") == 0) {
+        if (out) out->navigation = out->NAVIGATION_TRACKBALL;
+        return true;
+    } else if (strcmp(name, "wheel") == 0) {
+        if (out) out->navigation = out->NAVIGATION_WHEEL;
+        return true;
+    }
+
+    return false;
+}
+
+static bool parseScreenSize(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) {
+            out->screenWidth = out->SCREENWIDTH_ANY;
+            out->screenHeight = out->SCREENHEIGHT_ANY;
+        }
+        return true;
+    }
+
+    const char* x = name;
+    while (*x >= '0' && *x <= '9') x++;
+    if (x == name || *x != 'x') return false;
+    std::string xName(name, x-name);
+    x++;
+
+    const char* y = x;
+    while (*y >= '0' && *y <= '9') y++;
+    if (y == name || *y != 0) return false;
+    std::string yName(x, y-x);
+
+    uint16_t w = (uint16_t)atoi(xName.c_str());
+    uint16_t h = (uint16_t)atoi(yName.c_str());
+    if (w < h) {
+        return false;
+    }
+
+    if (out) {
+        out->screenWidth = w;
+        out->screenHeight = h;
+    }
+
+    return true;
+}
+
+static bool parseSmallestScreenWidthDp(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) {
+            out->smallestScreenWidthDp = out->SCREENWIDTH_ANY;
+        }
+        return true;
+    }
+
+    if (*name != 's') return false;
+    name++;
+    if (*name != 'w') return false;
+    name++;
+    const char* x = name;
+    while (*x >= '0' && *x <= '9') x++;
+    if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
+    std::string xName(name, x-name);
+
+    if (out) {
+        out->smallestScreenWidthDp = (uint16_t)atoi(xName.c_str());
+    }
+
+    return true;
+}
+
+static bool parseScreenWidthDp(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) {
+            out->screenWidthDp = out->SCREENWIDTH_ANY;
+        }
+        return true;
+    }
+
+    if (*name != 'w') return false;
+    name++;
+    const char* x = name;
+    while (*x >= '0' && *x <= '9') x++;
+    if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
+    std::string xName(name, x-name);
+
+    if (out) {
+        out->screenWidthDp = (uint16_t)atoi(xName.c_str());
+    }
+
+    return true;
+}
+
+static bool parseScreenHeightDp(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) {
+            out->screenHeightDp = out->SCREENWIDTH_ANY;
+        }
+        return true;
+    }
+
+    if (*name != 'h') return false;
+    name++;
+    const char* x = name;
+    while (*x >= '0' && *x <= '9') x++;
+    if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
+    std::string xName(name, x-name);
+
+    if (out) {
+        out->screenHeightDp = (uint16_t)atoi(xName.c_str());
+    }
+
+    return true;
+}
+
+static bool parseVersion(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) {
+            out->sdkVersion = out->SDKVERSION_ANY;
+            out->minorVersion = out->MINORVERSION_ANY;
+        }
+        return true;
+    }
+
+    if (*name != 'v') {
+        return false;
+    }
+
+    name++;
+    const char* s = name;
+    while (*s >= '0' && *s <= '9') s++;
+    if (s == name || *s != 0) return false;
+    std::string sdkName(name, s-name);
+
+    if (out) {
+        out->sdkVersion = (uint16_t)atoi(sdkName.c_str());
+        out->minorVersion = 0;
+    }
+
+    return true;
+}
+
+bool ConfigDescription::parse(const StringPiece& str, ConfigDescription* out) {
+    std::vector<std::string> parts = util::splitAndLowercase(str, '-');
+
+    ConfigDescription config;
+    ssize_t partsConsumed = 0;
+    LocaleValue locale;
+
+    const auto partsEnd = parts.end();
+    auto partIter = parts.begin();
+
+    if (str.size() == 0) {
+        goto success;
+    }
+
+    if (parseMcc(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseMnc(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    // Locale spans a few '-' separators, so we let it
+    // control the index.
+    partsConsumed = locale.initFromParts(partIter, partsEnd);
+    if (partsConsumed < 0) {
+        return false;
+    } else {
+        locale.writeTo(&config);
+        partIter += partsConsumed;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseLayoutDirection(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseSmallestScreenWidthDp(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseScreenWidthDp(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseScreenHeightDp(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseScreenLayoutSize(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseScreenLayoutLong(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseOrientation(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseUiModeType(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseUiModeNight(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseDensity(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseTouchscreen(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseKeysHidden(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseKeyboard(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseNavHidden(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseNavigation(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseScreenSize(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    if (parseVersion(partIter->c_str(), &config)) {
+        ++partIter;
+        if (partIter == partsEnd) {
+            goto success;
+        }
+    }
+
+    // Unrecognized.
+    return false;
+
+success:
+    if (out != NULL) {
+        applyVersionForCompatibility(&config);
+        *out = config;
+    }
+    return true;
+}
+
+void ConfigDescription::applyVersionForCompatibility(ConfigDescription* config) {
+    uint16_t minSdk = 0;
+    if (config->density == ResTable_config::DENSITY_ANY) {
+        minSdk = SDK_LOLLIPOP;
+    } else if (config->smallestScreenWidthDp != ResTable_config::SCREENWIDTH_ANY
+            || config->screenWidthDp != ResTable_config::SCREENWIDTH_ANY
+            || config->screenHeightDp != ResTable_config::SCREENHEIGHT_ANY) {
+        minSdk = SDK_HONEYCOMB_MR2;
+    } else if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE)
+                != ResTable_config::UI_MODE_TYPE_ANY
+            ||  (config->uiMode & ResTable_config::MASK_UI_MODE_NIGHT)
+                != ResTable_config::UI_MODE_NIGHT_ANY) {
+        minSdk = SDK_FROYO;
+    } else if ((config->screenLayout & ResTable_config::MASK_SCREENSIZE)
+                != ResTable_config::SCREENSIZE_ANY
+            ||  (config->screenLayout & ResTable_config::MASK_SCREENLONG)
+                != ResTable_config::SCREENLONG_ANY
+            || config->density != ResTable_config::DENSITY_DEFAULT) {
+        minSdk = SDK_DONUT;
+    }
+
+    if (minSdk > config->sdkVersion) {
+        config->sdkVersion = minSdk;
+    }
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h
new file mode 100644
index 0000000..67b4b75
--- /dev/null
+++ b/tools/aapt2/ConfigDescription.h
@@ -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.
+ */
+
+#ifndef AAPT_CONFIG_DESCRIPTION_H
+#define AAPT_CONFIG_DESCRIPTION_H
+
+#include "StringPiece.h"
+
+#include <androidfw/ResourceTypes.h>
+#include <ostream>
+
+namespace aapt {
+
+/*
+ * Subclass of ResTable_config that adds convenient
+ * initialization and comparison methods.
+ */
+struct ConfigDescription : public android::ResTable_config {
+    /*
+     * Parse a string of the form 'fr-sw600dp-land' and fill in the
+     * given ResTable_config with resulting configuration parameters.
+     *
+     * The resulting configuration has the appropriate sdkVersion defined
+     * for backwards compatibility.
+     */
+    static bool parse(const StringPiece& str, ConfigDescription* out = nullptr);
+
+    /**
+     * If the configuration uses an axis that was added after
+     * the original Android release, make sure the SDK version
+     * is set accordingly.
+     */
+    static void applyVersionForCompatibility(ConfigDescription* config);
+
+    ConfigDescription();
+    ConfigDescription(const android::ResTable_config& o);
+    ConfigDescription(const ConfigDescription& o);
+    ConfigDescription(ConfigDescription&& o);
+
+    ConfigDescription& operator=(const android::ResTable_config& o);
+    ConfigDescription& operator=(const ConfigDescription& o);
+    ConfigDescription& operator=(ConfigDescription&& o);
+
+    bool operator<(const ConfigDescription& o) const;
+    bool operator<=(const ConfigDescription& o) const;
+    bool operator==(const ConfigDescription& o) const;
+    bool operator!=(const ConfigDescription& o) const;
+    bool operator>=(const ConfigDescription& o) const;
+    bool operator>(const ConfigDescription& o) const;
+};
+
+inline ConfigDescription::ConfigDescription() {
+    memset(this, 0, sizeof(*this));
+    size = sizeof(android::ResTable_config);
+}
+
+inline ConfigDescription::ConfigDescription(const android::ResTable_config& o) {
+    *static_cast<android::ResTable_config*>(this) = o;
+    size = sizeof(android::ResTable_config);
+}
+
+inline ConfigDescription::ConfigDescription(const ConfigDescription& o) {
+    *static_cast<android::ResTable_config*>(this) = o;
+}
+
+inline ConfigDescription::ConfigDescription(ConfigDescription&& o) {
+    *this = o;
+}
+
+inline ConfigDescription& ConfigDescription::operator=(const android::ResTable_config& o) {
+    *static_cast<android::ResTable_config*>(this) = o;
+    size = sizeof(android::ResTable_config);
+    return *this;
+}
+
+inline ConfigDescription& ConfigDescription::operator=(const ConfigDescription& o) {
+    *static_cast<android::ResTable_config*>(this) = o;
+    return *this;
+}
+
+inline ConfigDescription& ConfigDescription::operator=(ConfigDescription&& o) {
+    *this = o;
+    return *this;
+}
+
+inline bool ConfigDescription::operator<(const ConfigDescription& o) const {
+    return compare(o) < 0;
+}
+
+inline bool ConfigDescription::operator<=(const ConfigDescription& o) const {
+    return compare(o) <= 0;
+}
+
+inline bool ConfigDescription::operator==(const ConfigDescription& o) const {
+    return compare(o) == 0;
+}
+
+inline bool ConfigDescription::operator!=(const ConfigDescription& o) const {
+    return compare(o) != 0;
+}
+
+inline bool ConfigDescription::operator>=(const ConfigDescription& o) const {
+    return compare(o) >= 0;
+}
+
+inline bool ConfigDescription::operator>(const ConfigDescription& o) const {
+    return compare(o) > 0;
+}
+
+inline ::std::ostream& operator<<(::std::ostream& out, const ConfigDescription& o) {
+    return out << o.toString().string();
+}
+
+} // namespace aapt
+
+#endif // AAPT_CONFIG_DESCRIPTION_H
diff --git a/tools/aapt2/ConfigDescription_test.cpp b/tools/aapt2/ConfigDescription_test.cpp
new file mode 100644
index 0000000..c57e351
--- /dev/null
+++ b/tools/aapt2/ConfigDescription_test.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#include "ConfigDescription.h"
+#include "StringPiece.h"
+
+#include <gtest/gtest.h>
+#include <string>
+
+namespace aapt {
+
+static ::testing::AssertionResult TestParse(const StringPiece& input,
+                                            ConfigDescription* config = nullptr) {
+    if (ConfigDescription::parse(input, config)) {
+        return ::testing::AssertionSuccess() << input << " was successfully parsed";
+    }
+    return ::testing::AssertionFailure() << input << " could not be parsed";
+}
+
+TEST(ConfigDescriptionTest, ParseFailWhenQualifiersAreOutOfOrder) {
+    EXPECT_FALSE(TestParse("en-sw600dp-ldrtl"));
+    EXPECT_FALSE(TestParse("land-en"));
+    EXPECT_FALSE(TestParse("hdpi-320dpi"));
+}
+
+TEST(ConfigDescriptionTest, ParseFailWhenQualifiersAreNotMatched) {
+    EXPECT_FALSE(TestParse("en-sw600dp-ILLEGAL"));
+}
+
+TEST(ConfigDescriptionTest, ParseFailWhenQualifiersHaveTrailingDash) {
+    EXPECT_FALSE(TestParse("en-sw600dp-land-"));
+}
+
+TEST(ConfigDescriptionTest, ParseBasicQualifiers) {
+    ConfigDescription config;
+    EXPECT_TRUE(TestParse("", &config));
+    EXPECT_EQ(std::string(""), config.toString().string());
+
+    EXPECT_TRUE(TestParse("fr-land", &config));
+    EXPECT_EQ(std::string("fr-land"), config.toString().string());
+
+    EXPECT_TRUE(TestParse("mcc310-pl-sw720dp-normal-long-port-night-"
+                "xhdpi-keyssoft-qwerty-navexposed-nonav", &config));
+    EXPECT_EQ(std::string("mcc310-pl-sw720dp-normal-long-port-night-"
+                "xhdpi-keyssoft-qwerty-navexposed-nonav-v13"), config.toString().string());
+}
+
+TEST(ConfigDescriptionTest, ParseLocales) {
+    ConfigDescription config;
+    EXPECT_TRUE(TestParse("en-rUS", &config));
+    EXPECT_EQ(std::string("en-rUS"), config.toString().string());
+}
+
+TEST(ConfigDescriptionTest, ParseQualifierAddedInApi13) {
+    ConfigDescription config;
+    EXPECT_TRUE(TestParse("sw600dp", &config));
+    EXPECT_EQ(std::string("sw600dp-v13"), config.toString().string());
+
+    EXPECT_TRUE(TestParse("sw600dp-v8", &config));
+    EXPECT_EQ(std::string("sw600dp-v13"), config.toString().string());
+}
+
+TEST(ConfigDescriptionTest, ParseCarAttribute) {
+    ConfigDescription config;
+    EXPECT_TRUE(TestParse("car", &config));
+    EXPECT_EQ(android::ResTable_config::UI_MODE_TYPE_CAR, config.uiMode);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/Files.cpp b/tools/aapt2/Files.cpp
new file mode 100644
index 0000000..349abbd
--- /dev/null
+++ b/tools/aapt2/Files.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+#include "Files.h"
+#include "Util.h"
+
+#include <cerrno>
+#include <dirent.h>
+#include <string>
+#include <sys/stat.h>
+
+#ifdef HAVE_MS_C_RUNTIME
+// Windows includes.
+#include <direct.h>
+#endif
+
+namespace aapt {
+
+FileType getFileType(const StringPiece& path) {
+    struct stat sb;
+    if (stat(path.data(), &sb) < 0) {
+        if (errno == ENOENT || errno == ENOTDIR) {
+            return FileType::kNonexistant;
+        }
+        return FileType::kUnknown;
+    }
+
+    if (S_ISREG(sb.st_mode)) {
+        return FileType::kRegular;
+    } else if (S_ISDIR(sb.st_mode)) {
+        return FileType::kDirectory;
+    } else if (S_ISCHR(sb.st_mode)) {
+        return FileType::kCharDev;
+    } else if (S_ISBLK(sb.st_mode)) {
+        return FileType::kBlockDev;
+    } else if (S_ISFIFO(sb.st_mode)) {
+        return FileType::kFifo;
+#if defined(S_ISLNK)
+    } else if (S_ISLNK(sb.st_mode)) {
+        return FileType::kSymlink;
+#endif
+#if defined(S_ISSOCK)
+    } else if (S_ISSOCK(sb.st_mode)) {
+        return FileType::kSocket;
+#endif
+    } else {
+        return FileType::kUnknown;
+    }
+}
+
+std::vector<std::string> listFiles(const StringPiece& root) {
+    DIR* dir = opendir(root.data());
+    if (dir == nullptr) {
+        Logger::error(Source{ root.toString() })
+            << "unable to open file: "
+            << strerror(errno)
+            << "."
+            << std::endl;
+        return {};
+    }
+
+    std::vector<std::string> files;
+    dirent* entry;
+    while ((entry = readdir(dir))) {
+        files.emplace_back(entry->d_name);
+    }
+
+    closedir(dir);
+    return files;
+}
+
+inline static int mkdirImpl(const StringPiece& path) {
+#ifdef HAVE_MS_C_RUNTIME
+    return _mkdir(path.toString().c_str());
+#else
+    return mkdir(path.toString().c_str(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP);
+#endif
+}
+
+bool mkdirs(const StringPiece& path) {
+    const char* start = path.begin();
+    const char* end = path.end();
+    for (const char* current = start; current != end; ++current) {
+        if (*current == sDirSep) {
+            StringPiece parentPath(start, current - start);
+            int result = mkdirImpl(parentPath);
+            if (result < 0 && errno != EEXIST) {
+                return false;
+            }
+        }
+    }
+    return mkdirImpl(path) == 0 || errno == EEXIST;
+}
+
+bool FileFilter::setPattern(const StringPiece& pattern) {
+    mPatternTokens = util::splitAndLowercase(pattern, ':');
+    return true;
+}
+
+bool FileFilter::operator()(const std::string& filename, FileType type) const {
+    if (filename == "." || filename == "..") {
+        return false;
+    }
+
+    const char kDir[] = "dir";
+    const char kFile[] = "file";
+    const size_t filenameLen = filename.length();
+    bool chatty = true;
+    for (const std::string& token : mPatternTokens) {
+        const char* tokenStr = token.c_str();
+        if (*tokenStr == '!') {
+            chatty = false;
+            tokenStr++;
+        }
+
+        if (strncasecmp(tokenStr, kDir, sizeof(kDir)) == 0) {
+            if (type != FileType::kDirectory) {
+                continue;
+            }
+            tokenStr += sizeof(kDir);
+        }
+
+        if (strncasecmp(tokenStr, kFile, sizeof(kFile)) == 0) {
+            if (type != FileType::kRegular) {
+                continue;
+            }
+            tokenStr += sizeof(kFile);
+        }
+
+        bool ignore = false;
+        size_t n = strlen(tokenStr);
+        if (*tokenStr == '*') {
+            // Math suffix.
+            tokenStr++;
+            n--;
+            if (n <= filenameLen) {
+                ignore = strncasecmp(tokenStr, filename.c_str() + filenameLen - n, n) == 0;
+            }
+        } else if (n > 1 && tokenStr[n - 1] == '*') {
+            // Match prefix.
+            ignore = strncasecmp(tokenStr, filename.c_str(), n - 1) == 0;
+        } else {
+            ignore = strcasecmp(tokenStr, filename.c_str()) == 0;
+        }
+
+        if (ignore) {
+            if (chatty) {
+                Logger::warn()
+                    << "skipping " <<
+                    (type == FileType::kDirectory ? "dir '" : "file '")
+                    << filename
+                    << "' due to ignore pattern '"
+                    << token
+                    << "'."
+                    << std::endl;
+            }
+            return false;
+        }
+    }
+    return true;
+}
+
+
+} // namespace aapt
diff --git a/tools/aapt2/Files.h b/tools/aapt2/Files.h
new file mode 100644
index 0000000..37e6f8c
--- /dev/null
+++ b/tools/aapt2/Files.h
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_FILES_H
+#define AAPT_FILES_H
+
+#include "Logger.h"
+#include "Source.h"
+#include "StringPiece.h"
+
+#include <cassert>
+#include <string>
+#include <vector>
+
+namespace aapt {
+
+#ifdef _WIN32
+constexpr const char sDirSep = '\\';
+#else
+constexpr const char sDirSep = '/';
+#endif
+
+enum class FileType {
+    kUnknown = 0,
+    kNonexistant,
+    kRegular,
+    kDirectory,
+    kCharDev,
+    kBlockDev,
+    kFifo,
+    kSymlink,
+    kSocket,
+};
+
+FileType getFileType(const StringPiece& path);
+
+/*
+ * Lists files under the directory `root`. Files are listed
+ * with just their leaf (filename) names.
+ */
+std::vector<std::string> listFiles(const StringPiece& root);
+
+/*
+ * Appends a path to `base`, separated by the directory separator.
+ */
+void appendPath(std::string* base, const StringPiece& part);
+
+/*
+ * Appends a series of paths to `base`, separated by the
+ * system directory separator.
+ */
+template <typename... Ts >
+void appendPath(std::string* base, const StringPiece& part, const Ts&... parts);
+
+/*
+ * Makes all the directories in `path`. The last element in the path
+ * is interpreted as a directory.
+ */
+bool mkdirs(const StringPiece& path);
+
+/*
+ * Filter that determines which resource files/directories are
+ * processed by AAPT. Takes a pattern string supplied by the user.
+ * Pattern format is specified in the
+ * FileFilter::setPattern(const std::string&) method.
+ */
+class FileFilter {
+public:
+    /*
+     * Patterns syntax:
+     * - Delimiter is :
+     * - Entry can start with the flag ! to avoid printing a warning
+     *   about the file being ignored.
+     * - Entry can have the flag "<dir>" to match only directories
+     *   or <file> to match only files. Default is to match both.
+     * - Entry can be a simplified glob "<prefix>*" or "*<suffix>"
+     *   where prefix/suffix must have at least 1 character (so that
+     *   we don't match a '*' catch-all pattern.)
+     * - The special filenames "." and ".." are always ignored.
+     * - Otherwise the full string is matched.
+     * - match is not case-sensitive.
+     */
+    bool setPattern(const StringPiece& pattern);
+
+    /**
+     * Applies the filter, returning true for pass, false for fail.
+     */
+    bool operator()(const std::string& filename, FileType type) const;
+
+private:
+    std::vector<std::string> mPatternTokens;
+};
+
+inline void appendPath(std::string* base, const StringPiece& part) {
+    assert(base);
+    *base += sDirSep;
+    base->append(part.data(), part.size());
+}
+
+template <typename... Ts >
+void appendPath(std::string* base, const StringPiece& part, const Ts&... parts) {
+    assert(base);
+    *base += sDirSep;
+    base->append(part.data(), part.size());
+    appendPath(base, parts...);
+}
+
+} // namespace aapt
+
+#endif // AAPT_FILES_H
diff --git a/tools/aapt2/JavaClassGenerator.cpp b/tools/aapt2/JavaClassGenerator.cpp
new file mode 100644
index 0000000..779a346
--- /dev/null
+++ b/tools/aapt2/JavaClassGenerator.cpp
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+#include "JavaClassGenerator.h"
+#include "Resource.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "StringPiece.h"
+
+#include <algorithm>
+#include <ostream>
+#include <set>
+#include <sstream>
+#include <tuple>
+
+namespace aapt {
+
+// The number of attributes to emit per line in a Styleable array.
+constexpr size_t kAttribsPerLine = 4;
+
+JavaClassGenerator::JavaClassGenerator(std::shared_ptr<const ResourceTable> table,
+                                       Options options) :
+        mTable(table), mOptions(options) {
+}
+
+static void generateHeader(std::ostream& out, const StringPiece16& package) {
+    out << "/* AUTO-GENERATED FILE. DO NOT MODIFY.\n"
+           " *\n"
+           " * This class was automatically generated by the\n"
+           " * aapt tool from the resource data it found. It\n"
+           " * should not be modified by hand.\n"
+           " */\n\n";
+    out << "package " << package << ";"
+        << std::endl
+        << std::endl;
+}
+
+static const std::set<StringPiece16> sJavaIdentifiers = {
+    u"abstract", u"assert", u"boolean", u"break", u"byte",
+    u"case", u"catch", u"char", u"class", u"const", u"continue",
+    u"default", u"do", u"double", u"else", u"enum", u"extends",
+    u"final", u"finally", u"float", u"for", u"goto", u"if",
+    u"implements", u"import", u"instanceof", u"int", u"interface",
+    u"long", u"native", u"new", u"package", u"private", u"protected",
+    u"public", u"return", u"short", u"static", u"strictfp", u"super",
+    u"switch", u"synchronized", u"this", u"throw", u"throws",
+    u"transient", u"try", u"void", u"volatile", u"while", u"true",
+    u"false", u"null"
+};
+
+static bool isValidSymbol(const StringPiece16& symbol) {
+    return sJavaIdentifiers.find(symbol) == sJavaIdentifiers.end();
+}
+
+/*
+ * Java symbols can not contain . or -, but those are valid in a resource name.
+ * Replace those with '_'.
+ */
+static std::u16string transform(const StringPiece16& symbol) {
+    std::u16string output = symbol.toString();
+    for (char16_t& c : output) {
+        if (c == u'.' || c == u'-') {
+            c = u'_';
+        }
+    }
+    return output;
+}
+
+bool JavaClassGenerator::generateType(std::ostream& out, const ResourceTableType& type,
+                                      size_t packageId) {
+    const StringPiece finalModifier = mOptions.useFinal ? " final" : "";
+
+    for (const auto& entry : type.entries) {
+        ResourceId id = { packageId, type.typeId, entry->entryId };
+        assert(id.isValid());
+
+        if (!isValidSymbol(entry->name)) {
+            std::stringstream err;
+            err << "invalid symbol name '"
+                << StringPiece16(entry->name)
+                << "'";
+            mError = err.str();
+            return false;
+        }
+
+        out << "        "
+            << "public static" << finalModifier
+            << " int " << transform(entry->name) << " = " << id << ";" << std::endl;
+    }
+    return true;
+}
+
+struct GenArgs : ValueVisitorArgs {
+    GenArgs(std::ostream& o, const ResourceEntry& e) : out(o), entry(e) {
+    }
+
+    std::ostream& out;
+    const ResourceEntry& entry;
+};
+
+void JavaClassGenerator::visit(const Styleable& styleable, ValueVisitorArgs& a) {
+    const StringPiece finalModifier = mOptions.useFinal ? " final" : "";
+    std::ostream& out = static_cast<GenArgs&>(a).out;
+    const ResourceEntry& entry = static_cast<GenArgs&>(a).entry;
+
+    // This must be sorted by resource ID.
+    std::vector<std::pair<ResourceId, StringPiece16>> sortedAttributes;
+    sortedAttributes.reserve(styleable.entries.size());
+    for (const auto& attr : styleable.entries) {
+        assert(attr.id.isValid() && "no ID set for Styleable entry");
+        assert(attr.name.isValid() && "no name set for Styleable entry");
+        sortedAttributes.emplace_back(attr.id, attr.name.entry);
+    }
+    std::sort(sortedAttributes.begin(), sortedAttributes.end());
+
+    // First we emit the array containing the IDs of each attribute.
+    out << "        "
+        << "public static final int[] " << transform(entry.name) << " = {";
+
+    const size_t attrCount = sortedAttributes.size();
+    for (size_t i = 0; i < attrCount; i++) {
+        if (i % kAttribsPerLine == 0) {
+            out << std::endl << "            ";
+        }
+
+        out << sortedAttributes[i].first;
+        if (i != attrCount - 1) {
+            out << ", ";
+        }
+    }
+    out << std::endl << "        };" << std::endl;
+
+    // Now we emit the indices into the array.
+    for (size_t i = 0; i < attrCount; i++) {
+        out << "        "
+            << "public static" << finalModifier
+            << " int " << transform(entry.name) << "_" << transform(sortedAttributes[i].second)
+            << " = " << i << ";" << std::endl;
+    }
+}
+
+bool JavaClassGenerator::generate(std::ostream& out) {
+    const size_t packageId = mTable->getPackageId();
+
+    generateHeader(out, mTable->getPackage());
+
+    out << "public final class R {" << std::endl;
+
+    for (const auto& type : *mTable) {
+        out << "    public static final class " << type->type << " {" << std::endl;
+        bool result;
+        if (type->type == ResourceType::kStyleable) {
+            for (const auto& entry : type->entries) {
+                assert(!entry->values.empty());
+                if (!isValidSymbol(entry->name)) {
+                    std::stringstream err;
+                    err << "invalid symbol name '"
+                        << StringPiece16(entry->name)
+                        << "'";
+                    mError = err.str();
+                    return false;
+                }
+                entry->values.front().value->accept(*this, GenArgs{ out, *entry });
+            }
+        } else {
+            result = generateType(out, *type, packageId);
+        }
+
+        if (!result) {
+            return false;
+        }
+        out << "    }" << std::endl;
+    }
+
+    out << "}" << std::endl;
+    return true;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/JavaClassGenerator.h b/tools/aapt2/JavaClassGenerator.h
new file mode 100644
index 0000000..5b8e500
--- /dev/null
+++ b/tools/aapt2/JavaClassGenerator.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_JAVA_CLASS_GENERATOR_H
+#define AAPT_JAVA_CLASS_GENERATOR_H
+
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+
+#include <ostream>
+#include <string>
+
+namespace aapt {
+
+/*
+ * Generates the R.java file for a resource table.
+ */
+class JavaClassGenerator : ConstValueVisitor {
+public:
+    /*
+     * A set of options for this JavaClassGenerator.
+     */
+    struct Options {
+        /*
+         * Specifies whether to use the 'final' modifier
+         * on resource entries. Default is true.
+         */
+        bool useFinal = true;
+    };
+
+    JavaClassGenerator(std::shared_ptr<const ResourceTable> table, Options options);
+
+    /*
+     * Writes the R.java file to `out`. Returns true on success.
+     */
+    bool generate(std::ostream& out);
+
+    /*
+     * ConstValueVisitor implementation.
+     */
+    void visit(const Styleable& styleable, ValueVisitorArgs& args);
+
+    const std::string& getError() const;
+
+private:
+    bool generateType(std::ostream& out, const ResourceTableType& type, size_t packageId);
+
+    std::shared_ptr<const ResourceTable> mTable;
+    Options mOptions;
+    std::string mError;
+};
+
+inline const std::string& JavaClassGenerator::getError() const {
+    return mError;
+}
+
+} // namespace aapt
+
+#endif // AAPT_JAVA_CLASS_GENERATOR_H
diff --git a/tools/aapt2/JavaClassGenerator_test.cpp b/tools/aapt2/JavaClassGenerator_test.cpp
new file mode 100644
index 0000000..32050e3
--- /dev/null
+++ b/tools/aapt2/JavaClassGenerator_test.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#include "JavaClassGenerator.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "Util.h"
+
+#include <gtest/gtest.h>
+#include <sstream>
+#include <string>
+
+namespace aapt {
+
+struct JavaClassGeneratorTest : public ::testing::Test {
+    virtual void SetUp() override {
+        mTable = std::make_shared<ResourceTable>();
+        mTable->setPackage(u"android");
+        mTable->setPackageId(0x01);
+    }
+
+    bool addResource(const ResourceNameRef& name, ResourceId id) {
+        return mTable->addResource(name, id, {}, SourceLine{ "test.xml", 21 },
+                                   util::make_unique<Id>());
+    }
+
+    std::shared_ptr<ResourceTable> mTable;
+};
+
+TEST_F(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
+    ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"class" },
+                            ResourceId{ 0x01, 0x02, 0x0000 }));
+
+    JavaClassGenerator generator(mTable, {});
+
+    std::stringstream out;
+    EXPECT_FALSE(generator.generate(out));
+}
+
+TEST_F(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
+    ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kId, u"hey-man" },
+                            ResourceId{ 0x01, 0x02, 0x0000 }));
+
+    ASSERT_TRUE(addResource(ResourceName{ {}, ResourceType::kAttr, u"cool.attr" },
+                            ResourceId{ 0x01, 0x01, 0x0000 }));
+
+    std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
+    Reference ref(ResourceName{ u"android", ResourceType::kAttr, u"cool.attr"});
+    ref.id = ResourceId{ 0x01, 0x01, 0x0000 };
+    styleable->entries.emplace_back(ref);
+
+    ASSERT_TRUE(mTable->addResource(ResourceName{ {}, ResourceType::kStyleable, u"hey.dude" },
+                                    ResourceId{ 0x01, 0x03, 0x0000 }, {},
+                                    SourceLine{ "test.xml", 21 }, std::move(styleable)));
+
+    JavaClassGenerator generator(mTable, {});
+
+    std::stringstream out;
+    EXPECT_TRUE(generator.generate(out));
+    std::string output = out.str();
+
+    EXPECT_NE(std::string::npos,
+              output.find("public static final int hey_man = 0x01020000;"));
+
+    EXPECT_NE(std::string::npos,
+              output.find("public static final int[] hey_dude = {"));
+
+    EXPECT_NE(std::string::npos,
+              output.find("public static final int hey_dude_cool_attr = 0;"));
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/Linker.cpp b/tools/aapt2/Linker.cpp
new file mode 100644
index 0000000..1cfb297
--- /dev/null
+++ b/tools/aapt2/Linker.cpp
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ */
+
+#include "Linker.h"
+#include "Logger.h"
+#include "ResourceParser.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "StringPiece.h"
+#include "Util.h"
+
+#include <androidfw/AssetManager.h>
+#include <array>
+#include <bitset>
+#include <iostream>
+#include <map>
+#include <ostream>
+#include <set>
+#include <sstream>
+#include <tuple>
+#include <vector>
+
+namespace aapt {
+
+Linker::Args::Args(const ResourceNameRef& r, const SourceLine& s) : referrer(r), source(s) {
+}
+
+Linker::Linker(std::shared_ptr<ResourceTable> table, std::shared_ptr<Resolver> resolver) :
+        mTable(table), mResolver(resolver), mError(false) {
+}
+
+bool Linker::linkAndValidate() {
+    std::bitset<256> usedTypeIds;
+    std::array<std::set<uint16_t>, 256> usedIds;
+    usedTypeIds.set(0);
+
+    // First build the graph of references.
+    for (auto& type : *mTable) {
+        if (type->typeId != ResourceTableType::kUnsetTypeId) {
+            // The ID for this type has already been set. We
+            // mark this ID as taken so we don't re-assign it
+            // later.
+            usedTypeIds.set(type->typeId);
+        }
+
+        for (auto& entry : type->entries) {
+            if (type->typeId != ResourceTableType::kUnsetTypeId &&
+                    entry->entryId != ResourceEntry::kUnsetEntryId) {
+                // The ID for this entry has already been set. We
+                // mark this ID as taken so we don't re-assign it
+                // later.
+                usedIds[type->typeId].insert(entry->entryId);
+            }
+
+            for (auto& valueConfig : entry->values) {
+                // Dispatch to the right method of this linker
+                // based on the value's type.
+                valueConfig.value->accept(*this, Args{
+                        ResourceNameRef{ mTable->getPackage(), type->type, entry->name },
+                        valueConfig.source
+                });
+            }
+        }
+    }
+
+    /*
+     * Assign resource IDs that are available.
+     */
+    size_t nextTypeIndex = 0;
+    for (auto& type : *mTable) {
+        if (type->typeId == ResourceTableType::kUnsetTypeId) {
+            while (nextTypeIndex < usedTypeIds.size() && usedTypeIds[nextTypeIndex]) {
+                nextTypeIndex++;
+            }
+            type->typeId = nextTypeIndex++;
+        }
+
+        const auto endEntryIter = std::end(usedIds[type->typeId]);
+        auto nextEntryIter = std::begin(usedIds[type->typeId]);
+        size_t nextIndex = 0;
+        for (auto& entry : type->entries) {
+            if (entry->entryId == ResourceTableType::kUnsetTypeId) {
+                while (nextEntryIter != endEntryIter &&
+                        nextIndex == *nextEntryIter) {
+                    nextIndex++;
+                    ++nextEntryIter;
+                }
+                entry->entryId = nextIndex++;
+
+                // Update callers of this resource with the right ID.
+                auto callersIter = mGraph.find(ResourceNameRef{
+                        mTable->getPackage(),
+                        type->type,
+                        entry->name
+                });
+
+                if (callersIter != std::end(mGraph)) {
+                    for (Node& caller : callersIter->second) {
+                        caller.reference->id = ResourceId(mTable->getPackageId(),
+                                                          type->typeId,
+                                                          entry->entryId);
+                    }
+                }
+            }
+        }
+    }
+
+    return !mError;
+}
+
+const Linker::ResourceNameToSourceMap& Linker::getUnresolvedReferences() const {
+    return mUnresolvedSymbols;
+}
+
+void Linker::visit(Reference& reference, ValueVisitorArgs& a) {
+    Args& args = static_cast<Args&>(a);
+
+    Maybe<ResourceId> result = mResolver->findId(reference.name);
+    if (!result) {
+        addUnresolvedSymbol(reference.name, args.source);
+        return;
+    }
+
+    const ResourceId& id = result.value();
+    if (id.isValid()) {
+        reference.id = id;
+    } else {
+        // We need to update the ID when it is set, so add it
+        // to the graph.
+        mGraph[reference.name].push_back(Node{
+                args.referrer,
+                args.source.path,
+                args.source.line,
+                &reference
+        });
+    }
+
+    // TODO(adamlesinski): Verify the referencedType is another reference
+    // or a compatible primitive.
+}
+
+void Linker::processAttributeValue(const ResourceNameRef& name, const SourceLine& source,
+        const Attribute& attr, std::unique_ptr<Item>& value) {
+    std::unique_ptr<Item> convertedValue;
+    visitFunc<RawString>(*value, [&](RawString& str) {
+        // This is a raw string, so check if it can be converted to anything.
+        // We can NOT swap value with the converted value in here, since
+        // we called through the original value.
+
+        auto onCreateReference = [&](const ResourceName& name) {
+            mTable->addResource(name, ConfigDescription{},
+                    source, util::make_unique<Id>());
+        };
+
+        convertedValue = ResourceParser::parseItemForAttribute(
+                *str.value, attr, mResolver->getDefaultPackage(),
+                onCreateReference);
+        if (!convertedValue && attr.typeMask & android::ResTable_map::TYPE_STRING) {
+            // Last effort is to parse as a string.
+            util::StringBuilder builder;
+            builder.append(*str.value);
+            if (builder) {
+                convertedValue = util::make_unique<String>(
+                        mTable->getValueStringPool().makeRef(builder.str()));
+            }
+        }
+    });
+
+    if (convertedValue) {
+        value = std::move(convertedValue);
+    }
+
+    // Process this new or old value (it can be a reference!).
+    value->accept(*this, Args{ name, source });
+
+    // Flatten the value to see what resource type it is.
+    android::Res_value resValue;
+    value->flatten(resValue);
+
+    // Always allow references.
+    const uint32_t typeMask = attr.typeMask | android::ResTable_map::TYPE_REFERENCE;
+    if (!(typeMask & ResourceParser::androidTypeToAttributeTypeMask(resValue.dataType))) {
+        Logger::error(source)
+                << *value
+                << " is not compatible with attribute "
+                << attr
+                << "."
+                << std::endl;
+        mError = true;
+    }
+}
+
+void Linker::visit(Style& style, ValueVisitorArgs& a) {
+    Args& args = static_cast<Args&>(a);
+
+    if (style.parent.name.isValid()) {
+        visit(style.parent, a);
+    }
+
+    for (Style::Entry& styleEntry : style.entries) {
+        Maybe<Resolver::Entry> result = mResolver->findAttribute(styleEntry.key.name);
+        if (!result || !result.value().attr) {
+            addUnresolvedSymbol(styleEntry.key.name, args.source);
+            continue;
+        }
+
+        const Resolver::Entry& entry = result.value();
+        if (entry.id.isValid()) {
+            styleEntry.key.id = entry.id;
+        } else {
+            // Create a dependency for the style on this attribute.
+            mGraph[styleEntry.key.name].push_back(Node{
+                    args.referrer,
+                    args.source.path,
+                    args.source.line,
+                    &styleEntry.key
+            });
+        }
+        processAttributeValue(args.referrer, args.source, *entry.attr, styleEntry.value);
+    }
+}
+
+void Linker::visit(Attribute& attr, ValueVisitorArgs& a) {
+    static constexpr uint32_t kMask = android::ResTable_map::TYPE_ENUM |
+            android::ResTable_map::TYPE_FLAGS;
+    if (attr.typeMask & kMask) {
+        for (auto& symbol : attr.symbols) {
+            visit(symbol.symbol, a);
+        }
+    }
+}
+
+void Linker::visit(Styleable& styleable, ValueVisitorArgs& a) {
+    for (auto& attrRef : styleable.entries) {
+        visit(attrRef, a);
+    }
+}
+
+void Linker::visit(Sentinel& sentinel, ValueVisitorArgs& a) {
+    Args& args = static_cast<Args&>(a);
+    addUnresolvedSymbol(args.referrer, args.source);
+}
+
+void Linker::visit(Array& array, ValueVisitorArgs& a) {
+    Args& args = static_cast<Args&>(a);
+
+    for (auto& item : array.items) {
+        item->accept(*this, Args{ args.referrer, args.source });
+    }
+}
+
+void Linker::visit(Plural& plural, ValueVisitorArgs& a) {
+    Args& args = static_cast<Args&>(a);
+
+    for (auto& item : plural.values) {
+        if (item) {
+            item->accept(*this, Args{ args.referrer, args.source });
+        }
+    }
+}
+
+void Linker::addUnresolvedSymbol(const ResourceNameRef& name, const SourceLine& source) {
+    mUnresolvedSymbols[name.toResourceName()].push_back(source);
+}
+
+::std::ostream& operator<<(::std::ostream& out, const Linker::Node& node) {
+    return out << node.name << "(" << node.source << ":" << node.line << ")";
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/Linker.h b/tools/aapt2/Linker.h
new file mode 100644
index 0000000..9b911b7
--- /dev/null
+++ b/tools/aapt2/Linker.h
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_LINKER_H
+#define AAPT_LINKER_H
+
+#include "Resolver.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "Source.h"
+#include "StringPiece.h"
+
+#include <androidfw/AssetManager.h>
+#include <map>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <vector>
+
+namespace aapt {
+
+/**
+ * The Linker has two jobs. It follows resource references
+ * and verifies that their targert exists and that their
+ * types are compatible. The Linker will also assign resource
+ * IDs and fill in all the dependent references with the newly
+ * assigned resource IDs.
+ *
+ * To do this, the Linker builds a graph of references. This
+ * can be useful to do other analysis, like building a
+ * dependency graph of source files. The hope is to be able to
+ * add functionality that operates on the graph without
+ * overcomplicating the Linker.
+ *
+ * TODO(adamlesinski): Build the graph first then run the separate
+ * steps over the graph.
+ */
+class Linker : ValueVisitor {
+public:
+    /**
+     * Create a Linker for the given resource table with the sources available in
+     * Resolver. Resolver should contain the ResourceTable as a source too.
+     */
+    Linker(std::shared_ptr<ResourceTable> table, std::shared_ptr<Resolver> resolver);
+
+    Linker(const Linker&) = delete;
+
+    /**
+     * Entry point to the linker. Assigns resource IDs, follows references,
+     * and validates types. Returns true if all references to defined values
+     * are type-compatible. Missing resource references are recorded but do
+     * not cause this method to fail.
+     */
+    bool linkAndValidate();
+
+    /**
+     * Returns any references to resources that were not defined in any of the
+     * sources.
+     */
+    using ResourceNameToSourceMap = std::map<ResourceName, std::vector<SourceLine>>;
+    const ResourceNameToSourceMap& getUnresolvedReferences() const;
+
+private:
+    struct Args : public ValueVisitorArgs {
+        Args(const ResourceNameRef& r, const SourceLine& s);
+
+        const ResourceNameRef& referrer;
+        const SourceLine& source;
+    };
+
+    //
+    // Overrides of ValueVisitor
+    //
+    void visit(Reference& reference, ValueVisitorArgs& args) override;
+    void visit(Attribute& attribute, ValueVisitorArgs& args) override;
+    void visit(Styleable& styleable, ValueVisitorArgs& args) override;
+    void visit(Style& style, ValueVisitorArgs& args) override;
+    void visit(Sentinel& sentinel, ValueVisitorArgs& args) override;
+    void visit(Array& array, ValueVisitorArgs& args) override;
+    void visit(Plural& plural, ValueVisitorArgs& args) override;
+
+    void processAttributeValue(const ResourceNameRef& name, const SourceLine& source,
+            const Attribute& attr, std::unique_ptr<Item>& value);
+
+    void addUnresolvedSymbol(const ResourceNameRef& name, const SourceLine& source);
+
+    /**
+     * Node of the resource table graph.
+     */
+    struct Node {
+        // We use ResourceNameRef and StringPiece, which are safe so long as the ResourceTable
+        // that defines the data isn't modified.
+        ResourceNameRef name;
+        StringPiece source;
+        size_t line;
+
+        // The reference object that points to name.
+        Reference* reference;
+
+        bool operator<(const Node& rhs) const;
+        bool operator==(const Node& rhs) const;
+        bool operator!=(const Node& rhs) const;
+    };
+    friend ::std::ostream& operator<<(::std::ostream&, const Node&);
+
+    std::shared_ptr<ResourceTable> mTable;
+    std::shared_ptr<Resolver> mResolver;
+    std::map<ResourceNameRef, std::vector<Node>> mGraph;
+    std::map<ResourceName, std::vector<SourceLine>> mUnresolvedSymbols;
+    bool mError;
+};
+
+} // namespace aapt
+
+#endif // AAPT_LINKER_H
diff --git a/tools/aapt2/Linker_test.cpp b/tools/aapt2/Linker_test.cpp
new file mode 100644
index 0000000..b1e201b
--- /dev/null
+++ b/tools/aapt2/Linker_test.cpp
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+#include "Linker.h"
+#include "Resolver.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "Util.h"
+
+#include <androidfw/AssetManager.h>
+#include <gtest/gtest.h>
+#include <string>
+
+namespace aapt {
+
+struct LinkerTest : public ::testing::Test {
+    virtual void SetUp() override {
+        mTable = std::make_shared<ResourceTable>();
+        mTable->setPackage(u"android");
+        mLinker = std::make_shared<Linker>(mTable, std::make_shared<Resolver>(
+                mTable, std::make_shared<android::AssetManager>()));
+
+        // Create a few attributes for use in the tests.
+
+        addResource(ResourceName{ {}, ResourceType::kAttr, u"integer" },
+                    util::make_unique<Attribute>(false, android::ResTable_map::TYPE_INTEGER));
+
+        addResource(ResourceName{ {}, ResourceType::kAttr, u"string" },
+                    util::make_unique<Attribute>(false, android::ResTable_map::TYPE_STRING));
+
+        addResource(ResourceName{ {}, ResourceType::kId, u"apple" }, util::make_unique<Id>());
+
+        addResource(ResourceName{ {}, ResourceType::kId, u"banana" }, util::make_unique<Id>());
+
+        std::unique_ptr<Attribute> flagAttr = util::make_unique<Attribute>(
+                false, android::ResTable_map::TYPE_FLAGS);
+        flagAttr->symbols.push_back(Attribute::Symbol{
+                ResourceNameRef{ u"android", ResourceType::kId, u"apple" }, 1 });
+        flagAttr->symbols.push_back(Attribute::Symbol{
+                ResourceNameRef{ u"android", ResourceType::kId, u"banana" }, 2 });
+        addResource(ResourceName{ {}, ResourceType::kAttr, u"flags" }, std::move(flagAttr));
+    }
+
+    /*
+     * Convenience method for adding resources with the default configuration and some
+     * bogus source line.
+     */
+    bool addResource(const ResourceNameRef& name, std::unique_ptr<Value> value) {
+        return mTable->addResource(name, {}, SourceLine{ "test.xml", 21 }, std::move(value));
+    }
+
+    std::shared_ptr<ResourceTable> mTable;
+    std::shared_ptr<Linker> mLinker;
+};
+
+TEST_F(LinkerTest, DoNotInterpretEscapedStringAsReference) {
+    ASSERT_TRUE(addResource(ResourceName{ u"android", ResourceType::kString, u"foo" },
+                util::make_unique<String>(mTable->getValueStringPool().makeRef(u"?123"))));
+
+    ASSERT_TRUE(mLinker->linkAndValidate());
+    EXPECT_TRUE(mLinker->getUnresolvedReferences().empty());
+}
+
+TEST_F(LinkerTest, EscapeAndConvertRawString) {
+    std::unique_ptr<Style> style = util::make_unique<Style>();
+    style->entries.push_back(Style::Entry{
+            ResourceNameRef{ u"android", ResourceType::kAttr, u"integer" },
+            util::make_unique<RawString>(mTable->getValueStringPool().makeRef(u"  123"))
+    });
+    const Style* result = style.get();
+    ASSERT_TRUE(addResource(ResourceName{ u"android", ResourceType::kStyle, u"foo" },
+                std::move(style)));
+
+    ASSERT_TRUE(mLinker->linkAndValidate());
+    EXPECT_TRUE(mLinker->getUnresolvedReferences().empty());
+
+    EXPECT_NE(nullptr, dynamic_cast<BinaryPrimitive*>(result->entries.front().value.get()));
+}
+
+TEST_F(LinkerTest, FailToConvertRawString) {
+    std::unique_ptr<Style> style = util::make_unique<Style>();
+    style->entries.push_back(Style::Entry{
+            ResourceNameRef{ u"android", ResourceType::kAttr, u"integer" },
+            util::make_unique<RawString>(mTable->getValueStringPool().makeRef(u"yo what is up?"))
+    });
+    ASSERT_TRUE(addResource(ResourceName{ u"android", ResourceType::kStyle, u"foo" },
+                std::move(style)));
+
+    ASSERT_FALSE(mLinker->linkAndValidate());
+}
+
+TEST_F(LinkerTest, ConvertRawStringToString) {
+    std::unique_ptr<Style> style = util::make_unique<Style>();
+    style->entries.push_back(Style::Entry{
+            ResourceNameRef{ u"android", ResourceType::kAttr, u"string" },
+            util::make_unique<RawString>(
+                    mTable->getValueStringPool().makeRef(u"  \"this  is  \\u00fa\"."))
+    });
+    const Style* result = style.get();
+    ASSERT_TRUE(addResource(ResourceName{ u"android", ResourceType::kStyle, u"foo" },
+                std::move(style)));
+
+    ASSERT_TRUE(mLinker->linkAndValidate());
+    EXPECT_TRUE(mLinker->getUnresolvedReferences().empty());
+
+    const String* str = dynamic_cast<const String*>(result->entries.front().value.get());
+    ASSERT_NE(nullptr, str);
+    EXPECT_EQ(*str->value, u"this  is  \u00fa.");
+}
+
+TEST_F(LinkerTest, ConvertRawStringToFlags) {
+    std::unique_ptr<Style> style = util::make_unique<Style>();
+    style->entries.push_back(Style::Entry{
+            ResourceNameRef{ u"android", ResourceType::kAttr, u"flags" },
+            util::make_unique<RawString>(mTable->getValueStringPool().makeRef(u"banana | apple"))
+    });
+    const Style* result = style.get();
+    ASSERT_TRUE(addResource(ResourceName{ u"android", ResourceType::kStyle, u"foo" },
+                std::move(style)));
+
+    ASSERT_TRUE(mLinker->linkAndValidate());
+    EXPECT_TRUE(mLinker->getUnresolvedReferences().empty());
+
+    const BinaryPrimitive* bin = dynamic_cast<const BinaryPrimitive*>(
+            result->entries.front().value.get());
+    ASSERT_NE(nullptr, bin);
+    EXPECT_EQ(bin->value.data, 1u | 2u);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/Locale.cpp b/tools/aapt2/Locale.cpp
new file mode 100644
index 0000000..eed0ea7
--- /dev/null
+++ b/tools/aapt2/Locale.cpp
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+
+#include "Locale.h"
+#include "Util.h"
+
+#include <algorithm>
+#include <ctype.h>
+#include <string>
+#include <vector>
+
+namespace aapt {
+
+using android::ResTable_config;
+
+void LocaleValue::setLanguage(const char* languageChars) {
+     size_t i = 0;
+     while ((*languageChars) != '\0') {
+          language[i++] = ::tolower(*languageChars);
+          languageChars++;
+     }
+}
+
+void LocaleValue::setRegion(const char* regionChars) {
+    size_t i = 0;
+    while ((*regionChars) != '\0') {
+         region[i++] = ::toupper(*regionChars);
+         regionChars++;
+    }
+}
+
+void LocaleValue::setScript(const char* scriptChars) {
+    size_t i = 0;
+    while ((*scriptChars) != '\0') {
+         if (i == 0) {
+             script[i++] = ::toupper(*scriptChars);
+         } else {
+             script[i++] = ::tolower(*scriptChars);
+         }
+         scriptChars++;
+    }
+}
+
+void LocaleValue::setVariant(const char* variantChars) {
+     size_t i = 0;
+     while ((*variantChars) != '\0') {
+          variant[i++] = *variantChars;
+          variantChars++;
+     }
+}
+
+static inline bool isAlpha(const std::string& str) {
+    return std::all_of(std::begin(str), std::end(str), ::isalpha);
+}
+
+static inline bool isNumber(const std::string& str) {
+    return std::all_of(std::begin(str), std::end(str), ::isdigit);
+}
+
+bool LocaleValue::initFromFilterString(const std::string& str) {
+     // A locale (as specified in the filter) is an underscore separated name such
+     // as "en_US", "en_Latn_US", or "en_US_POSIX".
+     std::vector<std::string> parts = util::splitAndLowercase(str, '_');
+
+     const int numTags = parts.size();
+     bool valid = false;
+     if (numTags >= 1) {
+         const std::string& lang = parts[0];
+         if (isAlpha(lang) && (lang.length() == 2 || lang.length() == 3)) {
+             setLanguage(lang.c_str());
+             valid = true;
+         }
+     }
+
+     if (!valid || numTags == 1) {
+         return valid;
+     }
+
+     // At this point, valid == true && numTags > 1.
+     const std::string& part2 = parts[1];
+     if ((part2.length() == 2 && isAlpha(part2)) ||
+         (part2.length() == 3 && isNumber(part2))) {
+         setRegion(part2.c_str());
+     } else if (part2.length() == 4 && isAlpha(part2)) {
+         setScript(part2.c_str());
+     } else if (part2.length() >= 5 && part2.length() <= 8) {
+         setVariant(part2.c_str());
+     } else {
+         valid = false;
+     }
+
+     if (!valid || numTags == 2) {
+         return valid;
+     }
+
+     // At this point, valid == true && numTags > 1.
+     const std::string& part3 = parts[2];
+     if (((part3.length() == 2 && isAlpha(part3)) ||
+         (part3.length() == 3 && isNumber(part3))) && script[0]) {
+         setRegion(part3.c_str());
+     } else if (part3.length() >= 5 && part3.length() <= 8) {
+         setVariant(part3.c_str());
+     } else {
+         valid = false;
+     }
+
+     if (!valid || numTags == 3) {
+         return valid;
+     }
+
+     const std::string& part4 = parts[3];
+     if (part4.length() >= 5 && part4.length() <= 8) {
+         setVariant(part4.c_str());
+     } else {
+         valid = false;
+     }
+
+     if (!valid || numTags > 4) {
+         return false;
+     }
+
+     return true;
+}
+
+ssize_t LocaleValue::initFromParts(std::vector<std::string>::iterator iter,
+        std::vector<std::string>::iterator end) {
+    const std::vector<std::string>::iterator startIter = iter;
+
+    std::string& part = *iter;
+    if (part[0] == 'b' && part[1] == '+') {
+        // This is a "modified" BCP-47 language tag. Same semantics as BCP-47 tags,
+        // except that the separator is "+" and not "-".
+        std::vector<std::string> subtags = util::splitAndLowercase(part, '+');
+        subtags.erase(subtags.begin());
+        if (subtags.size() == 1) {
+            setLanguage(subtags[0].c_str());
+        } else if (subtags.size() == 2) {
+            setLanguage(subtags[0].c_str());
+
+            // The second tag can either be a region, a variant or a script.
+            switch (subtags[1].size()) {
+                case 2:
+                case 3:
+                    setRegion(subtags[1].c_str());
+                    break;
+                case 4:
+                    setScript(subtags[1].c_str());
+                    break;
+                case 5:
+                case 6:
+                case 7:
+                case 8:
+                    setVariant(subtags[1].c_str());
+                    break;
+                default:
+                    return -1;
+            }
+        } else if (subtags.size() == 3) {
+            // The language is always the first subtag.
+            setLanguage(subtags[0].c_str());
+
+            // The second subtag can either be a script or a region code.
+            // If its size is 4, it's a script code, else it's a region code.
+            if (subtags[1].size() == 4) {
+                setScript(subtags[1].c_str());
+            } else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
+                setRegion(subtags[1].c_str());
+            } else {
+                return -1;
+            }
+
+            // The third tag can either be a region code (if the second tag was
+            // a script), else a variant code.
+            if (subtags[2].size() > 4) {
+                setVariant(subtags[2].c_str());
+            } else {
+                setRegion(subtags[2].c_str());
+            }
+        } else if (subtags.size() == 4) {
+            setLanguage(subtags[0].c_str());
+            setScript(subtags[1].c_str());
+            setRegion(subtags[2].c_str());
+            setVariant(subtags[3].c_str());
+        } else {
+            return -1;
+        }
+
+        ++iter;
+
+    } else {
+        if ((part.length() == 2 || part.length() == 3)
+                && isAlpha(part) && part != "car") {
+            setLanguage(part.c_str());
+            ++iter;
+
+            if (iter != end) {
+                const std::string& regionPart = *iter;
+                if (regionPart.c_str()[0] == 'r' && regionPart.length() == 3) {
+                    setRegion(regionPart.c_str() + 1);
+                    ++iter;
+                }
+            }
+        }
+    }
+
+    return static_cast<ssize_t>(iter - startIter);
+}
+
+
+std::string LocaleValue::toDirName() const {
+    std::string dirName;
+    if (language[0]) {
+        dirName += language;
+    } else {
+        return dirName;
+    }
+
+    if (script[0]) {
+        dirName += "-s";
+        dirName += script;
+    }
+
+    if (region[0]) {
+        dirName += "-r";
+        dirName += region;
+    }
+
+    if (variant[0]) {
+        dirName += "-v";
+        dirName += variant;
+    }
+
+    return dirName;
+}
+
+void LocaleValue::initFromResTable(const ResTable_config& config) {
+    config.unpackLanguage(language);
+    config.unpackRegion(region);
+    if (config.localeScript[0]) {
+        memcpy(script, config.localeScript, sizeof(config.localeScript));
+    }
+
+    if (config.localeVariant[0]) {
+        memcpy(variant, config.localeVariant, sizeof(config.localeVariant));
+    }
+}
+
+void LocaleValue::writeTo(ResTable_config* out) const {
+    out->packLanguage(language);
+    out->packRegion(region);
+
+    if (script[0]) {
+        memcpy(out->localeScript, script, sizeof(out->localeScript));
+    }
+
+    if (variant[0]) {
+        memcpy(out->localeVariant, variant, sizeof(out->localeVariant));
+    }
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/Locale.h b/tools/aapt2/Locale.h
new file mode 100644
index 0000000..ceec764
--- /dev/null
+++ b/tools/aapt2/Locale.h
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_LOCALE_VALUE_H
+#define AAPT_LOCALE_VALUE_H
+
+#include <androidfw/ResourceTypes.h>
+#include <string>
+#include <vector>
+
+namespace aapt {
+
+/**
+ * A convenience class to build and parse locales.
+ */
+struct LocaleValue {
+    char language[4];
+    char region[4];
+    char script[4];
+    char variant[8];
+
+    inline LocaleValue();
+
+    /**
+     * Initialize this LocaleValue from a config string.
+     */
+    bool initFromFilterString(const std::string& config);
+
+    /**
+     * Initialize this LocaleValue from parts of a vector.
+     */
+    ssize_t initFromParts(std::vector<std::string>::iterator iter,
+            std::vector<std::string>::iterator end);
+
+    /**
+     * Initialize this LocaleValue from a ResTable_config.
+     */
+    void initFromResTable(const android::ResTable_config& config);
+
+    /**
+     * Set the locale in a ResTable_config from this LocaleValue.
+     */
+    void writeTo(android::ResTable_config* out) const;
+
+    std::string toDirName() const;
+
+    inline int compare(const LocaleValue& other) const;
+
+    inline bool operator<(const LocaleValue& o) const;
+    inline bool operator<=(const LocaleValue& o) const;
+    inline bool operator==(const LocaleValue& o) const;
+    inline bool operator!=(const LocaleValue& o) const;
+    inline bool operator>=(const LocaleValue& o) const;
+    inline bool operator>(const LocaleValue& o) const;
+
+private:
+     void setLanguage(const char* language);
+     void setRegion(const char* language);
+     void setScript(const char* script);
+     void setVariant(const char* variant);
+};
+
+//
+// Implementation
+//
+
+LocaleValue::LocaleValue() {
+    memset(this, 0, sizeof(LocaleValue));
+}
+
+int LocaleValue::compare(const LocaleValue& other) const {
+    return memcmp(this, &other, sizeof(LocaleValue));
+}
+
+bool LocaleValue::operator<(const LocaleValue& o) const {
+    return compare(o) < 0;
+}
+
+bool LocaleValue::operator<=(const LocaleValue& o) const {
+    return compare(o) <= 0;
+}
+
+bool LocaleValue::operator==(const LocaleValue& o) const {
+    return compare(o) == 0;
+}
+
+bool LocaleValue::operator!=(const LocaleValue& o) const {
+    return compare(o) != 0;
+}
+
+bool LocaleValue::operator>=(const LocaleValue& o) const {
+    return compare(o) >= 0;
+}
+
+bool LocaleValue::operator>(const LocaleValue& o) const {
+    return compare(o) > 0;
+}
+
+} // namespace aapt
+
+#endif // AAPT_LOCALE_VALUE_H
diff --git a/tools/aapt2/Locale_test.cpp b/tools/aapt2/Locale_test.cpp
new file mode 100644
index 0000000..4e154d6
--- /dev/null
+++ b/tools/aapt2/Locale_test.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#include "Locale.h"
+#include "Util.h"
+
+#include <gtest/gtest.h>
+#include <string>
+
+namespace aapt {
+
+static ::testing::AssertionResult TestLanguage(const char* input, const char* lang) {
+    std::vector<std::string> parts = util::splitAndLowercase(std::string(input), '-');
+    LocaleValue lv;
+    ssize_t count = lv.initFromParts(std::begin(parts), std::end(parts));
+    if (count < 0) {
+        return ::testing::AssertionFailure() << " failed to parse '" << input << "'.";
+    }
+
+    if (count != 1) {
+        return ::testing::AssertionFailure() << count
+            << " parts were consumed parsing '" << input << "' but expected 1.";
+    }
+
+    if (memcmp(lv.language, lang, std::min(strlen(lang), sizeof(lv.language))) != 0) {
+        return ::testing::AssertionFailure() << "expected " << lang << " but got "
+            << std::string(lv.language, sizeof(lv.language)) << ".";
+    }
+
+    return ::testing::AssertionSuccess();
+}
+
+static ::testing::AssertionResult TestLanguageRegion(const char* input, const char* lang,
+                                                     const char* region) {
+    std::vector<std::string> parts = util::splitAndLowercase(std::string(input), '-');
+    LocaleValue lv;
+    ssize_t count = lv.initFromParts(std::begin(parts), std::end(parts));
+    if (count < 0) {
+        return ::testing::AssertionFailure() << " failed to parse '" << input << "'.";
+    }
+
+    if (count != 2) {
+        return ::testing::AssertionFailure() << count
+            << " parts were consumed parsing '" << input << "' but expected 2.";
+    }
+
+    if (memcmp(lv.language, lang, std::min(strlen(lang), sizeof(lv.language))) != 0) {
+        return ::testing::AssertionFailure() << "expected " << input << " but got "
+            << std::string(lv.language, sizeof(lv.language)) << ".";
+    }
+
+    if (memcmp(lv.region, region, std::min(strlen(region), sizeof(lv.region))) != 0) {
+        return ::testing::AssertionFailure() << "expected " << region << " but got "
+            << std::string(lv.region, sizeof(lv.region)) << ".";
+    }
+
+    return ::testing::AssertionSuccess();
+}
+
+TEST(ConfigDescriptionTest, ParseLanguage) {
+    EXPECT_TRUE(TestLanguage("en", "en"));
+    EXPECT_TRUE(TestLanguage("fr", "fr"));
+    EXPECT_FALSE(TestLanguage("land", ""));
+    EXPECT_TRUE(TestLanguage("fr-land", "fr"));
+
+    EXPECT_TRUE(TestLanguageRegion("fr-rCA", "fr", "CA"));
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/Logger.cpp b/tools/aapt2/Logger.cpp
new file mode 100644
index 0000000..3847185
--- /dev/null
+++ b/tools/aapt2/Logger.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+#include "Logger.h"
+#include "Source.h"
+
+#include <memory>
+#include <iostream>
+
+namespace aapt {
+
+Log::Log(std::ostream& _out, std::ostream& _err) : out(_out), err(_err) {
+}
+
+std::shared_ptr<Log> Logger::sLog(std::make_shared<Log>(std::cerr, std::cerr));
+
+void Logger::setLog(const std::shared_ptr<Log>& log) {
+    sLog = log;
+}
+
+std::ostream& Logger::error() {
+    return sLog->err << "error: ";
+}
+
+std::ostream& Logger::error(const Source& source) {
+    return sLog->err << source << ": error: ";
+}
+
+std::ostream& Logger::error(const SourceLine& source) {
+    return sLog->err << source << ": error: ";
+}
+
+std::ostream& Logger::warn() {
+    return sLog->err << "warning: ";
+}
+
+std::ostream& Logger::warn(const Source& source) {
+    return sLog->err << source << ": warning: ";
+}
+
+std::ostream& Logger::warn(const SourceLine& source) {
+    return sLog->err << source << ": warning: ";
+}
+
+std::ostream& Logger::note() {
+    return sLog->out << "note: ";
+}
+
+std::ostream& Logger::note(const Source& source) {
+    return sLog->err << source << ": note: ";
+}
+
+std::ostream& Logger::note(const SourceLine& source) {
+    return sLog->err << source << ": note: ";
+}
+
+SourceLogger::SourceLogger(const Source& source)
+: mSource(source) {
+}
+
+std::ostream& SourceLogger::error() {
+    return Logger::error(mSource);
+}
+
+std::ostream& SourceLogger::error(size_t line) {
+    return Logger::error(SourceLine{ mSource.path, line });
+}
+
+std::ostream& SourceLogger::warn() {
+    return Logger::warn(mSource);
+}
+
+std::ostream& SourceLogger::warn(size_t line) {
+    return Logger::warn(SourceLine{ mSource.path, line });
+}
+
+std::ostream& SourceLogger::note() {
+    return Logger::note(mSource);
+}
+
+std::ostream& SourceLogger::note(size_t line) {
+    return Logger::note(SourceLine{ mSource.path, line });
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/Logger.h b/tools/aapt2/Logger.h
new file mode 100644
index 0000000..1d437eb
--- /dev/null
+++ b/tools/aapt2/Logger.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_LOGGER_H
+#define AAPT_LOGGER_H
+
+#include "Source.h"
+
+#include <memory>
+#include <ostream>
+#include <string>
+#include <utils/String8.h>
+
+namespace aapt {
+
+struct Log {
+    Log(std::ostream& out, std::ostream& err);
+    Log(const Log& rhs) = delete;
+
+    std::ostream& out;
+    std::ostream& err;
+};
+
+class Logger {
+public:
+    static void setLog(const std::shared_ptr<Log>& log);
+
+    static std::ostream& error();
+    static std::ostream& error(const Source& source);
+    static std::ostream& error(const SourceLine& sourceLine);
+
+    static std::ostream& warn();
+    static std::ostream& warn(const Source& source);
+    static std::ostream& warn(const SourceLine& sourceLine);
+
+    static std::ostream& note();
+    static std::ostream& note(const Source& source);
+    static std::ostream& note(const SourceLine& sourceLine);
+
+private:
+    static std::shared_ptr<Log> sLog;
+};
+
+class SourceLogger {
+public:
+    SourceLogger(const Source& source);
+
+    std::ostream& error();
+    std::ostream& error(size_t line);
+
+    std::ostream& warn();
+    std::ostream& warn(size_t line);
+
+    std::ostream& note();
+    std::ostream& note(size_t line);
+
+private:
+    Source mSource;
+};
+
+inline ::std::ostream& operator<<(::std::ostream& out, const std::u16string& str) {
+    android::String8 utf8(str.data(), str.size());
+    return out.write(utf8.string(), utf8.size());
+}
+
+} // namespace aapt
+
+#endif // AAPT_LOGGER_H
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
new file mode 100644
index 0000000..cfc5874
--- /dev/null
+++ b/tools/aapt2/Main.cpp
@@ -0,0 +1,1426 @@
+/*
+ * 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.
+ */
+
+#include "AppInfo.h"
+#include "BigBuffer.h"
+#include "BinaryResourceParser.h"
+#include "Files.h"
+#include "JavaClassGenerator.h"
+#include "Linker.h"
+#include "ManifestParser.h"
+#include "ManifestValidator.h"
+#include "ResourceParser.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "SdkConstants.h"
+#include "SourceXmlPullParser.h"
+#include "StringPiece.h"
+#include "TableFlattener.h"
+#include "Util.h"
+#include "XmlFlattener.h"
+
+#include <algorithm>
+#include <androidfw/AssetManager.h>
+#include <cstdlib>
+#include <dirent.h>
+#include <errno.h>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <sys/stat.h>
+
+using namespace aapt;
+
+void printTable(const ResourceTable& table) {
+    std::cout << "ResourceTable package=" << table.getPackage();
+    if (table.getPackageId() != ResourceTable::kUnsetPackageId) {
+        std::cout << " id=" << std::hex << table.getPackageId() << std::dec;
+    }
+    std::cout << std::endl
+         << "---------------------------------------------------------" << std::endl;
+
+    for (const auto& type : table) {
+        std::cout << "Type " << type->type;
+        if (type->typeId != ResourceTableType::kUnsetTypeId) {
+            std::cout << " [" << type->typeId << "]";
+        }
+        std::cout << " (" << type->entries.size() << " entries)" << std::endl;
+        for (const auto& entry : type->entries) {
+            std::cout << "  " << entry->name;
+            if (entry->entryId != ResourceEntry::kUnsetEntryId) {
+                std::cout << " [" << entry->entryId << "]";
+            }
+            std::cout << " (" << entry->values.size() << " configurations)";
+            if (entry->publicStatus.isPublic) {
+                std::cout << " PUBLIC";
+            }
+            std::cout << std::endl;
+            for (const auto& value : entry->values) {
+                std::cout << "    " << value.config << " (" << value.source << ") : ";
+                value.value->print(std::cout);
+                std::cout << std::endl;
+            }
+        }
+    }
+}
+
+void printStringPool(const StringPool& pool) {
+    std::cout << "String pool of length " << pool.size() << std::endl
+         << "---------------------------------------------------------" << std::endl;
+
+    size_t i = 0;
+    for (const auto& entry : pool) {
+        std::cout << "[" << i << "]: "
+             << entry->value
+             << " (Priority " << entry->context.priority
+             << ", Config '" << entry->context.config << "')"
+             << std::endl;
+        i++;
+    }
+}
+
+std::unique_ptr<FileReference> makeFileReference(StringPool& pool, const StringPiece& filename,
+        ResourceType type, const ConfigDescription& config) {
+    std::stringstream path;
+    path << "res/" << type;
+    if (config != ConfigDescription{}) {
+        path << "-" << config;
+    }
+    path << "/" << filename;
+    return util::make_unique<FileReference>(pool.makeRef(util::utf8ToUtf16(path.str())));
+}
+
+/**
+ * Collect files from 'root', filtering out any files that do not
+ * match the FileFilter 'filter'.
+ */
+bool walkTree(const StringPiece& root, const FileFilter& filter,
+        std::vector<Source>& outEntries) {
+    bool error = false;
+
+    for (const std::string& dirName : listFiles(root)) {
+        std::string dir(root.toString());
+        appendPath(&dir, dirName);
+
+        FileType ft = getFileType(dir);
+        if (!filter(dirName, ft)) {
+            continue;
+        }
+
+        if (ft != FileType::kDirectory) {
+            continue;
+        }
+
+        for (const std::string& fileName : listFiles(dir)) {
+            std::string file(dir);
+            appendPath(&file, fileName);
+
+            FileType ft = getFileType(file);
+            if (!filter(fileName, ft)) {
+                continue;
+            }
+
+            if (ft != FileType::kRegular) {
+                Logger::error(Source{ file })
+                    << "not a regular file."
+                    << std::endl;
+                error = true;
+                continue;
+            }
+            outEntries.emplace_back(Source{ file });
+        }
+    }
+    return !error;
+}
+
+bool loadBinaryResourceTable(std::shared_ptr<ResourceTable> table, const Source& source) {
+    std::ifstream ifs(source.path, std::ifstream::in | std::ifstream::binary);
+    if (!ifs) {
+        Logger::error(source) << strerror(errno) << std::endl;
+        return false;
+    }
+
+    std::streampos fsize = ifs.tellg();
+    ifs.seekg(0, std::ios::end);
+    fsize = ifs.tellg() - fsize;
+    ifs.seekg(0, std::ios::beg);
+
+    assert(fsize >= 0);
+    size_t dataSize = static_cast<size_t>(fsize);
+    char* buf = new char[dataSize];
+    ifs.read(buf, dataSize);
+
+    BinaryResourceParser parser(table, source, buf, dataSize);
+    bool result = parser.parse();
+
+    delete [] buf;
+    return result;
+}
+
+bool loadResTable(android::ResTable* table, const Source& source) {
+    // For NO_ERROR (which on Windows is a MACRO).
+    using namespace android;
+
+    std::ifstream ifs(source.path, std::ifstream::in | std::ifstream::binary);
+    if (!ifs) {
+        Logger::error(source) << strerror(errno) << std::endl;
+        return false;
+    }
+
+    std::streampos fsize = ifs.tellg();
+    ifs.seekg(0, std::ios::end);
+    fsize = ifs.tellg() - fsize;
+    ifs.seekg(0, std::ios::beg);
+
+    assert(fsize >= 0);
+    size_t dataSize = static_cast<size_t>(fsize);
+    char* buf = new char[dataSize];
+    ifs.read(buf, dataSize);
+
+    bool result = table->add(buf, dataSize, -1, true) == NO_ERROR;
+
+    delete [] buf;
+    return result;
+}
+
+void versionStylesForCompat(std::shared_ptr<ResourceTable> table) {
+    for (auto& type : *table) {
+        if (type->type != ResourceType::kStyle) {
+            continue;
+        }
+
+        for (auto& entry : type->entries) {
+            // Add the versioned styles we want to create
+            // here. They are added to the table after
+            // iterating over the original set of styles.
+            //
+            // A stack is used since auto-generated styles
+            // from later versions should override
+            // auto-generated styles from earlier versions.
+            // Iterating over the styles is done in order,
+            // so we will always visit sdkVersions from smallest
+            // to largest.
+            std::stack<ResourceConfigValue> addStack;
+
+            for (ResourceConfigValue& configValue : entry->values) {
+                visitFunc<Style>(*configValue.value, [&](Style& style) {
+                    // Collect which entries we've stripped and the smallest
+                    // SDK level which was stripped.
+                    size_t minSdkStripped = std::numeric_limits<size_t>::max();
+                    std::vector<Style::Entry> stripped;
+
+                    // Iterate over the style's entries and erase/record the
+                    // attributes whose SDK level exceeds the config's sdkVersion.
+                    auto iter = style.entries.begin();
+                    while (iter != style.entries.end()) {
+                        if (iter->key.name.package == u"android") {
+                            size_t sdkLevel = findAttributeSdkLevel(iter->key.name.entry);
+                            if (sdkLevel > 1 && sdkLevel > configValue.config.sdkVersion) {
+                                // Record that we are about to strip this.
+                                stripped.emplace_back(std::move(*iter));
+                                minSdkStripped = std::min(minSdkStripped, sdkLevel);
+
+                                // Erase this from this style.
+                                iter = style.entries.erase(iter);
+                                continue;
+                            }
+                        }
+                        ++iter;
+                    }
+
+                    if (!stripped.empty()) {
+                        // We have stripped attributes, so let's create a new style to hold them.
+                        ConfigDescription versionConfig(configValue.config);
+                        versionConfig.sdkVersion = minSdkStripped;
+
+                        ResourceConfigValue value = {
+                                versionConfig,
+                                configValue.source,
+                                {},
+
+                                // Create a copy of the original style.
+                                std::unique_ptr<Value>(configValue.value->clone())
+                        };
+
+                        Style& newStyle = static_cast<Style&>(*value.value);
+
+                        // Move the recorded stripped attributes into this new style.
+                        std::move(stripped.begin(), stripped.end(),
+                                  std::back_inserter(newStyle.entries));
+
+                        // We will add this style to the table later. If we do it now, we will
+                        // mess up iteration.
+                        addStack.push(std::move(value));
+                    }
+                });
+            }
+
+            auto comparator =
+                    [](const ResourceConfigValue& lhs, const ConfigDescription& rhs) -> bool {
+                        return lhs.config < rhs;
+                    };
+
+            while (!addStack.empty()) {
+                ResourceConfigValue& value = addStack.top();
+                auto iter = std::lower_bound(entry->values.begin(), entry->values.end(),
+                                             value.config, comparator);
+                if (iter == entry->values.end() || iter->config != value.config) {
+                    entry->values.insert(iter, std::move(value));
+                }
+                addStack.pop();
+            }
+        }
+    }
+}
+
+bool collectXml(std::shared_ptr<ResourceTable> table, const Source& source,
+                const ResourceName& name,
+                const ConfigDescription& config) {
+    std::ifstream in(source.path, std::ifstream::binary);
+    if (!in) {
+        Logger::error(source) << strerror(errno) << std::endl;
+        return false;
+    }
+
+    std::set<size_t> sdkLevels;
+
+    SourceXmlPullParser pullParser(in);
+    while (XmlPullParser::isGoodEvent(pullParser.next())) {
+        if (pullParser.getEvent() != XmlPullParser::Event::kStartElement) {
+            continue;
+        }
+
+        const auto endIter = pullParser.endAttributes();
+        for (auto iter = pullParser.beginAttributes(); iter != endIter; ++iter) {
+            if (iter->namespaceUri == u"http://schemas.android.com/apk/res/android") {
+                size_t sdkLevel = findAttributeSdkLevel(iter->name);
+                if (sdkLevel > 1) {
+                    sdkLevels.insert(sdkLevel);
+                }
+            }
+
+            ResourceNameRef refName;
+            bool create = false;
+            bool privateRef = false;
+            if (ResourceParser::tryParseReference(iter->value, &refName, &create, &privateRef) &&
+                    create) {
+                table->addResource(refName, {}, source.line(pullParser.getLineNumber()),
+                                   util::make_unique<Id>());
+            }
+        }
+    }
+
+    std::unique_ptr<FileReference> fileResource = makeFileReference(
+            table->getValueStringPool(),
+            util::utf16ToUtf8(name.entry) + ".xml",
+            name.type,
+            config);
+    table->addResource(name, config, source.line(0), std::move(fileResource));
+
+    for (size_t level : sdkLevels) {
+        Logger::note(source)
+                << "creating v" << level << " versioned file."
+                << std::endl;
+        ConfigDescription newConfig = config;
+        newConfig.sdkVersion = level;
+
+        std::unique_ptr<FileReference> fileResource = makeFileReference(
+                table->getValueStringPool(),
+                util::utf16ToUtf8(name.entry) + ".xml",
+                name.type,
+                newConfig);
+        table->addResource(name, newConfig, source.line(0), std::move(fileResource));
+    }
+    return true;
+}
+
+struct CompileXml {
+    Source source;
+    ResourceName name;
+    ConfigDescription config;
+};
+
+bool compileXml(std::shared_ptr<Resolver> resolver, const CompileXml& item,
+                const Source& outputSource, std::queue<CompileXml>* queue) {
+    std::ifstream in(item.source.path, std::ifstream::binary);
+    if (!in) {
+        Logger::error(item.source) << strerror(errno) << std::endl;
+        return false;
+    }
+
+    BigBuffer outBuffer(1024);
+    std::shared_ptr<XmlPullParser> xmlParser = std::make_shared<SourceXmlPullParser>(in);
+    XmlFlattener flattener(resolver);
+
+    // We strip attributes that do not belong in this version of the resource.
+    // Non-version qualified resources have an implicit version 1 requirement.
+    XmlFlattener::Options options = { item.config.sdkVersion ? item.config.sdkVersion : 1 };
+    Maybe<size_t> minStrippedSdk = flattener.flatten(item.source, xmlParser, &outBuffer, options);
+    if (!minStrippedSdk) {
+        return false;
+    }
+
+    if (minStrippedSdk.value() > 0) {
+        // Something was stripped, so let's generate a new file
+        // with the version of the smallest SDK version stripped.
+        CompileXml newWork = item;
+        newWork.config.sdkVersion = minStrippedSdk.value();
+        queue->push(newWork);
+    }
+
+    std::ofstream out(outputSource.path, std::ofstream::binary);
+    if (!out) {
+        Logger::error(outputSource) << strerror(errno) << std::endl;
+        return false;
+    }
+
+    if (!util::writeAll(out, outBuffer)) {
+        Logger::error(outputSource) << strerror(errno) << std::endl;
+        return false;
+    }
+    return true;
+}
+
+struct AaptOptions {
+    enum class Phase {
+        LegacyFull,
+        Collect,
+        Link,
+        Compile,
+    };
+
+    // The phase to process.
+    Phase phase;
+
+    // Details about the app.
+    AppInfo appInfo;
+
+    // The location of the manifest file.
+    Source manifest;
+
+    // The files to process.
+    std::vector<Source> sources;
+
+    // The libraries these files may reference.
+    std::vector<Source> libraries;
+
+    // Output directory.
+    Source output;
+
+    // Whether to generate a Java Class.
+    Maybe<Source> generateJavaClass;
+
+    // Whether to output verbose details about
+    // compilation.
+    bool verbose = false;
+};
+
+bool compileAndroidManifest(std::shared_ptr<Resolver> resolver, const AaptOptions& options) {
+    using namespace android;
+
+    Source outSource = options.output;
+    appendPath(&outSource.path, "AndroidManifest.xml");
+
+    if (options.verbose) {
+        Logger::note(outSource) << "compiling AndroidManifest.xml." << std::endl;
+    }
+
+    std::ifstream in(options.manifest.path, std::ifstream::binary);
+    if (!in) {
+        Logger::error(options.manifest) << strerror(errno) << std::endl;
+        return false;
+    }
+
+    BigBuffer outBuffer(1024);
+    std::shared_ptr<XmlPullParser> xmlParser = std::make_shared<SourceXmlPullParser>(in);
+    XmlFlattener flattener(resolver);
+
+    Maybe<size_t> result = flattener.flatten(options.manifest, xmlParser, &outBuffer,
+                                             XmlFlattener::Options{});
+    if (!result) {
+        return false;
+    }
+
+    std::unique_ptr<uint8_t[]> data = std::unique_ptr<uint8_t[]>(new uint8_t[outBuffer.size()]);
+    uint8_t* p = data.get();
+    for (const auto& b : outBuffer) {
+        memcpy(p, b.buffer.get(), b.size);
+        p += b.size;
+    }
+
+    ResXMLTree tree;
+    if (tree.setTo(data.get(), outBuffer.size()) != NO_ERROR) {
+        return false;
+    }
+
+    ManifestValidator validator(resolver->getResTable());
+    if (!validator.validate(options.manifest, &tree)) {
+        return false;
+    }
+
+    std::ofstream out(outSource.path, std::ofstream::binary);
+    if (!out) {
+        Logger::error(outSource) << strerror(errno) << std::endl;
+        return false;
+    }
+
+    if (!util::writeAll(out, outBuffer)) {
+        Logger::error(outSource) << strerror(errno) << std::endl;
+        return false;
+    }
+    return true;
+}
+
+bool loadAppInfo(const Source& source, AppInfo* outInfo) {
+    std::ifstream ifs(source.path, std::ifstream::in | std::ifstream::binary);
+    if (!ifs) {
+        Logger::error(source) << strerror(errno) << std::endl;
+        return false;
+    }
+
+    ManifestParser parser;
+    std::shared_ptr<XmlPullParser> pullParser = std::make_shared<SourceXmlPullParser>(ifs);
+    return parser.parse(source, pullParser, outInfo);
+}
+
+/**
+ * Parses legacy options and walks the source directories collecting
+ * files to process.
+ */
+bool prepareLegacy(std::vector<StringPiece>::const_iterator argsIter,
+        const std::vector<StringPiece>::const_iterator argsEndIter,
+        AaptOptions &options) {
+    options.phase = AaptOptions::Phase::LegacyFull;
+
+    std::vector<StringPiece> sourceDirs;
+    while (argsIter != argsEndIter) {
+        if (*argsIter == "-S") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "-S missing argument." << std::endl;
+                return false;
+            }
+            sourceDirs.push_back(*argsIter);
+        } else if (*argsIter == "-I") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "-I missing argument." << std::endl;
+                return false;
+            }
+            options.libraries.push_back(Source{ argsIter->toString() });
+        } else if (*argsIter == "-M") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "-M missing argument." << std::endl;
+                return false;
+            }
+
+            if (!options.manifest.path.empty()) {
+                Logger::error() << "multiple -M flags are not allowed." << std::endl;
+                return false;
+            }
+            options.manifest.path = argsIter->toString();
+        } else if (*argsIter == "-o") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "-o missing argument." << std::endl;
+                return false;
+            }
+            options.output = Source{ argsIter->toString() };
+        } else if (*argsIter == "-J") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "-J missing argument." << std::endl;
+                return false;
+            }
+            options.generateJavaClass = make_value<Source>(Source{ argsIter->toString() });
+        } else if (*argsIter == "-v") {
+            options.verbose = true;
+        } else {
+            Logger::error() << "unrecognized option '" << *argsIter << "'." << std::endl;
+            return false;
+        }
+
+        ++argsIter;
+    }
+
+    if (options.manifest.path.empty()) {
+        Logger::error() << "must specify manifest file with -M." << std::endl;
+        return false;
+    }
+
+    // Load the App's package name, etc.
+    if (!loadAppInfo(options.manifest, &options.appInfo)) {
+        return false;
+    }
+
+    /**
+     * Set up the file filter to ignore certain files.
+     */
+    const char* customIgnore = getenv("ANDROID_AAPT_IGNORE");
+    FileFilter fileFilter;
+    if (customIgnore && customIgnore[0]) {
+        fileFilter.setPattern(customIgnore);
+    } else {
+        fileFilter.setPattern(
+                "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~");
+    }
+
+    /*
+     * Enumerate the files in each source directory.
+     */
+    for (const StringPiece& source : sourceDirs) {
+        if (!walkTree(source, fileFilter, options.sources)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool prepareCollect(std::vector<StringPiece>::const_iterator argsIter,
+        const std::vector<StringPiece>::const_iterator argsEndIter,
+        AaptOptions& options) {
+    options.phase = AaptOptions::Phase::Collect;
+
+    while (argsIter != argsEndIter) {
+        if (*argsIter == "--package") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "--package missing argument." << std::endl;
+                return false;
+            }
+            options.appInfo.package = util::utf8ToUtf16(*argsIter);
+        } else if (*argsIter == "-o") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "-o missing argument." << std::endl;
+                return false;
+            }
+            options.output = Source{ argsIter->toString() };
+        } else if (*argsIter == "-v") {
+            options.verbose = true;
+        } else if (argsIter->data()[0] != '-') {
+            options.sources.push_back(Source{ argsIter->toString() });
+        } else {
+            Logger::error()
+                    << "unknown option '"
+                    << *argsIter
+                    << "'."
+                    << std::endl;
+            return false;
+        }
+        ++argsIter;
+    }
+    return true;
+}
+
+bool prepareLink(std::vector<StringPiece>::const_iterator argsIter,
+        const std::vector<StringPiece>::const_iterator argsEndIter,
+        AaptOptions& options) {
+    options.phase = AaptOptions::Phase::Link;
+
+    while (argsIter != argsEndIter) {
+        if (*argsIter == "--package") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "--package missing argument." << std::endl;
+                return false;
+            }
+            options.appInfo.package = util::utf8ToUtf16(*argsIter);
+        } else if (*argsIter == "-o") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "-o missing argument." << std::endl;
+                return false;
+            }
+            options.output = Source{ argsIter->toString() };
+        } else if (*argsIter == "-I") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "-I missing argument." << std::endl;
+                return false;
+            }
+            options.libraries.push_back(Source{ argsIter->toString() });
+        } else if (*argsIter == "--java") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "--java missing argument." << std::endl;
+                return false;
+            }
+            options.generateJavaClass = make_value<Source>(Source{ argsIter->toString() });
+        } else if (*argsIter == "-v") {
+            options.verbose = true;
+        } else if (argsIter->data()[0] != '-') {
+            options.sources.push_back(Source{ argsIter->toString() });
+        } else {
+            Logger::error()
+                    << "unknown option '"
+                    << *argsIter
+                    << "'."
+                    << std::endl;
+            return false;
+        }
+        ++argsIter;
+    }
+    return true;
+}
+
+bool prepareCompile(std::vector<StringPiece>::const_iterator argsIter,
+        const std::vector<StringPiece>::const_iterator argsEndIter,
+        AaptOptions& options) {
+    options.phase = AaptOptions::Phase::Compile;
+
+    while (argsIter != argsEndIter) {
+        if (*argsIter == "--package") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "--package missing argument." << std::endl;
+                return false;
+            }
+            options.appInfo.package = util::utf8ToUtf16(*argsIter);
+        } else if (*argsIter == "-o") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "-o missing argument." << std::endl;
+                return false;
+            }
+            options.output = Source{ argsIter->toString() };
+        } else if (*argsIter == "-I") {
+            ++argsIter;
+            if (argsIter == argsEndIter) {
+                Logger::error() << "-I missing argument." << std::endl;
+                return false;
+            }
+            options.libraries.push_back(Source{ argsIter->toString() });
+        } else if (*argsIter == "-v") {
+            options.verbose = true;
+        } else if (argsIter->data()[0] != '-') {
+            options.sources.push_back(Source{ argsIter->toString() });
+        } else {
+            Logger::error()
+                    << "unknown option '"
+                    << *argsIter
+                    << "'."
+                    << std::endl;
+            return false;
+        }
+        ++argsIter;
+    }
+    return true;
+}
+
+struct CollectValuesItem {
+    Source source;
+    ConfigDescription config;
+};
+
+bool collectValues(std::shared_ptr<ResourceTable> table, const CollectValuesItem& item) {
+    std::ifstream in(item.source.path, std::ifstream::binary);
+    if (!in) {
+        Logger::error(item.source) << strerror(errno) << std::endl;
+        return false;
+    }
+
+    std::shared_ptr<XmlPullParser> xmlParser = std::make_shared<SourceXmlPullParser>(in);
+    ResourceParser parser(table, item.source, item.config, xmlParser);
+    return parser.parse();
+}
+
+struct ResourcePathData {
+    std::u16string resourceDir;
+    std::u16string name;
+    std::string extension;
+    ConfigDescription config;
+};
+
+/**
+ * Resource file paths are expected to look like:
+ * [--/res/]type[-config]/name
+ */
+Maybe<ResourcePathData> extractResourcePathData(const Source& source) {
+    std::vector<std::string> parts = util::splitAndLowercase(source.path, '/');
+    if (parts.size() < 2) {
+        Logger::error(source) << "bad resource path." << std::endl;
+        return {};
+    }
+
+    std::string& dir = parts[parts.size() - 2];
+    StringPiece dirStr = dir;
+
+    ConfigDescription config;
+    size_t dashPos = dir.find('-');
+    if (dashPos != std::string::npos) {
+        StringPiece configStr = dirStr.substr(dashPos + 1, dir.size() - (dashPos + 1));
+        if (!ConfigDescription::parse(configStr, &config)) {
+            Logger::error(source)
+                    << "invalid configuration '"
+                    << configStr
+                    << "'."
+                    << std::endl;
+            return {};
+        }
+        dirStr = dirStr.substr(0, dashPos);
+    }
+
+    std::string& filename = parts[parts.size() - 1];
+    StringPiece name = filename;
+    StringPiece extension;
+    size_t dotPos = filename.find('.');
+    if (dotPos != std::string::npos) {
+        extension = name.substr(dotPos + 1, filename.size() - (dotPos + 1));
+        name = name.substr(0, dotPos);
+    }
+
+    return ResourcePathData{
+            util::utf8ToUtf16(dirStr),
+            util::utf8ToUtf16(name),
+            extension.toString(),
+            config
+    };
+}
+
+static bool doLegacy(std::shared_ptr<ResourceTable> table, std::shared_ptr<Resolver> resolver,
+                     const AaptOptions& options) {
+    bool error = false;
+    std::queue<CompileXml> xmlCompileQueue;
+
+    //
+    // Read values XML files and XML/PNG files.
+    // Need to parse the resource type/config/filename.
+    //
+    for (const Source& source : options.sources) {
+        Maybe<ResourcePathData> maybePathData = extractResourcePathData(source);
+        if (!maybePathData) {
+            return false;
+        }
+
+        const ResourcePathData& pathData = maybePathData.value();
+        if (pathData.resourceDir == u"values") {
+            if (options.verbose) {
+                Logger::note(source) << "collecting values..." << std::endl;
+            }
+
+            error |= !collectValues(table, CollectValuesItem{ source, pathData.config });
+            continue;
+        }
+
+        const ResourceType* type = parseResourceType(pathData.resourceDir);
+        if (!type) {
+            Logger::error(source)
+                    << "invalid resource type '"
+                    << pathData.resourceDir
+                    << "'."
+                    << std::endl;
+            return false;
+        }
+
+        ResourceName resourceName = { table->getPackage(), *type, pathData.name };
+        if (pathData.extension == "xml") {
+            if (options.verbose) {
+                Logger::note(source) << "collecting XML..." << std::endl;
+            }
+
+            error |= !collectXml(table, source, resourceName, pathData.config);
+            xmlCompileQueue.push(CompileXml{
+                    source,
+                    resourceName,
+                    pathData.config
+            });
+        } else {
+            std::unique_ptr<FileReference> fileReference = makeFileReference(
+                    table->getValueStringPool(),
+                    util::utf16ToUtf8(pathData.name) + "." + pathData.extension,
+                    *type, pathData.config);
+
+            error |= !table->addResource(resourceName, pathData.config, source.line(0),
+                                         std::move(fileReference));
+        }
+    }
+
+    if (error) {
+        return false;
+    }
+
+    versionStylesForCompat(table);
+
+    //
+    // Verify all references and data types.
+    //
+    Linker linker(table, resolver);
+    if (!linker.linkAndValidate()) {
+        Logger::error()
+                << "linking failed."
+                << std::endl;
+        return false;
+    }
+
+    const auto& unresolvedRefs = linker.getUnresolvedReferences();
+    if (!unresolvedRefs.empty()) {
+        for (const auto& entry : unresolvedRefs) {
+            for (const auto& source : entry.second) {
+                Logger::error(source)
+                        << "unresolved symbol '"
+                        << entry.first
+                        << "'."
+                        << std::endl;
+            }
+        }
+        return false;
+    }
+
+    //
+    // Compile the XML files.
+    //
+    while (!xmlCompileQueue.empty()) {
+        const CompileXml& item = xmlCompileQueue.front();
+
+        // Create the output path from the resource name.
+        std::stringstream outputPath;
+        outputPath << item.name.type;
+        if (item.config != ConfigDescription{}) {
+            outputPath << "-" << item.config.toString();
+        }
+
+        Source outSource = options.output;
+        appendPath(&outSource.path, "res");
+        appendPath(&outSource.path, outputPath.str());
+
+        if (!mkdirs(outSource.path)) {
+            Logger::error(outSource) << strerror(errno) << std::endl;
+            return false;
+        }
+
+        appendPath(&outSource.path, util::utf16ToUtf8(item.name.entry) + ".xml");
+
+        if (options.verbose) {
+            Logger::note(outSource) << "compiling XML file." << std::endl;
+        }
+
+        error |= !compileXml(resolver, item, outSource, &xmlCompileQueue);
+        xmlCompileQueue.pop();
+    }
+
+    if (error) {
+        return false;
+    }
+
+    //
+    // Compile the AndroidManifest.xml file.
+    //
+    if (!compileAndroidManifest(resolver, options)) {
+        return false;
+    }
+
+    //
+    // Generate the Java R class.
+    //
+    if (options.generateJavaClass) {
+        Source outPath = options.generateJavaClass.value();
+        if (options.verbose) {
+            Logger::note()
+                    << "writing symbols to "
+                    << outPath
+                    << "."
+                    << std::endl;
+        }
+
+        for (std::string& part : util::split(util::utf16ToUtf8(table->getPackage()), '.')) {
+            appendPath(&outPath.path, part);
+        }
+
+        if (!mkdirs(outPath.path)) {
+            Logger::error(outPath) << strerror(errno) << std::endl;
+            return false;
+        }
+
+        appendPath(&outPath.path, "R.java");
+
+        std::ofstream fout(outPath.path);
+        if (!fout) {
+            Logger::error(outPath) << strerror(errno) << std::endl;
+            return false;
+        }
+
+        JavaClassGenerator generator(table, JavaClassGenerator::Options{});
+        if (!generator.generate(fout)) {
+            Logger::error(outPath)
+                    << generator.getError()
+                    << "."
+                    << std::endl;
+            return false;
+        }
+    }
+
+    //
+    // Flatten resource table.
+    //
+    if (table->begin() != table->end()) {
+        BigBuffer buffer(1024);
+        TableFlattener::Options tableOptions;
+        tableOptions.useExtendedChunks = false;
+        TableFlattener flattener(tableOptions);
+        if (!flattener.flatten(&buffer, *table)) {
+            Logger::error()
+                    << "failed to flatten resource table->"
+                    << std::endl;
+            return false;
+        }
+
+        if (options.verbose) {
+            Logger::note()
+                    << "Final resource table size="
+                    << util::formatSize(buffer.size())
+                    << std::endl;
+        }
+
+        std::string outTable(options.output.path);
+        appendPath(&outTable, "resources.arsc");
+
+        std::ofstream fout(outTable, std::ofstream::binary);
+        if (!fout) {
+            Logger::error(Source{outTable})
+                    << strerror(errno)
+                    << "."
+                    << std::endl;
+            return false;
+        }
+
+        if (!util::writeAll(fout, buffer)) {
+            Logger::error(Source{outTable})
+                    << strerror(errno)
+                    << "."
+                    << std::endl;
+            return false;
+        }
+        fout.flush();
+    }
+    return true;
+}
+
+static bool doCollect(std::shared_ptr<ResourceTable> table, std::shared_ptr<Resolver> resolver,
+                      const AaptOptions& options) {
+    bool error = false;
+
+    //
+    // Read values XML files and XML/PNG files.
+    // Need to parse the resource type/config/filename.
+    //
+    for (const Source& source : options.sources) {
+        Maybe<ResourcePathData> maybePathData = extractResourcePathData(source);
+        if (!maybePathData) {
+            return false;
+        }
+
+        const ResourcePathData& pathData = maybePathData.value();
+        if (pathData.resourceDir == u"values") {
+            if (options.verbose) {
+                Logger::note(source) << "collecting values..." << std::endl;
+            }
+
+            error |= !collectValues(table, CollectValuesItem{ source, pathData.config });
+            continue;
+        }
+
+        const ResourceType* type = parseResourceType(pathData.resourceDir);
+        if (!type) {
+            Logger::error(source)
+                    << "invalid resource type '"
+                    << pathData.resourceDir
+                    << "'."
+                    << std::endl;
+            return false;
+        }
+
+        ResourceName resourceName = { table->getPackage(), *type, pathData.name };
+        if (pathData.extension == "xml") {
+            if (options.verbose) {
+                Logger::note(source) << "collecting XML..." << std::endl;
+            }
+
+            error |= !collectXml(table, source, resourceName, pathData.config);
+        } else {
+            std::unique_ptr<FileReference> fileReference = makeFileReference(
+                    table->getValueStringPool(),
+                    util::utf16ToUtf8(pathData.name) + "." + pathData.extension,
+                    *type,
+                    pathData.config);
+            error |= !table->addResource(resourceName, pathData.config, source.line(0),
+                                         std::move(fileReference));
+        }
+    }
+
+    if (error) {
+        return false;
+    }
+
+    Linker linker(table, resolver);
+    if (!linker.linkAndValidate()) {
+        return false;
+    }
+
+    //
+    // Flatten resource table->
+    //
+    if (table->begin() != table->end()) {
+        BigBuffer buffer(1024);
+        TableFlattener::Options tableOptions;
+        tableOptions.useExtendedChunks = true;
+        TableFlattener flattener(tableOptions);
+        if (!flattener.flatten(&buffer, *table)) {
+            Logger::error()
+                    << "failed to flatten resource table->"
+                    << std::endl;
+            return false;
+        }
+
+        std::ofstream fout(options.output.path, std::ofstream::binary);
+        if (!fout) {
+            Logger::error(options.output)
+                    << strerror(errno)
+                    << "."
+                    << std::endl;
+            return false;
+        }
+
+        if (!util::writeAll(fout, buffer)) {
+            Logger::error(options.output)
+                    << strerror(errno)
+                    << "."
+                    << std::endl;
+            return false;
+        }
+        fout.flush();
+    }
+    return true;
+}
+
+static bool doLink(std::shared_ptr<ResourceTable> table, std::shared_ptr<Resolver> resolver,
+                   const AaptOptions& options) {
+    bool error = false;
+
+    for (const Source& source : options.sources) {
+        error |= !loadBinaryResourceTable(table, source);
+    }
+
+    if (error) {
+        return false;
+    }
+
+    versionStylesForCompat(table);
+
+    Linker linker(table, resolver);
+    if (!linker.linkAndValidate()) {
+        return false;
+    }
+
+    const auto& unresolvedRefs = linker.getUnresolvedReferences();
+    if (!unresolvedRefs.empty()) {
+        for (const auto& entry : unresolvedRefs) {
+            for (const auto& source : entry.second) {
+                Logger::error(source)
+                        << "unresolved symbol '"
+                        << entry.first
+                        << "'."
+                        << std::endl;
+            }
+        }
+        return false;
+    }
+
+    //
+    // Generate the Java R class.
+    //
+    if (options.generateJavaClass) {
+        Source outPath = options.generateJavaClass.value();
+        if (options.verbose) {
+            Logger::note()
+                    << "writing symbols to "
+                    << outPath
+                    << "."
+                    << std::endl;
+        }
+
+        for (std::string& part : util::split(util::utf16ToUtf8(table->getPackage()), '.')) {
+            appendPath(&outPath.path, part);
+        }
+
+        if (!mkdirs(outPath.path)) {
+            Logger::error(outPath) << strerror(errno) << std::endl;
+            return false;
+        }
+
+        appendPath(&outPath.path, "R.java");
+
+        std::ofstream fout(outPath.path);
+        if (!fout) {
+            Logger::error(outPath) << strerror(errno) << std::endl;
+            return false;
+        }
+
+        JavaClassGenerator generator(table, JavaClassGenerator::Options{});
+        if (!generator.generate(fout)) {
+            Logger::error(outPath)
+                    << generator.getError()
+                    << "."
+                    << std::endl;
+            return false;
+        }
+    }
+
+    //
+    // Flatten resource table.
+    //
+    if (table->begin() != table->end()) {
+        BigBuffer buffer(1024);
+        TableFlattener::Options tableOptions;
+        tableOptions.useExtendedChunks = false;
+        TableFlattener flattener(tableOptions);
+        if (!flattener.flatten(&buffer, *table)) {
+            Logger::error()
+                    << "failed to flatten resource table->"
+                    << std::endl;
+            return false;
+        }
+
+        if (options.verbose) {
+            Logger::note()
+                    << "Final resource table size="
+                    << util::formatSize(buffer.size())
+                    << std::endl;
+        }
+
+        std::ofstream fout(options.output.path, std::ofstream::binary);
+        if (!fout) {
+            Logger::error(options.output)
+                    << strerror(errno)
+                    << "."
+                    << std::endl;
+            return false;
+        }
+
+        if (!util::writeAll(fout, buffer)) {
+            Logger::error(options.output)
+                    << strerror(errno)
+                    << "."
+                    << std::endl;
+            return false;
+        }
+        fout.flush();
+    }
+    return true;
+}
+
+static bool doCompile(std::shared_ptr<ResourceTable> table, std::shared_ptr<Resolver> resolver,
+                      const AaptOptions& options) {
+    std::queue<CompileXml> xmlCompileQueue;
+
+    for (const Source& source : options.sources) {
+        Maybe<ResourcePathData> maybePathData = extractResourcePathData(source);
+        if (!maybePathData) {
+            return false;
+        }
+
+        ResourcePathData& pathData = maybePathData.value();
+        const ResourceType* type = parseResourceType(pathData.resourceDir);
+        if (!type) {
+            Logger::error(source)
+                    << "invalid resource type '"
+                    << pathData.resourceDir
+                    << "'."
+                    << std::endl;
+            return false;
+        }
+
+        ResourceName resourceName = { table->getPackage(), *type, pathData.name };
+        if (pathData.extension == "xml") {
+            xmlCompileQueue.push(CompileXml{
+                    source,
+                    resourceName,
+                    pathData.config
+            });
+        } else {
+            // TODO(adamlesinski): Handle images here.
+        }
+    }
+
+    bool error = false;
+    while (!xmlCompileQueue.empty()) {
+        const CompileXml& item = xmlCompileQueue.front();
+
+        // Create the output path from the resource name.
+        std::stringstream outputPath;
+        outputPath << item.name.type;
+        if (item.config != ConfigDescription{}) {
+            outputPath << "-" << item.config.toString();
+        }
+
+        Source outSource = options.output;
+        appendPath(&outSource.path, "res");
+        appendPath(&outSource.path, outputPath.str());
+
+        if (!mkdirs(outSource.path)) {
+            Logger::error(outSource) << strerror(errno) << std::endl;
+            return false;
+        }
+
+        appendPath(&outSource.path, util::utf16ToUtf8(item.name.entry) + ".xml");
+
+        if (options.verbose) {
+            Logger::note(outSource) << "compiling XML file." << std::endl;
+        }
+
+        error |= !compileXml(resolver, item, outSource, &xmlCompileQueue);
+        xmlCompileQueue.pop();
+    }
+    return !error;
+}
+
+int main(int argc, char** argv) {
+    Logger::setLog(std::make_shared<Log>(std::cerr, std::cerr));
+
+    std::vector<StringPiece> args;
+    args.reserve(argc - 1);
+    for (int i = 1; i < argc; i++) {
+        args.emplace_back(argv[i], strlen(argv[i]));
+    }
+
+    if (args.empty()) {
+        Logger::error() << "no command specified." << std::endl;
+        return 1;
+    }
+
+    AaptOptions options;
+
+    // Check the command we're running.
+    const StringPiece& command = args.front();
+    if (command == "package") {
+        if (!prepareLegacy(std::begin(args) + 1, std::end(args), options)) {
+            return 1;
+        }
+    } else if (command == "collect") {
+        if (!prepareCollect(std::begin(args) + 1, std::end(args), options)) {
+            return 1;
+        }
+    } else if (command == "link") {
+        if (!prepareLink(std::begin(args) + 1, std::end(args), options)) {
+            return 1;
+        }
+    } else if (command == "compile") {
+        if (!prepareCompile(std::begin(args) + 1, std::end(args), options)) {
+            return 1;
+        }
+    } else {
+        Logger::error() << "unknown command '" << command << "'." << std::endl;
+        return 1;
+    }
+
+    //
+    // Verify we have some common options set.
+    //
+
+    if (options.sources.empty()) {
+        Logger::error() << "no sources specified." << std::endl;
+        return false;
+    }
+
+    if (options.output.path.empty()) {
+        Logger::error() << "no output directory specified." << std::endl;
+        return false;
+    }
+
+    if (options.appInfo.package.empty()) {
+        Logger::error() << "no package name specified." << std::endl;
+        return false;
+    }
+
+
+    //
+    // Every phase needs a resource table and a resolver/linker.
+    //
+
+    std::shared_ptr<ResourceTable> table = std::make_shared<ResourceTable>();
+    table->setPackage(options.appInfo.package);
+    if (options.appInfo.package == u"android") {
+        table->setPackageId(0x01);
+    } else {
+        table->setPackageId(0x7f);
+    }
+
+    //
+    // Load the included libraries.
+    //
+    std::shared_ptr<android::AssetManager> libraries = std::make_shared<android::AssetManager>();
+    for (const Source& source : options.libraries) {
+        if (util::stringEndsWith(source.path, ".arsc")) {
+            // We'll process these last so as to avoid a cookie issue.
+            continue;
+        }
+
+        int32_t cookie;
+        if (!libraries->addAssetPath(android::String8(source.path.data()), &cookie)) {
+            Logger::error(source) << "failed to load library." << std::endl;
+            return false;
+        }
+    }
+
+    for (const Source& source : options.libraries) {
+        if (!util::stringEndsWith(source.path, ".arsc")) {
+            // We've already processed this.
+            continue;
+        }
+
+        // Dirty hack but there is no other way to get a
+        // writeable ResTable.
+        if (!loadResTable(const_cast<android::ResTable*>(&libraries->getResources(false)),
+                          source)) {
+            return false;
+        }
+    }
+
+    // Make the resolver that will cache IDs for us.
+    std::shared_ptr<Resolver> resolver = std::make_shared<Resolver>(table, libraries);
+
+    //
+    // Dispatch to the real phase here.
+    //
+
+    bool result = true;
+    switch (options.phase) {
+        case AaptOptions::Phase::LegacyFull:
+            result = doLegacy(table, resolver, options);
+            break;
+
+        case AaptOptions::Phase::Collect:
+            result = doCollect(table, resolver, options);
+            break;
+
+        case AaptOptions::Phase::Link:
+            result = doLink(table, resolver, options);
+            break;
+
+        case AaptOptions::Phase::Compile:
+            result = doCompile(table, resolver, options);
+            break;
+    }
+
+    if (!result) {
+        Logger::error()
+                << "aapt exiting with failures."
+                << std::endl;
+        return 1;
+    }
+    return 0;
+}
diff --git a/tools/aapt2/ManifestParser.cpp b/tools/aapt2/ManifestParser.cpp
new file mode 100644
index 0000000..b8f0a43
--- /dev/null
+++ b/tools/aapt2/ManifestParser.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#include "AppInfo.h"
+#include "Logger.h"
+#include "ManifestParser.h"
+#include "Source.h"
+#include "XmlPullParser.h"
+
+#include <string>
+
+namespace aapt {
+
+bool ManifestParser::parse(const Source& source, std::shared_ptr<XmlPullParser> parser,
+                           AppInfo* outInfo) {
+    SourceLogger logger = { source };
+
+    int depth = 0;
+    while (XmlPullParser::isGoodEvent(parser->next())) {
+        XmlPullParser::Event event = parser->getEvent();
+        if (event == XmlPullParser::Event::kEndElement) {
+            depth--;
+            continue;
+        } else if (event != XmlPullParser::Event::kStartElement) {
+            continue;
+        }
+
+        depth++;
+
+        const std::u16string& element = parser->getElementName();
+        if (depth == 1) {
+            if (element == u"manifest") {
+                if (!parseManifest(logger, parser, outInfo)) {
+                    return false;
+                }
+            } else {
+                logger.error()
+                        << "unexpected top-level element '"
+                        << element
+                        << "'."
+                        << std::endl;
+                return false;
+            }
+        } else {
+            XmlPullParser::skipCurrentElement(parser.get());
+        }
+    }
+
+    if (parser->getEvent() == XmlPullParser::Event::kBadDocument) {
+            logger.error(parser->getLineNumber())
+                << "failed to parse manifest: "
+                << parser->getLastError()
+                << "."
+                << std::endl;
+        return false;
+    }
+    return true;
+}
+
+bool ManifestParser::parseManifest(SourceLogger& logger, std::shared_ptr<XmlPullParser> parser,
+                                   AppInfo* outInfo) {
+    auto attrIter = parser->findAttribute(u"", u"package");
+    if (attrIter == parser->endAttributes() || attrIter->value.empty()) {
+        logger.error() << "no 'package' attribute found for element <manifest>." << std::endl;
+        return false;
+    }
+    outInfo->package = attrIter->value;
+    return true;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ManifestParser.h b/tools/aapt2/ManifestParser.h
new file mode 100644
index 0000000..f2e43d4
--- /dev/null
+++ b/tools/aapt2/ManifestParser.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_MANIFEST_PARSER_H
+#define AAPT_MANIFEST_PARSER_H
+
+#include "AppInfo.h"
+#include "Logger.h"
+#include "Source.h"
+#include "XmlPullParser.h"
+
+namespace aapt {
+
+/*
+ * Parses an AndroidManifest.xml file and fills in an AppInfo structure with
+ * app data.
+ */
+class ManifestParser {
+public:
+    ManifestParser() = default;
+    ManifestParser(const ManifestParser&) = delete;
+
+    bool parse(const Source& source, std::shared_ptr<XmlPullParser> parser, AppInfo* outInfo);
+
+private:
+    bool parseManifest(SourceLogger& logger, std::shared_ptr<XmlPullParser> parser,
+                       AppInfo* outInfo);
+};
+
+} // namespace aapt
+
+#endif // AAPT_MANIFEST_PARSER_H
diff --git a/tools/aapt2/ManifestParser_test.cpp b/tools/aapt2/ManifestParser_test.cpp
new file mode 100644
index 0000000..be3a6fb
--- /dev/null
+++ b/tools/aapt2/ManifestParser_test.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#include "AppInfo.h"
+#include "ManifestParser.h"
+#include "SourceXmlPullParser.h"
+
+#include <gtest/gtest.h>
+#include <sstream>
+#include <string>
+
+namespace aapt {
+
+TEST(ManifestParserTest, FindPackage) {
+    std::stringstream input;
+    input << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+             "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
+             "package=\"android\">\n"
+             "</manifest>\n";
+
+    ManifestParser parser;
+    AppInfo info;
+    std::shared_ptr<XmlPullParser> xmlParser = std::make_shared<SourceXmlPullParser>(input);
+    ASSERT_TRUE(parser.parse(Source{ "AndroidManifest.xml" }, xmlParser, &info));
+
+    EXPECT_EQ(std::u16string(u"android"), info.package);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ManifestValidator.cpp b/tools/aapt2/ManifestValidator.cpp
new file mode 100644
index 0000000..7ec0bc7
--- /dev/null
+++ b/tools/aapt2/ManifestValidator.cpp
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ */
+
+#include "Logger.h"
+#include "ManifestValidator.h"
+#include "Maybe.h"
+#include "Source.h"
+#include "Util.h"
+
+#include <androidfw/ResourceTypes.h>
+
+namespace aapt {
+
+ManifestValidator::ManifestValidator(const android::ResTable& table)
+: mTable(table) {
+}
+
+bool ManifestValidator::validate(const Source& source, android::ResXMLParser* parser) {
+    SourceLogger logger(source);
+
+    android::ResXMLParser::event_code_t code;
+    while ((code = parser->next()) != android::ResXMLParser::END_DOCUMENT &&
+            code != android::ResXMLParser::BAD_DOCUMENT) {
+        if (code != android::ResXMLParser::START_TAG) {
+            continue;
+        }
+
+        size_t len = 0;
+        const StringPiece16 namespaceUri(parser->getElementNamespace(&len), len);
+        if (!namespaceUri.empty()) {
+            continue;
+        }
+
+        const StringPiece16 name(parser->getElementName(&len), len);
+        if (name.empty()) {
+            logger.error(parser->getLineNumber())
+                    << "failed to get the element name."
+                    << std::endl;
+            return false;
+        }
+
+        if (name == u"manifest") {
+            if (!validateManifest(source, parser)) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+Maybe<StringPiece16> ManifestValidator::getAttributeValue(android::ResXMLParser* parser,
+                                                          size_t idx) {
+    android::Res_value value;
+    if (parser->getAttributeValue(idx, &value) < 0) {
+        return StringPiece16();
+    }
+
+    const android::ResStringPool* pool = &parser->getStrings();
+    if (value.dataType == android::Res_value::TYPE_REFERENCE) {
+        ssize_t strIdx = mTable.resolveReference(&value, 0x10000000u);
+        if (strIdx < 0) {
+            return {};
+        }
+        pool = mTable.getTableStringBlock(strIdx);
+    }
+
+    if (value.dataType != android::Res_value::TYPE_STRING || !pool) {
+        return {};
+    }
+    return util::getString(*pool, value.data);
+}
+
+Maybe<StringPiece16> ManifestValidator::getAttributeInlineValue(android::ResXMLParser* parser,
+                                                                size_t idx) {
+    android::Res_value value;
+    if (parser->getAttributeValue(idx, &value) < 0) {
+        return StringPiece16();
+    }
+
+    if (value.dataType != android::Res_value::TYPE_STRING) {
+        return {};
+    }
+    return util::getString(parser->getStrings(), value.data);
+}
+
+bool ManifestValidator::validateInlineAttribute(android::ResXMLParser* parser, size_t idx,
+                                                SourceLogger& logger,
+                                                const StringPiece16& charSet) {
+    size_t len = 0;
+    StringPiece16 element(parser->getElementName(&len), len);
+    StringPiece16 attributeName(parser->getAttributeName(idx, &len), len);
+    Maybe<StringPiece16> result = getAttributeInlineValue(parser, idx);
+    if (!result) {
+        logger.error(parser->getLineNumber())
+                << "<"
+                << element
+                << "> must have a '"
+                << attributeName
+                << "' attribute with a string literal value."
+                << std::endl;
+        return false;
+    }
+    return validateAttributeImpl(element, attributeName, result.value(), charSet,
+                                 parser->getLineNumber(), logger);
+}
+
+bool ManifestValidator::validateAttribute(android::ResXMLParser* parser, size_t idx,
+                                          SourceLogger& logger, const StringPiece16& charSet) {
+    size_t len = 0;
+    StringPiece16 element(parser->getElementName(&len), len);
+    StringPiece16 attributeName(parser->getAttributeName(idx, &len), len);
+    Maybe<StringPiece16> result = getAttributeValue(parser, idx);
+    if (!result) {
+        logger.error(parser->getLineNumber())
+                << "<"
+                << element
+                << "> must have a '"
+                << attributeName
+                << "' attribute that points to a string."
+                << std::endl;
+        return false;
+    }
+    return validateAttributeImpl(element, attributeName, result.value(), charSet,
+                                 parser->getLineNumber(), logger);
+}
+
+bool ManifestValidator::validateAttributeImpl(const StringPiece16& element,
+                                              const StringPiece16& attributeName,
+                                              const StringPiece16& attributeValue,
+                                              const StringPiece16& charSet, size_t lineNumber,
+                                              SourceLogger& logger) {
+    StringPiece16::const_iterator badIter =
+            util::findNonAlphaNumericAndNotInSet(attributeValue, charSet);
+    if (badIter != attributeValue.end()) {
+        logger.error(lineNumber)
+                << "tag <"
+                << element
+                << "> attribute '"
+                << attributeName
+                << "' has invalid character '"
+                << StringPiece16(badIter, 1)
+                << "'."
+                << std::endl;
+        return false;
+    }
+
+    if (!attributeValue.empty()) {
+        StringPiece16 trimmed = util::trimWhitespace(attributeValue);
+        if (attributeValue.begin() != trimmed.begin()) {
+            logger.error(lineNumber)
+                    << "tag <"
+                    << element
+                    << "> attribute '"
+                    << attributeName
+                    << "' can not start with whitespace."
+                    << std::endl;
+            return false;
+        }
+
+        if (attributeValue.end() != trimmed.end()) {
+            logger.error(lineNumber)
+                    << "tag <"
+                    << element
+                    << "> attribute '"
+                    << attributeName
+                    << "' can not end with whitespace."
+                    << std::endl;
+            return false;
+        }
+    }
+    return true;
+}
+
+constexpr const char16_t* kPackageIdentSet = u"._";
+
+bool ManifestValidator::validateManifest(const Source& source, android::ResXMLParser* parser) {
+    bool error = false;
+    SourceLogger logger(source);
+
+    const size_t attrCount = parser->getAttributeCount();
+    for (size_t i = 0; i < attrCount; i++) {
+        size_t len = 0;
+        StringPiece16 attrNamespace(parser->getAttributeNamespace(i, &len), len);
+        StringPiece16 attrName(parser->getAttributeName(i, &len), len);
+        if (attrNamespace.empty() && attrName == u"package") {
+            error |= !validateInlineAttribute(parser, i, logger, kPackageIdentSet);
+        } else if (attrNamespace == u"android") {
+            if (attrName == u"sharedUserId") {
+                error |= !validateInlineAttribute(parser, i, logger, kPackageIdentSet);
+            }
+        }
+    }
+    return !error;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ManifestValidator.h b/tools/aapt2/ManifestValidator.h
new file mode 100644
index 0000000..3188784
--- /dev/null
+++ b/tools/aapt2/ManifestValidator.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_MANIFEST_VALIDATOR_H
+#define AAPT_MANIFEST_VALIDATOR_H
+
+#include "Logger.h"
+#include "Maybe.h"
+#include "Source.h"
+#include "StringPiece.h"
+
+#include <androidfw/ResourceTypes.h>
+
+namespace aapt {
+
+class ManifestValidator {
+public:
+    ManifestValidator(const android::ResTable& table);
+    ManifestValidator(const ManifestValidator&) = delete;
+
+    bool validate(const Source& source, android::ResXMLParser* parser);
+
+private:
+    bool validateManifest(const Source& source, android::ResXMLParser* parser);
+
+    Maybe<StringPiece16> getAttributeInlineValue(android::ResXMLParser* parser, size_t idx);
+    Maybe<StringPiece16> getAttributeValue(android::ResXMLParser* parser, size_t idx);
+
+    bool validateInlineAttribute(android::ResXMLParser* parser, size_t idx,
+                                 SourceLogger& logger, const StringPiece16& charSet);
+    bool validateAttribute(android::ResXMLParser* parser, size_t idx, SourceLogger& logger,
+                           const StringPiece16& charSet);
+    bool validateAttributeImpl(const StringPiece16& element, const StringPiece16& attributeName,
+                               const StringPiece16& attributeValue, const StringPiece16& charSet,
+                               size_t lineNumber, SourceLogger& logger);
+
+    const android::ResTable& mTable;
+};
+
+} // namespace aapt
+
+#endif // AAPT_MANIFEST_VALIDATOR_H
diff --git a/tools/aapt2/Maybe.h b/tools/aapt2/Maybe.h
new file mode 100644
index 0000000..f6a396d
--- /dev/null
+++ b/tools/aapt2/Maybe.h
@@ -0,0 +1,224 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_MAYBE_H
+#define AAPT_MAYBE_H
+
+#include <cassert>
+#include <type_traits>
+#include <utility>
+
+namespace aapt {
+
+/**
+ * Either holds a valid value of type T, or holds Nothing.
+ * The value is stored inline in this structure, so no
+ * heap memory is used when creating a Maybe<T> object.
+ */
+template <typename T>
+class Maybe {
+public:
+    /**
+     * Construct Nothing.
+     */
+    inline Maybe();
+
+    inline ~Maybe();
+
+    template <typename U>
+    inline Maybe(const Maybe<U>& rhs);
+
+    template <typename U>
+    inline Maybe(Maybe<U>&& rhs);
+
+    template <typename U>
+    inline Maybe& operator=(const Maybe<U>& rhs);
+
+    template <typename U>
+    inline Maybe& operator=(Maybe<U>&& rhs);
+
+    /**
+     * Construct a Maybe holding a value.
+     */
+    inline Maybe(const T& value);
+
+    /**
+     * Construct a Maybe holding a value.
+     */
+    inline Maybe(T&& value);
+
+    /**
+     * True if this holds a value, false if
+     * it holds Nothing.
+     */
+    inline operator bool() const;
+
+    /**
+     * Gets the value if one exists, or else
+     * panics.
+     */
+    inline T& value();
+
+    /**
+     * Gets the value if one exists, or else
+     * panics.
+     */
+    inline const T& value() const;
+
+private:
+    template <typename U>
+    friend class Maybe;
+
+    void destroy();
+
+    bool mNothing;
+
+    typename std::aligned_storage<sizeof(T), alignof(T)>::type mStorage;
+};
+
+template <typename T>
+Maybe<T>::Maybe()
+: mNothing(true) {
+}
+
+template <typename T>
+Maybe<T>::~Maybe() {
+    if (!mNothing) {
+        destroy();
+    }
+}
+
+template <typename T>
+template <typename U>
+Maybe<T>::Maybe(const Maybe<U>& rhs)
+: mNothing(rhs.mNothing) {
+    if (!rhs.mNothing) {
+        new (&mStorage) T(reinterpret_cast<const U&>(rhs.mStorage));
+    }
+}
+
+template <typename T>
+template <typename U>
+Maybe<T>::Maybe(Maybe<U>&& rhs)
+: mNothing(rhs.mNothing) {
+    if (!rhs.mNothing) {
+        rhs.mNothing = true;
+
+        // Move the value from rhs.
+        new (&mStorage) T(std::move(reinterpret_cast<U&>(rhs.mStorage)));
+
+        // Since the value in rhs is now Nothing,
+        // run the destructor for the value.
+        rhs.destroy();
+    }
+}
+
+template <typename T>
+template <typename U>
+Maybe<T>& Maybe<T>::operator=(const Maybe<U>& rhs) {
+    if (mNothing && rhs.mNothing) {
+        // Both are nothing, nothing to do.
+        return *this;
+    } else if  (!mNothing && !rhs.mNothing) {
+        // We both are something, so assign rhs to us.
+        reinterpret_cast<T&>(mStorage) = reinterpret_cast<const U&>(rhs.mStorage);
+    } else if (mNothing) {
+        // We are nothing but rhs is something.
+        mNothing = rhs.mNothing;
+
+        // Copy the value from rhs.
+        new (&mStorage) T(reinterpret_cast<const U&>(rhs.mStorage));
+    } else {
+        // We are something but rhs is nothing, so destroy our value.
+        mNothing = rhs.mNothing;
+        destroy();
+    }
+    return *this;
+}
+
+template <typename T>
+template <typename U>
+Maybe<T>& Maybe<T>::operator=(Maybe<U>&& rhs) {
+    if (mNothing && rhs.mNothing) {
+        // Both are nothing, nothing to do.
+        return *this;
+    } else if  (!mNothing && !rhs.mNothing) {
+        // We both are something, so move assign rhs to us.
+        rhs.mNothing = true;
+        reinterpret_cast<T&>(mStorage) = std::move(reinterpret_cast<U&>(rhs.mStorage));
+        rhs.destroy();
+    } else if (mNothing) {
+        // We are nothing but rhs is something.
+        mNothing = rhs.mNothing;
+
+        // Move the value from rhs.
+        new (&mStorage) T(std::move(reinterpret_cast<U&>(rhs.mStorage)));
+        rhs.destroy();
+    } else {
+        // We are something but rhs is nothing, so destroy our value.
+        mNothing = rhs.mNothing;
+        destroy();
+    }
+    return *this;
+}
+
+template <typename T>
+Maybe<T>::Maybe(const T& value)
+: mNothing(false) {
+    new (&mStorage) T(value);
+}
+
+template <typename T>
+Maybe<T>::Maybe(T&& value)
+: mNothing(false) {
+    new (&mStorage) T(std::forward<T>(value));
+}
+
+template <typename T>
+Maybe<T>::operator bool() const {
+    return !mNothing;
+}
+
+template <typename T>
+T& Maybe<T>::value() {
+    assert(!mNothing && "Maybe<T>::value() called on Nothing");
+    return reinterpret_cast<T&>(mStorage);
+}
+
+template <typename T>
+const T& Maybe<T>::value() const {
+    assert(!mNothing && "Maybe<T>::value() called on Nothing");
+    return reinterpret_cast<const T&>(mStorage);
+}
+
+template <typename T>
+void Maybe<T>::destroy() {
+    reinterpret_cast<T&>(mStorage).~T();
+}
+
+template <typename T>
+inline Maybe<typename std::remove_reference<T>::type> make_value(T&& value) {
+    return Maybe<typename std::remove_reference<T>::type>(std::forward<T>(value));
+}
+
+template <typename T>
+inline Maybe<T> make_nothing() {
+    return Maybe<T>();
+}
+
+} // namespace aapt
+
+#endif // AAPT_MAYBE_H
diff --git a/tools/aapt2/Maybe_test.cpp b/tools/aapt2/Maybe_test.cpp
new file mode 100644
index 0000000..348d7dd
--- /dev/null
+++ b/tools/aapt2/Maybe_test.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <string>
+
+#include "Maybe.h"
+
+namespace aapt {
+
+struct Dummy {
+    Dummy() {
+        std::cerr << "Constructing Dummy " << (void *) this << std::endl;
+    }
+
+    Dummy(const Dummy& rhs) {
+        std::cerr << "Copying Dummy " << (void *) this << " from " << (const void*) &rhs << std::endl;
+    }
+
+    Dummy(Dummy&& rhs) {
+        std::cerr << "Moving Dummy " << (void *) this << " from " << (void*) &rhs << std::endl;
+    }
+
+    ~Dummy() {
+        std::cerr << "Destroying Dummy " << (void *) this << std::endl;
+    }
+};
+
+TEST(MaybeTest, MakeNothing) {
+    Maybe<int> val = make_nothing<int>();
+    EXPECT_FALSE(val);
+
+    Maybe<std::string> val2 = make_nothing<std::string>();
+    EXPECT_FALSE(val2);
+
+    val2 = make_nothing<std::string>();
+    EXPECT_FALSE(val2);
+}
+
+TEST(MaybeTest, MakeSomething) {
+    Maybe<int> val = make_value(23);
+    ASSERT_TRUE(val);
+    EXPECT_EQ(23, val.value());
+
+    Maybe<std::string> val2 = make_value(std::string("hey"));
+    ASSERT_TRUE(val2);
+    EXPECT_EQ(std::string("hey"), val2.value());
+}
+
+TEST(MaybeTest, Lifecycle) {
+    Maybe<Dummy> val = make_nothing<Dummy>();
+
+    Maybe<Dummy> val2 = make_value(Dummy());
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ResChunkPullParser.cpp b/tools/aapt2/ResChunkPullParser.cpp
new file mode 100644
index 0000000..78ea60e
--- /dev/null
+++ b/tools/aapt2/ResChunkPullParser.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#include "ResChunkPullParser.h"
+
+#include <androidfw/ResourceTypes.h>
+#include <cstddef>
+
+namespace aapt {
+
+using android::ResChunk_header;
+
+ResChunkPullParser::Event ResChunkPullParser::next() {
+    if (!isGoodEvent(mEvent)) {
+        return mEvent;
+    }
+
+    if (mEvent == Event::StartDocument) {
+        mCurrentChunk = mData;
+    } else {
+        mCurrentChunk = reinterpret_cast<const ResChunk_header*>(
+                reinterpret_cast<const char*>(mCurrentChunk) + mCurrentChunk->size);
+    }
+
+    const std::ptrdiff_t diff = reinterpret_cast<const char*>(mCurrentChunk)
+            - reinterpret_cast<const char*>(mData);
+    assert(diff >= 0 && "diff is negative");
+    const size_t offset = static_cast<const size_t>(diff);
+
+    if (offset == mLen) {
+        mCurrentChunk = nullptr;
+        return (mEvent = Event::EndDocument);
+    } else if (offset + sizeof(ResChunk_header) > mLen) {
+        mLastError = "chunk is past the end of the document";
+        mCurrentChunk = nullptr;
+        return (mEvent = Event::BadDocument);
+    }
+
+    if (mCurrentChunk->headerSize < sizeof(ResChunk_header)) {
+        mLastError = "chunk has too small header";
+        mCurrentChunk = nullptr;
+        return (mEvent = Event::BadDocument);
+    } else if (mCurrentChunk->size < mCurrentChunk->headerSize) {
+        mLastError = "chunk's total size is smaller than header";
+        mCurrentChunk = nullptr;
+        return (mEvent = Event::BadDocument);
+    } else if (offset + mCurrentChunk->size > mLen) {
+        mLastError = "chunk's data extends past the end of the document";
+        mCurrentChunk = nullptr;
+        return (mEvent = Event::BadDocument);
+    }
+    return (mEvent = Event::Chunk);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ResChunkPullParser.h b/tools/aapt2/ResChunkPullParser.h
new file mode 100644
index 0000000..7366c89
--- /dev/null
+++ b/tools/aapt2/ResChunkPullParser.h
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_RES_CHUNK_PULL_PARSER_H
+#define AAPT_RES_CHUNK_PULL_PARSER_H
+
+#include <androidfw/ResourceTypes.h>
+#include <string>
+
+namespace aapt {
+
+/**
+ * A pull parser, modeled after XmlPullParser, that reads
+ * android::ResChunk_header structs from a block of data.
+ *
+ * An android::ResChunk_header specifies a type, headerSize,
+ * and size. The pull parser will verify that the chunk's size
+ * doesn't extend beyond the available data, and will iterate
+ * over each chunk in the given block of data.
+ *
+ * Processing nested chunks is done by creating a new ResChunkPullParser
+ * pointing to the data portion of a chunk.
+ */
+class ResChunkPullParser {
+public:
+    enum class Event {
+        StartDocument,
+        EndDocument,
+        BadDocument,
+
+        Chunk,
+    };
+
+    /**
+     * Returns false if the event is EndDocument or BadDocument.
+     */
+    static bool isGoodEvent(Event event);
+
+    /**
+     * Create a ResChunkPullParser to read android::ResChunk_headers
+     * from the memory pointed to by data, of len bytes.
+     */
+    ResChunkPullParser(const void* data, size_t len);
+
+    ResChunkPullParser(const ResChunkPullParser&) = delete;
+
+    Event getEvent() const;
+    const std::string& getLastError() const;
+    const android::ResChunk_header* getChunk() const;
+
+    /**
+     * Move to the next android::ResChunk_header.
+     */
+    Event next();
+
+private:
+    Event mEvent;
+    const android::ResChunk_header* mData;
+    size_t mLen;
+    const android::ResChunk_header* mCurrentChunk;
+    std::string mLastError;
+};
+
+//
+// Implementation
+//
+
+inline bool ResChunkPullParser::isGoodEvent(ResChunkPullParser::Event event) {
+    return event != Event::EndDocument && event != Event::BadDocument;
+}
+
+inline ResChunkPullParser::ResChunkPullParser(const void* data, size_t len) :
+        mEvent(Event::StartDocument),
+        mData(reinterpret_cast<const android::ResChunk_header*>(data)),
+        mLen(len),
+        mCurrentChunk(nullptr) {
+}
+
+inline ResChunkPullParser::Event ResChunkPullParser::getEvent() const {
+    return mEvent;
+}
+
+inline const std::string& ResChunkPullParser::getLastError() const {
+    return mLastError;
+}
+
+inline const android::ResChunk_header* ResChunkPullParser::getChunk() const {
+    return mCurrentChunk;
+}
+
+} // namespace aapt
+
+#endif // AAPT_RES_CHUNK_PULL_PARSER_H
diff --git a/tools/aapt2/Resolver.cpp b/tools/aapt2/Resolver.cpp
new file mode 100644
index 0000000..93b5e98
--- /dev/null
+++ b/tools/aapt2/Resolver.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+#include "Maybe.h"
+#include "Resolver.h"
+#include "Resource.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "Util.h"
+
+#include <androidfw/AssetManager.h>
+#include <androidfw/ResourceTypes.h>
+#include <memory>
+#include <vector>
+
+namespace aapt {
+
+Resolver::Resolver(std::shared_ptr<const ResourceTable> table,
+                   std::shared_ptr<const android::AssetManager> sources) :
+        mTable(table), mSources(sources) {
+}
+
+Maybe<ResourceId> Resolver::findId(const ResourceName& name) {
+    Maybe<Entry> result = findAttribute(name);
+    if (result) {
+        return result.value().id;
+    }
+    return {};
+}
+
+Maybe<Resolver::Entry> Resolver::findAttribute(const ResourceName& name) {
+    auto cacheIter = mCache.find(name);
+    if (cacheIter != std::end(mCache)) {
+        return Entry{ cacheIter->second.id, cacheIter->second.attr.get() };
+    }
+
+    const ResourceTableType* type;
+    const ResourceEntry* entry;
+    std::tie(type, entry) = mTable->findResource(name);
+    if (type && entry) {
+        Entry result = {};
+        if (mTable->getPackageId() != ResourceTable::kUnsetPackageId &&
+                type->typeId != ResourceTableType::kUnsetTypeId &&
+                entry->entryId != ResourceEntry::kUnsetEntryId) {
+            result.id = ResourceId(mTable->getPackageId(), type->typeId, entry->entryId);
+        }
+
+        if (!entry->values.empty()) {
+            visitFunc<Attribute>(*entry->values.front().value, [&result](Attribute& attr) {
+                    result.attr = &attr;
+            });
+        }
+        return result;
+    }
+
+    const CacheEntry* cacheEntry = buildCacheEntry(name);
+    if (cacheEntry) {
+        return Entry{ cacheEntry->id, cacheEntry->attr.get() };
+    }
+    return {};
+}
+
+/**
+ * This is called when we need to lookup a resource name in the AssetManager.
+ * Since the values in the AssetManager are not parsed like in a ResourceTable,
+ * we must create Attribute objects here if we find them.
+ */
+const Resolver::CacheEntry* Resolver::buildCacheEntry(const ResourceName& name) {
+    const android::ResTable& table = mSources->getResources(false);
+
+    const StringPiece16 type16 = toString(name.type);
+    ResourceId resId {
+        table.identifierForName(
+                name.entry.data(), name.entry.size(),
+                type16.data(), type16.size(),
+                name.package.data(), name.package.size())
+    };
+
+    if (!resId.isValid()) {
+        return nullptr;
+    }
+
+    CacheEntry& entry = mCache[name];
+    entry.id = resId;
+
+    //
+    // Now check to see if this resource is an Attribute.
+    //
+
+    const android::ResTable::bag_entry* bagBegin;
+    ssize_t bags = table.lockBag(resId.id, &bagBegin);
+    if (bags < 1) {
+        table.unlockBag(bagBegin);
+        return &entry;
+    }
+
+    // Look for the ATTR_TYPE key in the bag and check the types it supports.
+    uint32_t attrTypeMask = 0;
+    for (ssize_t i = 0; i < bags; i++) {
+        if (bagBegin[i].map.name.ident == android::ResTable_map::ATTR_TYPE) {
+            attrTypeMask = bagBegin[i].map.value.data;
+        }
+    }
+
+    entry.attr = util::make_unique<Attribute>(false);
+
+    if (attrTypeMask & android::ResTable_map::TYPE_ENUM ||
+            attrTypeMask & android::ResTable_map::TYPE_FLAGS) {
+        for (ssize_t i = 0; i < bags; i++) {
+            if (Res_INTERNALID(bagBegin[i].map.name.ident)) {
+                // Internal IDs are special keys, which are not enum/flag symbols, so skip.
+                continue;
+            }
+
+            android::ResTable::resource_name symbolName;
+            bool result = table.getResourceName(bagBegin[i].map.name.ident, false,
+                    &symbolName);
+            assert(result);
+            const ResourceType* type = parseResourceType(
+                    StringPiece16(symbolName.type, symbolName.typeLen));
+            assert(type);
+
+            entry.attr->symbols.push_back(Attribute::Symbol{
+                    Reference(ResourceNameRef(
+                                StringPiece16(symbolName.package, symbolName.packageLen),
+                                *type,
+                                StringPiece16(symbolName.name, symbolName.nameLen))),
+                            bagBegin[i].map.value.data
+            });
+        }
+    }
+
+    entry.attr->typeMask |= attrTypeMask;
+    table.unlockBag(bagBegin);
+    return &entry;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/Resolver.h b/tools/aapt2/Resolver.h
new file mode 100644
index 0000000..90a8cd9
--- /dev/null
+++ b/tools/aapt2/Resolver.h
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_RESOLVER_H
+#define AAPT_RESOLVER_H
+
+#include "Maybe.h"
+#include "Resource.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+
+#include <androidfw/AssetManager.h>
+#include <androidfw/ResourceTypes.h>
+#include <memory>
+#include <vector>
+
+namespace aapt {
+
+/**
+ * Resolves symbolic references (package:type/entry) into resource IDs/objects.
+ * Encapsulates the search of library sources as well as the local ResourceTable.
+ */
+class Resolver {
+public:
+    /**
+     * Creates a resolver with a local ResourceTable and an AssetManager
+     * loaded with library packages.
+     */
+    Resolver(std::shared_ptr<const ResourceTable> table,
+             std::shared_ptr<const android::AssetManager> sources);
+
+    Resolver(const Resolver&) = delete; // Not copyable.
+
+    /**
+     * Holds the result of a resource name lookup.
+     */
+    struct Entry {
+        /**
+         * The ID of the resource. ResourceId::isValid() may
+         * return false if the resource has not been assigned
+         * an ID.
+         */
+        ResourceId id;
+
+        /**
+         * If the resource is an attribute, this will point
+         * to a valid Attribute object, or else it will be
+         * nullptr.
+         */
+        const Attribute* attr;
+    };
+
+    /**
+     * Return the package to use when none is specified. This
+     * is the package name of the app being built.
+     */
+    const std::u16string& getDefaultPackage() const;
+
+    /**
+     * Returns a ResourceID if the name is found. The ResourceID
+     * may not be valid if the resource was not assigned an ID.
+     */
+    Maybe<ResourceId> findId(const ResourceName& name);
+
+    /**
+     * Returns an Entry if the name is found. Entry::attr
+     * may be nullptr if the resource is not an attribute.
+     */
+    Maybe<Entry> findAttribute(const ResourceName& name);
+
+    const android::ResTable& getResTable() const;
+
+private:
+    struct CacheEntry {
+        ResourceId id;
+        std::unique_ptr<Attribute> attr;
+    };
+
+    const CacheEntry* buildCacheEntry(const ResourceName& name);
+
+    std::shared_ptr<const ResourceTable> mTable;
+    std::shared_ptr<const android::AssetManager> mSources;
+    std::map<ResourceName, CacheEntry> mCache;
+};
+
+inline const std::u16string& Resolver::getDefaultPackage() const {
+    return mTable->getPackage();
+}
+
+inline const android::ResTable& Resolver::getResTable() const {
+    return mSources->getResources(false);
+}
+
+} // namespace aapt
+
+#endif // AAPT_RESOLVER_H
diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp
new file mode 100644
index 0000000..287d8de
--- /dev/null
+++ b/tools/aapt2/Resource.cpp
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+#include "Resource.h"
+#include "StringPiece.h"
+
+#include <map>
+#include <string>
+
+namespace aapt {
+
+StringPiece16 toString(ResourceType type) {
+    switch (type) {
+        case ResourceType::kAnim:          return u"anim";
+        case ResourceType::kAnimator:      return u"animator";
+        case ResourceType::kArray:         return u"array";
+        case ResourceType::kAttr:          return u"attr";
+        case ResourceType::kAttrPrivate:   return u"attr";
+        case ResourceType::kBool:          return u"bool";
+        case ResourceType::kColor:         return u"color";
+        case ResourceType::kDimen:         return u"dimen";
+        case ResourceType::kDrawable:      return u"drawable";
+        case ResourceType::kFraction:      return u"fraction";
+        case ResourceType::kId:            return u"id";
+        case ResourceType::kInteger:       return u"integer";
+        case ResourceType::kIntegerArray:  return u"integer-array";
+        case ResourceType::kInterpolator:  return u"interpolator";
+        case ResourceType::kLayout:        return u"layout";
+        case ResourceType::kMenu:          return u"menu";
+        case ResourceType::kMipmap:        return u"mipmap";
+        case ResourceType::kPlurals:       return u"plurals";
+        case ResourceType::kRaw:           return u"raw";
+        case ResourceType::kString:        return u"string";
+        case ResourceType::kStyle:         return u"style";
+        case ResourceType::kStyleable:     return u"styleable";
+        case ResourceType::kTransition:    return u"transition";
+        case ResourceType::kXml:           return u"xml";
+    }
+    return {};
+}
+
+static const std::map<StringPiece16, ResourceType> sResourceTypeMap {
+        { u"anim", ResourceType::kAnim },
+        { u"animator", ResourceType::kAnimator },
+        { u"array", ResourceType::kArray },
+        { u"attr", ResourceType::kAttr },
+        { u"^attr-private", ResourceType::kAttrPrivate },
+        { u"bool", ResourceType::kBool },
+        { u"color", ResourceType::kColor },
+        { u"dimen", ResourceType::kDimen },
+        { u"drawable", ResourceType::kDrawable },
+        { u"fraction", ResourceType::kFraction },
+        { u"id", ResourceType::kId },
+        { u"integer", ResourceType::kInteger },
+        { u"integer-array", ResourceType::kIntegerArray },
+        { u"interpolator", ResourceType::kInterpolator },
+        { u"layout", ResourceType::kLayout },
+        { u"menu", ResourceType::kMenu },
+        { u"mipmap", ResourceType::kMipmap },
+        { u"plurals", ResourceType::kPlurals },
+        { u"raw", ResourceType::kRaw },
+        { u"string", ResourceType::kString },
+        { u"style", ResourceType::kStyle },
+        { u"styleable", ResourceType::kStyleable },
+        { u"transition", ResourceType::kTransition },
+        { u"xml", ResourceType::kXml },
+};
+
+const ResourceType* parseResourceType(const StringPiece16& str) {
+    auto iter = sResourceTypeMap.find(str);
+    if (iter == std::end(sResourceTypeMap)) {
+        return nullptr;
+    }
+    return &iter->second;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
new file mode 100644
index 0000000..4d2c64c
--- /dev/null
+++ b/tools/aapt2/Resource.h
@@ -0,0 +1,277 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_RESOURCE_H
+#define AAPT_RESOURCE_H
+
+#include "StringPiece.h"
+
+#include <iomanip>
+#include <limits>
+#include <string>
+#include <tuple>
+
+namespace aapt {
+
+/**
+ * The various types of resource types available. Corresponds
+ * to the 'type' in package:type/entry.
+ */
+enum class ResourceType {
+    kAnim,
+    kAnimator,
+    kArray,
+    kAttr,
+    kAttrPrivate,
+    kBool,
+    kColor,
+    kDimen,
+    kDrawable,
+    kFraction,
+    kId,
+    kInteger,
+    kIntegerArray,
+    kInterpolator,
+    kLayout,
+    kMenu,
+    kMipmap,
+    kPlurals,
+    kRaw,
+    kString,
+    kStyle,
+    kStyleable,
+    kTransition,
+    kXml,
+};
+
+StringPiece16 toString(ResourceType type);
+
+/**
+ * Returns a pointer to a valid ResourceType, or nullptr if
+ * the string was invalid.
+ */
+const ResourceType* parseResourceType(const StringPiece16& str);
+
+/**
+ * A resource's name. This can uniquely identify
+ * a resource in the ResourceTable.
+ */
+struct ResourceName {
+    std::u16string package;
+    ResourceType type;
+    std::u16string entry;
+
+    bool isValid() const;
+    bool operator<(const ResourceName& rhs) const;
+    bool operator==(const ResourceName& rhs) const;
+    bool operator!=(const ResourceName& rhs) const;
+};
+
+/**
+ * Same as ResourceName, but uses StringPieces instead.
+ * Use this if you need to avoid copying and know that
+ * the lifetime of this object is shorter than that
+ * of the original string.
+ */
+struct ResourceNameRef {
+    StringPiece16 package;
+    ResourceType type;
+    StringPiece16 entry;
+
+    ResourceNameRef() = default;
+    ResourceNameRef(const ResourceNameRef&) = default;
+    ResourceNameRef(ResourceNameRef&&) = default;
+    ResourceNameRef(const ResourceName& rhs);
+    ResourceNameRef(const StringPiece16& p, ResourceType t, const StringPiece16& e);
+    ResourceNameRef& operator=(const ResourceName& rhs);
+
+    ResourceName toResourceName() const;
+    bool isValid() const;
+
+    bool operator<(const ResourceNameRef& rhs) const;
+    bool operator==(const ResourceNameRef& rhs) const;
+    bool operator!=(const ResourceNameRef& rhs) const;
+};
+
+/**
+ * A binary identifier representing a resource. Internally it
+ * is a 32bit integer split as follows:
+ *
+ * 0xPPTTEEEE
+ *
+ * PP: 8 bit package identifier. 0x01 is reserved for system
+ *     and 0x7f is reserved for the running app.
+ * TT: 8 bit type identifier. 0x00 is invalid.
+ * EEEE: 16 bit entry identifier.
+ */
+struct ResourceId {
+    uint32_t id;
+
+    ResourceId();
+    ResourceId(const ResourceId& rhs);
+    ResourceId(uint32_t resId);
+    ResourceId(size_t p, size_t t, size_t e);
+
+    bool isValid() const;
+    uint8_t packageId() const;
+    uint8_t typeId() const;
+    uint16_t entryId() const;
+    bool operator<(const ResourceId& rhs) const;
+};
+
+//
+// ResourceId implementation.
+//
+
+inline ResourceId::ResourceId() : id(0) {
+}
+
+inline ResourceId::ResourceId(const ResourceId& rhs) : id(rhs.id) {
+}
+
+inline ResourceId::ResourceId(uint32_t resId) : id(resId) {
+}
+
+inline ResourceId::ResourceId(size_t p, size_t t, size_t e) : id(0) {
+    if (p > std::numeric_limits<uint8_t>::max() ||
+            t > std::numeric_limits<uint8_t>::max() ||
+            e > std::numeric_limits<uint16_t>::max()) {
+        // This will leave the ResourceId in an invalid state.
+        return;
+    }
+
+    id = (static_cast<uint8_t>(p) << 24) |
+         (static_cast<uint8_t>(t) << 16) |
+         static_cast<uint16_t>(e);
+}
+
+inline bool ResourceId::isValid() const {
+    return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
+}
+
+inline uint8_t ResourceId::packageId() const {
+    return static_cast<uint8_t>(id >> 24);
+}
+
+inline uint8_t ResourceId::typeId() const {
+    return static_cast<uint8_t>(id >> 16);
+}
+
+inline uint16_t ResourceId::entryId() const {
+    return static_cast<uint16_t>(id);
+}
+
+inline bool ResourceId::operator<(const ResourceId& rhs) const {
+    return id < rhs.id;
+}
+
+inline ::std::ostream& operator<<(::std::ostream& out,
+        const ResourceId& resId) {
+    std::ios_base::fmtflags oldFlags = out.flags();
+    char oldFill = out.fill();
+    out << "0x" << std::internal << std::setfill('0') << std::setw(8)
+        << std::hex << resId.id;
+    out.flags(oldFlags);
+    out.fill(oldFill);
+    return out;
+}
+
+//
+// ResourceType implementation.
+//
+
+inline ::std::ostream& operator<<(::std::ostream& out,
+        const ResourceType& val) {
+    return out << toString(val);
+}
+
+//
+// ResourceName implementation.
+//
+
+inline bool ResourceName::isValid() const {
+    return !package.empty() && !entry.empty();
+}
+
+inline bool ResourceName::operator<(const ResourceName& rhs) const {
+    return std::tie(package, type, entry)
+            < std::tie(rhs.package, rhs.type, rhs.entry);
+}
+
+inline bool ResourceName::operator==(const ResourceName& rhs) const {
+    return std::tie(package, type, entry)
+            == std::tie(rhs.package, rhs.type, rhs.entry);
+}
+
+inline bool ResourceName::operator!=(const ResourceName& rhs) const {
+    return std::tie(package, type, entry)
+            != std::tie(rhs.package, rhs.type, rhs.entry);
+}
+
+//
+// ResourceNameRef implementation.
+//
+
+inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs) :
+        package(rhs.package), type(rhs.type), entry(rhs.entry) {
+}
+
+inline ResourceNameRef::ResourceNameRef(const StringPiece16& p, ResourceType t,
+                                        const StringPiece16& e) :
+        package(p), type(t), entry(e) {
+}
+
+inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) {
+    package = rhs.package;
+    type = rhs.type;
+    entry = rhs.entry;
+    return *this;
+}
+
+inline ResourceName ResourceNameRef::toResourceName() const {
+    return { package.toString(), type, entry.toString() };
+}
+
+inline bool ResourceNameRef::isValid() const {
+    return !package.empty() && !entry.empty();
+}
+
+inline bool ResourceNameRef::operator<(const ResourceNameRef& rhs) const {
+    return std::tie(package, type, entry)
+            < std::tie(rhs.package, rhs.type, rhs.entry);
+}
+
+inline bool ResourceNameRef::operator==(const ResourceNameRef& rhs) const {
+    return std::tie(package, type, entry)
+            == std::tie(rhs.package, rhs.type, rhs.entry);
+}
+
+inline bool ResourceNameRef::operator!=(const ResourceNameRef& rhs) const {
+    return std::tie(package, type, entry)
+            != std::tie(rhs.package, rhs.type, rhs.entry);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& out,
+        const ResourceNameRef& name) {
+    if (!name.package.empty()) {
+        out << name.package << ":";
+    }
+    return out << name.type << "/" << name.entry;
+}
+
+} // namespace aapt
+
+#endif // AAPT_RESOURCE_H
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
new file mode 100644
index 0000000..4c96187
--- /dev/null
+++ b/tools/aapt2/ResourceParser.cpp
@@ -0,0 +1,1317 @@
+/*
+ * 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.
+ */
+
+#include "Logger.h"
+#include "ResourceParser.h"
+#include "ResourceValues.h"
+#include "ScopedXmlPullParser.h"
+#include "SourceXmlPullParser.h"
+#include "Util.h"
+#include "XliffXmlPullParser.h"
+
+namespace aapt {
+
+void ResourceParser::extractResourceName(const StringPiece16& str, StringPiece16* outPackage,
+                                         StringPiece16* outType, StringPiece16* outEntry) {
+    const char16_t* start = str.data();
+    const char16_t* end = start + str.size();
+    const char16_t* current = start;
+    while (current != end) {
+        if (outType->size() == 0 && *current == u'/') {
+            outType->assign(start, current - start);
+            start = current + 1;
+        } else if (outPackage->size() == 0 && *current == u':') {
+            outPackage->assign(start, current - start);
+            start = current + 1;
+        }
+        current++;
+    }
+    outEntry->assign(start, end - start);
+}
+
+bool ResourceParser::tryParseReference(const StringPiece16& str, ResourceNameRef* outRef,
+                                       bool* outCreate, bool* outPrivate) {
+    StringPiece16 trimmedStr(util::trimWhitespace(str));
+    if (trimmedStr.empty()) {
+        return false;
+    }
+
+    if (trimmedStr.data()[0] == u'@') {
+        size_t offset = 1;
+        *outCreate = false;
+        if (trimmedStr.data()[1] == u'+') {
+            *outCreate = true;
+            offset += 1;
+        } else if (trimmedStr.data()[1] == u'*') {
+            *outPrivate = true;
+            offset += 1;
+        }
+        StringPiece16 package;
+        StringPiece16 type;
+        StringPiece16 entry;
+        extractResourceName(trimmedStr.substr(offset, trimmedStr.size() - offset),
+                            &package, &type, &entry);
+
+        const ResourceType* parsedType = parseResourceType(type);
+        if (!parsedType) {
+            return false;
+        }
+
+        if (*outCreate && *parsedType != ResourceType::kId) {
+            return false;
+        }
+
+        outRef->package = package;
+        outRef->type = *parsedType;
+        outRef->entry = entry;
+        return true;
+    }
+    return false;
+}
+
+bool ResourceParser::tryParseAttributeReference(const StringPiece16& str,
+                                                ResourceNameRef* outRef) {
+    StringPiece16 trimmedStr(util::trimWhitespace(str));
+    if (trimmedStr.empty()) {
+        return false;
+    }
+
+    if (*trimmedStr.data() == u'?') {
+        StringPiece16 package;
+        StringPiece16 type;
+        StringPiece16 entry;
+        extractResourceName(trimmedStr.substr(1, trimmedStr.size() - 1), &package, &type, &entry);
+
+        if (!type.empty() && type != u"attr") {
+            return false;
+        }
+
+        outRef->package = package;
+        outRef->type = ResourceType::kAttr;
+        outRef->entry = entry;
+        return true;
+    }
+    return false;
+}
+
+std::unique_ptr<Reference> ResourceParser::tryParseReference(const StringPiece16& str,
+                                                             const StringPiece16& defaultPackage,
+                                                             bool* outCreate) {
+    ResourceNameRef ref;
+    bool privateRef = false;
+    if (tryParseReference(str, &ref, outCreate, &privateRef)) {
+        if (ref.package.empty()) {
+            ref.package = defaultPackage;
+        }
+        std::unique_ptr<Reference> value = util::make_unique<Reference>(ref);
+        value->privateReference = privateRef;
+        return value;
+    }
+
+    if (tryParseAttributeReference(str, &ref)) {
+        if (ref.package.empty()) {
+            ref.package = defaultPackage;
+        }
+        *outCreate = false;
+        return util::make_unique<Reference>(ref, Reference::Type::kAttribute);
+    }
+    return {};
+}
+
+std::unique_ptr<BinaryPrimitive> ResourceParser::tryParseNullOrEmpty(const StringPiece16& str) {
+    StringPiece16 trimmedStr(util::trimWhitespace(str));
+    uint32_t data = 0;
+    if (trimmedStr == u"@null") {
+        data = android::Res_value::DATA_NULL_UNDEFINED;
+    } else if (trimmedStr == u"@empty") {
+        data = android::Res_value::DATA_NULL_EMPTY;
+    } else {
+        return {};
+    }
+
+    android::Res_value value = {};
+    value.dataType = android::Res_value::TYPE_NULL;
+    value.data = data;
+    return util::make_unique<BinaryPrimitive>(value);
+}
+
+std::unique_ptr<BinaryPrimitive> ResourceParser::tryParseEnumSymbol(const Attribute& enumAttr,
+                                                                    const StringPiece16& str) {
+    StringPiece16 trimmedStr(util::trimWhitespace(str));
+    for (const auto& entry : enumAttr.symbols) {
+        // Enum symbols are stored as @package:id/symbol resources,
+        // so we need to match against the 'entry' part of the identifier.
+        const ResourceName& enumSymbolResourceName = entry.symbol.name;
+        if (trimmedStr == enumSymbolResourceName.entry) {
+            android::Res_value value = {};
+            value.dataType = android::Res_value::TYPE_INT_DEC;
+            value.data = entry.value;
+            return util::make_unique<BinaryPrimitive>(value);
+        }
+    }
+    return {};
+}
+
+std::unique_ptr<BinaryPrimitive> ResourceParser::tryParseFlagSymbol(const Attribute& flagAttr,
+                                                                    const StringPiece16& str) {
+    android::Res_value flags = {};
+    flags.dataType = android::Res_value::TYPE_INT_DEC;
+
+    for (StringPiece16 part : util::tokenize(str, u'|')) {
+        StringPiece16 trimmedPart = util::trimWhitespace(part);
+
+        bool flagSet = false;
+        for (const auto& entry : flagAttr.symbols) {
+            // Flag symbols are stored as @package:id/symbol resources,
+            // so we need to match against the 'entry' part of the identifier.
+            const ResourceName& flagSymbolResourceName = entry.symbol.name;
+            if (trimmedPart == flagSymbolResourceName.entry) {
+                flags.data |= entry.value;
+                flagSet = true;
+                break;
+            }
+        }
+
+        if (!flagSet) {
+            return {};
+        }
+    }
+    return util::make_unique<BinaryPrimitive>(flags);
+}
+
+static uint32_t parseHex(char16_t c, bool* outError) {
+   if (c >= u'0' && c <= u'9') {
+        return c - u'0';
+    } else if (c >= u'a' && c <= u'f') {
+        return c - u'a' + 0xa;
+    } else if (c >= u'A' && c <= u'F') {
+        return c - u'A' + 0xa;
+    } else {
+        *outError = true;
+        return 0xffffffffu;
+    }
+}
+
+std::unique_ptr<BinaryPrimitive> ResourceParser::tryParseColor(const StringPiece16& str) {
+    StringPiece16 colorStr(util::trimWhitespace(str));
+    const char16_t* start = colorStr.data();
+    const size_t len = colorStr.size();
+    if (len == 0 || start[0] != u'#') {
+        return {};
+    }
+
+    android::Res_value value = {};
+    bool error = false;
+    if (len == 4) {
+        value.dataType = android::Res_value::TYPE_INT_COLOR_RGB4;
+        value.data = 0xff000000u;
+        value.data |= parseHex(start[1], &error) << 20;
+        value.data |= parseHex(start[1], &error) << 16;
+        value.data |= parseHex(start[2], &error) << 12;
+        value.data |= parseHex(start[2], &error) << 8;
+        value.data |= parseHex(start[3], &error) << 4;
+        value.data |= parseHex(start[3], &error);
+    } else if (len == 5) {
+        value.dataType = android::Res_value::TYPE_INT_COLOR_ARGB4;
+        value.data |= parseHex(start[1], &error) << 28;
+        value.data |= parseHex(start[1], &error) << 24;
+        value.data |= parseHex(start[2], &error) << 20;
+        value.data |= parseHex(start[2], &error) << 16;
+        value.data |= parseHex(start[3], &error) << 12;
+        value.data |= parseHex(start[3], &error) << 8;
+        value.data |= parseHex(start[4], &error) << 4;
+        value.data |= parseHex(start[4], &error);
+    } else if (len == 7) {
+        value.dataType = android::Res_value::TYPE_INT_COLOR_RGB8;
+        value.data = 0xff000000u;
+        value.data |= parseHex(start[1], &error) << 20;
+        value.data |= parseHex(start[2], &error) << 16;
+        value.data |= parseHex(start[3], &error) << 12;
+        value.data |= parseHex(start[4], &error) << 8;
+        value.data |= parseHex(start[5], &error) << 4;
+        value.data |= parseHex(start[6], &error);
+    } else if (len == 9) {
+        value.dataType = android::Res_value::TYPE_INT_COLOR_ARGB8;
+        value.data |= parseHex(start[1], &error) << 28;
+        value.data |= parseHex(start[2], &error) << 24;
+        value.data |= parseHex(start[3], &error) << 20;
+        value.data |= parseHex(start[4], &error) << 16;
+        value.data |= parseHex(start[5], &error) << 12;
+        value.data |= parseHex(start[6], &error) << 8;
+        value.data |= parseHex(start[7], &error) << 4;
+        value.data |= parseHex(start[8], &error);
+    } else {
+        return {};
+    }
+    return error ? std::unique_ptr<BinaryPrimitive>() : util::make_unique<BinaryPrimitive>(value);
+}
+
+std::unique_ptr<BinaryPrimitive> ResourceParser::tryParseBool(const StringPiece16& str) {
+    StringPiece16 trimmedStr(util::trimWhitespace(str));
+    uint32_t data = 0;
+    if (trimmedStr == u"true" || trimmedStr == u"TRUE") {
+        data = 1;
+    } else if (trimmedStr != u"false" && trimmedStr != u"FALSE") {
+        return {};
+    }
+    android::Res_value value = {};
+    value.dataType = android::Res_value::TYPE_INT_BOOLEAN;
+    value.data = data;
+    return util::make_unique<BinaryPrimitive>(value);
+}
+
+std::unique_ptr<BinaryPrimitive> ResourceParser::tryParseInt(const StringPiece16& str) {
+    android::Res_value value;
+    if (!android::ResTable::stringToInt(str.data(), str.size(), &value)) {
+        return {};
+    }
+    return util::make_unique<BinaryPrimitive>(value);
+}
+
+std::unique_ptr<BinaryPrimitive> ResourceParser::tryParseFloat(const StringPiece16& str) {
+    android::Res_value value;
+    if (!android::ResTable::stringToFloat(str.data(), str.size(), &value)) {
+        return {};
+    }
+    return util::make_unique<BinaryPrimitive>(value);
+}
+
+uint32_t ResourceParser::androidTypeToAttributeTypeMask(uint16_t type) {
+    switch (type) {
+        case android::Res_value::TYPE_NULL:
+        case android::Res_value::TYPE_REFERENCE:
+        case android::Res_value::TYPE_ATTRIBUTE:
+        case android::Res_value::TYPE_DYNAMIC_REFERENCE:
+            return android::ResTable_map::TYPE_REFERENCE;
+
+        case android::Res_value::TYPE_STRING:
+            return android::ResTable_map::TYPE_STRING;
+
+        case android::Res_value::TYPE_FLOAT:
+            return android::ResTable_map::TYPE_FLOAT;
+
+        case android::Res_value::TYPE_DIMENSION:
+            return android::ResTable_map::TYPE_DIMENSION;
+
+        case android::Res_value::TYPE_FRACTION:
+            return android::ResTable_map::TYPE_FRACTION;
+
+        case android::Res_value::TYPE_INT_DEC:
+        case android::Res_value::TYPE_INT_HEX:
+            return android::ResTable_map::TYPE_INTEGER |
+                    android::ResTable_map::TYPE_ENUM |
+                    android::ResTable_map::TYPE_FLAGS;
+
+        case android::Res_value::TYPE_INT_BOOLEAN:
+            return android::ResTable_map::TYPE_BOOLEAN;
+
+        case android::Res_value::TYPE_INT_COLOR_ARGB8:
+        case android::Res_value::TYPE_INT_COLOR_RGB8:
+        case android::Res_value::TYPE_INT_COLOR_ARGB4:
+        case android::Res_value::TYPE_INT_COLOR_RGB4:
+            return android::ResTable_map::TYPE_COLOR;
+
+        default:
+            return 0;
+    };
+}
+
+std::unique_ptr<Item> ResourceParser::parseItemForAttribute(
+        const StringPiece16& value, uint32_t typeMask, const StringPiece16& defaultPackage,
+        std::function<void(const ResourceName&)> onCreateReference) {
+    std::unique_ptr<BinaryPrimitive> nullOrEmpty = tryParseNullOrEmpty(value);
+    if (nullOrEmpty) {
+        return std::move(nullOrEmpty);
+    }
+
+    bool create = false;
+    std::unique_ptr<Reference> reference = tryParseReference(value, defaultPackage, &create);
+    if (reference) {
+        if (create && onCreateReference) {
+            onCreateReference(reference->name);
+        }
+        return std::move(reference);
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_COLOR) {
+        // Try parsing this as a color.
+        std::unique_ptr<BinaryPrimitive> color = tryParseColor(value);
+        if (color) {
+            return std::move(color);
+        }
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_BOOLEAN) {
+        // Try parsing this as a boolean.
+        std::unique_ptr<BinaryPrimitive> boolean = tryParseBool(value);
+        if (boolean) {
+            return std::move(boolean);
+        }
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_INTEGER) {
+        // Try parsing this as an integer.
+        std::unique_ptr<BinaryPrimitive> integer = tryParseInt(value);
+        if (integer) {
+            return std::move(integer);
+        }
+    }
+
+    const uint32_t floatMask = android::ResTable_map::TYPE_FLOAT |
+            android::ResTable_map::TYPE_DIMENSION |
+            android::ResTable_map::TYPE_FRACTION;
+    if (typeMask & floatMask) {
+        // Try parsing this as a float.
+        std::unique_ptr<BinaryPrimitive> floatingPoint = tryParseFloat(value);
+        if (floatingPoint) {
+            if (typeMask & androidTypeToAttributeTypeMask(floatingPoint->value.dataType)) {
+                return std::move(floatingPoint);
+            }
+        }
+    }
+    return {};
+}
+
+/**
+ * We successively try to parse the string as a resource type that the Attribute
+ * allows.
+ */
+std::unique_ptr<Item> ResourceParser::parseItemForAttribute(
+        const StringPiece16& str, const Attribute& attr, const StringPiece16& defaultPackage,
+        std::function<void(const ResourceName&)> onCreateReference) {
+    const uint32_t typeMask = attr.typeMask;
+    std::unique_ptr<Item> value = parseItemForAttribute(str, typeMask, defaultPackage,
+                                                        onCreateReference);
+    if (value) {
+        return value;
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_ENUM) {
+        // Try parsing this as an enum.
+        std::unique_ptr<BinaryPrimitive> enumValue = tryParseEnumSymbol(attr, str);
+        if (enumValue) {
+            return std::move(enumValue);
+        }
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_FLAGS) {
+        // Try parsing this as a flag.
+        std::unique_ptr<BinaryPrimitive> flagValue = tryParseFlagSymbol(attr, str);
+        if (flagValue) {
+            return std::move(flagValue);
+        }
+    }
+    return {};
+}
+
+ResourceParser::ResourceParser(const std::shared_ptr<ResourceTable>& table, const Source& source,
+                               const ConfigDescription& config,
+                               const std::shared_ptr<XmlPullParser>& parser) :
+        mTable(table), mSource(source), mConfig(config), mLogger(source),
+        mParser(std::make_shared<XliffXmlPullParser>(parser)) {
+}
+
+/**
+ * Build a string from XML that converts nested elements into Span objects.
+ */
+bool ResourceParser::flattenXmlSubtree(XmlPullParser* parser, std::u16string* outRawString,
+                                       StyleString* outStyleString) {
+    std::vector<Span> spanStack;
+
+    outRawString->clear();
+    outStyleString->spans.clear();
+    util::StringBuilder builder;
+    size_t depth = 1;
+    while (XmlPullParser::isGoodEvent(parser->next())) {
+        const XmlPullParser::Event event = parser->getEvent();
+        if (event == XmlPullParser::Event::kEndElement) {
+            depth--;
+            if (depth == 0) {
+                break;
+            }
+
+            spanStack.back().lastChar = builder.str().size();
+            outStyleString->spans.push_back(spanStack.back());
+            spanStack.pop_back();
+
+        } else if (event == XmlPullParser::Event::kText) {
+            // TODO(adamlesinski): Verify format strings.
+            outRawString->append(parser->getText());
+            builder.append(parser->getText());
+
+        } else if (event == XmlPullParser::Event::kStartElement) {
+            if (parser->getElementNamespace().size() > 0) {
+                mLogger.warn(parser->getLineNumber())
+                        << "skipping element '"
+                        << parser->getElementName()
+                        << "' with unknown namespace '"
+                        << parser->getElementNamespace()
+                        << "'."
+                        << std::endl;
+                XmlPullParser::skipCurrentElement(parser);
+                continue;
+            }
+            depth++;
+
+            // Build a span object out of the nested element.
+            std::u16string spanName = parser->getElementName();
+            const auto endAttrIter = parser->endAttributes();
+            for (auto attrIter = parser->beginAttributes(); attrIter != endAttrIter; ++attrIter) {
+                spanName += u";";
+                spanName += attrIter->name;
+                spanName += u"=";
+                spanName += attrIter->value;
+            }
+
+            if (builder.str().size() > std::numeric_limits<uint32_t>::max()) {
+                mLogger.error(parser->getLineNumber())
+                        << "style string '"
+                        << builder.str()
+                        << "' is too long."
+                        << std::endl;
+                return false;
+            }
+            spanStack.push_back(Span{ spanName, static_cast<uint32_t>(builder.str().size()) });
+
+        } else if (event == XmlPullParser::Event::kComment) {
+            // Skip
+        } else {
+            mLogger.warn(parser->getLineNumber())
+                    << "unknown event "
+                    << event
+                    << "."
+                    << std::endl;
+        }
+    }
+    assert(spanStack.empty() && "spans haven't been fully processed");
+
+    outStyleString->str = builder.str();
+    return true;
+}
+
+bool ResourceParser::parse() {
+    while (XmlPullParser::isGoodEvent(mParser->next())) {
+        if (mParser->getEvent() != XmlPullParser::Event::kStartElement) {
+            continue;
+        }
+
+        ScopedXmlPullParser parser(mParser.get());
+        if (!parser.getElementNamespace().empty() ||
+                parser.getElementName() != u"resources") {
+            mLogger.error(parser.getLineNumber())
+                    << "root element must be <resources> in the global namespace."
+                    << std::endl;
+            return false;
+        }
+
+        if (!parseResources(&parser)) {
+            return false;
+        }
+    }
+
+    if (mParser->getEvent() == XmlPullParser::Event::kBadDocument) {
+        mLogger.error(mParser->getLineNumber())
+                << mParser->getLastError()
+                << std::endl;
+        return false;
+    }
+    return true;
+}
+
+bool ResourceParser::parseResources(XmlPullParser* parser) {
+    bool success = true;
+
+    std::u16string comment;
+    while (XmlPullParser::isGoodEvent(parser->next())) {
+        const XmlPullParser::Event event = parser->getEvent();
+        if (event == XmlPullParser::Event::kComment) {
+            comment = parser->getComment();
+            continue;
+        }
+
+        if (event == XmlPullParser::Event::kText) {
+            if (!util::trimWhitespace(parser->getText()).empty()) {
+                comment = u"";
+            }
+            continue;
+        }
+
+        if (event != XmlPullParser::Event::kStartElement) {
+            continue;
+        }
+
+        ScopedXmlPullParser childParser(parser);
+
+        if (!childParser.getElementNamespace().empty()) {
+            // Skip unknown namespace.
+            continue;
+        }
+
+        StringPiece16 name = childParser.getElementName();
+        if (name == u"skip" || name == u"eat-comment") {
+            continue;
+        }
+
+        if (name == u"private-symbols") {
+            // Handle differently.
+            mLogger.note(childParser.getLineNumber())
+                    << "got a <private-symbols> tag."
+                    << std::endl;
+            continue;
+        }
+
+        const auto endAttrIter = childParser.endAttributes();
+        auto attrIter = childParser.findAttribute(u"", u"name");
+        if (attrIter == endAttrIter || attrIter->value.empty()) {
+            mLogger.error(childParser.getLineNumber())
+                    << "<" << name << "> tag must have a 'name' attribute."
+                    << std::endl;
+            success = false;
+            continue;
+        }
+
+        // Copy because our iterator will go out of scope when
+        // we parse more XML.
+        std::u16string attributeName = attrIter->value;
+
+        if (name == u"item") {
+            // Items simply have their type encoded in the type attribute.
+            auto typeIter = childParser.findAttribute(u"", u"type");
+            if (typeIter == endAttrIter || typeIter->value.empty()) {
+                mLogger.error(childParser.getLineNumber())
+                        << "<item> must have a 'type' attribute."
+                        << std::endl;
+                success = false;
+                continue;
+            }
+            name = typeIter->value;
+        }
+
+        if (name == u"id") {
+            success &= mTable->addResource(ResourceNameRef{ {}, ResourceType::kId, attributeName },
+                                           {}, mSource.line(childParser.getLineNumber()),
+                                           util::make_unique<Id>());
+        } else if (name == u"string") {
+            success &= parseString(&childParser,
+                                   ResourceNameRef{ {}, ResourceType::kString, attributeName });
+        } else if (name == u"color") {
+            success &= parseColor(&childParser,
+                                  ResourceNameRef{ {}, ResourceType::kColor, attributeName });
+        } else if (name == u"drawable") {
+            success &= parseColor(&childParser,
+                                  ResourceNameRef{ {}, ResourceType::kDrawable, attributeName });
+        } else if (name == u"bool") {
+            success &= parsePrimitive(&childParser,
+                                      ResourceNameRef{ {}, ResourceType::kBool, attributeName });
+        } else if (name == u"integer") {
+            success &= parsePrimitive(
+                    &childParser,
+                    ResourceNameRef{ {}, ResourceType::kInteger, attributeName });
+        } else if (name == u"dimen") {
+            success &= parsePrimitive(&childParser,
+                                      ResourceNameRef{ {}, ResourceType::kDimen, attributeName });
+        } else if (name == u"fraction") {
+//          success &= parsePrimitive(
+//                  &childParser,
+//                  ResourceNameRef{ {}, ResourceType::kFraction, attributeName });
+        } else if (name == u"style") {
+            success &= parseStyle(&childParser,
+                                  ResourceNameRef{ {}, ResourceType::kStyle, attributeName });
+        } else if (name == u"plurals") {
+            success &= parsePlural(&childParser,
+                                   ResourceNameRef{ {}, ResourceType::kPlurals, attributeName });
+        } else if (name == u"array") {
+            success &= parseArray(&childParser,
+                                  ResourceNameRef{ {}, ResourceType::kArray, attributeName },
+                                  android::ResTable_map::TYPE_ANY);
+        } else if (name == u"string-array") {
+            success &= parseArray(&childParser,
+                                  ResourceNameRef{ {}, ResourceType::kArray, attributeName },
+                                  android::ResTable_map::TYPE_STRING);
+        } else if (name == u"integer-array") {
+            success &= parseArray(&childParser,
+                                  ResourceNameRef{ {}, ResourceType::kArray, attributeName },
+                                  android::ResTable_map::TYPE_INTEGER);
+        } else if (name == u"public") {
+            success &= parsePublic(&childParser, attributeName);
+        } else if (name == u"declare-styleable") {
+            success &= parseDeclareStyleable(
+                    &childParser,
+                    ResourceNameRef{ {}, ResourceType::kStyleable, attributeName });
+        } else if (name == u"attr") {
+            success &= parseAttr(&childParser,
+                                 ResourceNameRef{ {}, ResourceType::kAttr, attributeName });
+        } else if (name == u"bag") {
+        } else if (name == u"public-padding") {
+        } else if (name == u"java-symbol") {
+        } else if (name == u"add-resource") {
+       }
+    }
+
+    if (parser->getEvent() == XmlPullParser::Event::kBadDocument) {
+        mLogger.error(parser->getLineNumber())
+                << parser->getLastError()
+                << std::endl;
+        return false;
+    }
+    return success;
+}
+
+
+
+enum {
+    kAllowRawString = true,
+    kNoRawString = false
+};
+
+/**
+ * Reads the entire XML subtree and attempts to parse it as some Item,
+ * with typeMask denoting which items it can be. If allowRawValue is
+ * true, a RawString is returned if the XML couldn't be parsed as
+ * an Item. If allowRawValue is false, nullptr is returned in this
+ * case.
+ */
+std::unique_ptr<Item> ResourceParser::parseXml(XmlPullParser* parser, uint32_t typeMask,
+                                               bool allowRawValue) {
+    const size_t beginXmlLine = parser->getLineNumber();
+
+    std::u16string rawValue;
+    StyleString styleString;
+    if (!flattenXmlSubtree(parser, &rawValue, &styleString)) {
+        return {};
+    }
+
+    StringPool& pool = mTable->getValueStringPool();
+
+    if (!styleString.spans.empty()) {
+        // This can only be a StyledString.
+        return util::make_unique<StyledString>(
+                pool.makeRef(styleString, StringPool::Context{ 1, mConfig }));
+    }
+
+    auto onCreateReference = [&](const ResourceName& name) {
+        mTable->addResource(name, {}, mSource.line(beginXmlLine), util::make_unique<Id>());
+    };
+
+    // Process the raw value.
+    std::unique_ptr<Item> processedItem = parseItemForAttribute(rawValue, typeMask,
+                                                                mTable->getPackage(),
+                                                                onCreateReference);
+    if (processedItem) {
+        return processedItem;
+    }
+
+    // Try making a regular string.
+    if (typeMask & android::ResTable_map::TYPE_STRING) {
+        // Use the trimmed, escaped string.
+        return util::make_unique<String>(
+                pool.makeRef(styleString.str, StringPool::Context{ 1, mConfig }));
+    }
+
+    // We can't parse this so return a RawString if we are allowed.
+    if (allowRawValue) {
+        return util::make_unique<RawString>(
+                pool.makeRef(rawValue, StringPool::Context{ 1, mConfig }));
+    }
+    return {};
+}
+
+bool ResourceParser::parseString(XmlPullParser* parser, const ResourceNameRef& resourceName) {
+    const SourceLine source = mSource.line(parser->getLineNumber());
+
+    // Mark the string as untranslateable if needed.
+    const auto endAttrIter = parser->endAttributes();
+    auto attrIter = parser->findAttribute(u"", u"untranslateable");
+    // bool untranslateable = attrIter != endAttrIter;
+    // TODO(adamlesinski): Do something with this (mark the string).
+
+    // Deal with the product.
+    attrIter = parser->findAttribute(u"", u"product");
+    if (attrIter != endAttrIter) {
+        if (attrIter->value != u"default" && attrIter->value != u"phone") {
+            // TODO(adamlesinski): Match products.
+            return true;
+        }
+    }
+
+    std::unique_ptr<Item> processedItem = parseXml(parser, android::ResTable_map::TYPE_STRING,
+                                                   kNoRawString);
+    if (!processedItem) {
+        mLogger.error(source.line)
+                << "not a valid string."
+                << std::endl;
+        return false;
+    }
+
+    return mTable->addResource(resourceName, mConfig, source, std::move(processedItem));
+}
+
+bool ResourceParser::parseColor(XmlPullParser* parser, const ResourceNameRef& resourceName) {
+    const SourceLine source = mSource.line(parser->getLineNumber());
+
+    std::unique_ptr<Item> item = parseXml(parser, android::ResTable_map::TYPE_COLOR, kNoRawString);
+    if (!item) {
+        mLogger.error(source.line) << "invalid color." << std::endl;
+        return false;
+    }
+    return mTable->addResource(resourceName, mConfig, source, std::move(item));
+}
+
+bool ResourceParser::parsePrimitive(XmlPullParser* parser, const ResourceNameRef& resourceName) {
+    const SourceLine source = mSource.line(parser->getLineNumber());
+
+    uint32_t typeMask = 0;
+    switch (resourceName.type) {
+        case ResourceType::kInteger:
+            typeMask |= android::ResTable_map::TYPE_INTEGER;
+            break;
+
+        case ResourceType::kDimen:
+            typeMask |= android::ResTable_map::TYPE_DIMENSION
+                     | android::ResTable_map::TYPE_FLOAT
+                     | android::ResTable_map::TYPE_FRACTION;
+            break;
+
+        case ResourceType::kBool:
+            typeMask |= android::ResTable_map::TYPE_BOOLEAN;
+            break;
+
+        default:
+            assert(false);
+            break;
+    }
+
+    std::unique_ptr<Item> item = parseXml(parser, typeMask, kNoRawString);
+    if (!item) {
+        mLogger.error(source.line)
+                << "invalid "
+                << resourceName.type
+                << "."
+                << std::endl;
+        return false;
+    }
+
+    return mTable->addResource(resourceName, mConfig, source, std::move(item));
+}
+
+bool ResourceParser::parsePublic(XmlPullParser* parser, const StringPiece16& name) {
+    const SourceLine source = mSource.line(parser->getLineNumber());
+
+    const auto endAttrIter = parser->endAttributes();
+    const auto typeAttrIter = parser->findAttribute(u"", u"type");
+    if (typeAttrIter == endAttrIter || typeAttrIter->value.empty()) {
+        mLogger.error(source.line)
+                << "<public> must have a 'type' attribute."
+                << std::endl;
+        return false;
+    }
+
+    const ResourceType* parsedType = parseResourceType(typeAttrIter->value);
+    if (!parsedType) {
+        mLogger.error(source.line)
+                << "invalid resource type '"
+                << typeAttrIter->value
+                << "' in <public>."
+                << std::endl;
+        return false;
+    }
+
+    ResourceNameRef resourceName { {}, *parsedType, name };
+    ResourceId resourceId;
+
+    const auto idAttrIter = parser->findAttribute(u"", u"id");
+    if (idAttrIter != endAttrIter && !idAttrIter->value.empty()) {
+        android::Res_value val;
+        bool result = android::ResTable::stringToInt(idAttrIter->value.data(),
+                                                     idAttrIter->value.size(), &val);
+        resourceId.id = val.data;
+        if (!result || !resourceId.isValid()) {
+            mLogger.error(source.line)
+                    << "invalid resource ID '"
+                    << idAttrIter->value
+                    << "' in <public>."
+                    << std::endl;
+            return false;
+        }
+    }
+
+    if (*parsedType == ResourceType::kId) {
+        // An ID marked as public is also the definition of an ID.
+        mTable->addResource(resourceName, {}, source, util::make_unique<Id>());
+    }
+
+    return mTable->markPublic(resourceName, resourceId, source);
+}
+
+static uint32_t parseFormatType(const StringPiece16& piece) {
+    if (piece == u"reference")      return android::ResTable_map::TYPE_REFERENCE;
+    else if (piece == u"string")    return android::ResTable_map::TYPE_STRING;
+    else if (piece == u"integer")   return android::ResTable_map::TYPE_INTEGER;
+    else if (piece == u"boolean")   return android::ResTable_map::TYPE_BOOLEAN;
+    else if (piece == u"color")     return android::ResTable_map::TYPE_COLOR;
+    else if (piece == u"float")     return android::ResTable_map::TYPE_FLOAT;
+    else if (piece == u"dimension") return android::ResTable_map::TYPE_DIMENSION;
+    else if (piece == u"fraction")  return android::ResTable_map::TYPE_FRACTION;
+    else if (piece == u"enum")      return android::ResTable_map::TYPE_ENUM;
+    else if (piece == u"flags")     return android::ResTable_map::TYPE_FLAGS;
+    return 0;
+}
+
+static uint32_t parseFormatAttribute(const StringPiece16& str) {
+    uint32_t mask = 0;
+    for (StringPiece16 part : util::tokenize(str, u'|')) {
+        StringPiece16 trimmedPart = util::trimWhitespace(part);
+        uint32_t type = parseFormatType(trimmedPart);
+        if (type == 0) {
+            return 0;
+        }
+        mask |= type;
+    }
+    return mask;
+}
+
+bool ResourceParser::parseAttr(XmlPullParser* parser, const ResourceNameRef& resourceName) {
+    const SourceLine source = mSource.line(parser->getLineNumber());
+    std::unique_ptr<Attribute> attr = parseAttrImpl(parser, resourceName, false);
+    if (!attr) {
+        return false;
+    }
+    return mTable->addResource(resourceName, mConfig, source, std::move(attr));
+}
+
+std::unique_ptr<Attribute> ResourceParser::parseAttrImpl(XmlPullParser* parser,
+                                                         const ResourceNameRef& resourceName,
+                                                         bool weak) {
+    uint32_t typeMask = 0;
+
+    const auto endAttrIter = parser->endAttributes();
+    const auto formatAttrIter = parser->findAttribute(u"", u"format");
+    if (formatAttrIter != endAttrIter) {
+        typeMask = parseFormatAttribute(formatAttrIter->value);
+        if (typeMask == 0) {
+            mLogger.error(parser->getLineNumber())
+                    << "invalid attribute format '"
+                    << formatAttrIter->value
+                    << "'."
+                    << std::endl;
+            return {};
+        }
+    }
+
+    std::vector<Attribute::Symbol> items;
+
+    bool error = false;
+    while (XmlPullParser::isGoodEvent(parser->next())) {
+        if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
+            continue;
+        }
+
+        ScopedXmlPullParser childParser(parser);
+
+        const std::u16string& name = childParser.getElementName();
+        if (!childParser.getElementNamespace().empty()
+                || (name != u"flag" && name != u"enum")) {
+            mLogger.error(childParser.getLineNumber())
+                    << "unexpected tag <"
+                    << name
+                    << "> in <attr>."
+                    << std::endl;
+            error = true;
+            continue;
+        }
+
+        if (name == u"enum") {
+            if (typeMask & android::ResTable_map::TYPE_FLAGS) {
+                mLogger.error(childParser.getLineNumber())
+                        << "can not define an <enum>; already defined a <flag>."
+                        << std::endl;
+                error = true;
+                continue;
+            }
+            typeMask |= android::ResTable_map::TYPE_ENUM;
+        } else if (name == u"flag") {
+            if (typeMask & android::ResTable_map::TYPE_ENUM) {
+                mLogger.error(childParser.getLineNumber())
+                        << "can not define a <flag>; already defined an <enum>."
+                        << std::endl;
+                error = true;
+                continue;
+            }
+            typeMask |= android::ResTable_map::TYPE_FLAGS;
+        }
+
+        Attribute::Symbol item;
+        if (parseEnumOrFlagItem(&childParser, name, &item)) {
+            if (!mTable->addResource(item.symbol.name, mConfig,
+                                     mSource.line(childParser.getLineNumber()),
+                                     util::make_unique<Id>())) {
+                error = true;
+            } else {
+                items.push_back(std::move(item));
+            }
+        } else {
+            error = true;
+        }
+    }
+
+    if (error) {
+        return {};
+    }
+
+    std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(weak);
+    attr->symbols.swap(items);
+    attr->typeMask = typeMask ? typeMask : uint32_t(android::ResTable_map::TYPE_ANY);
+    return attr;
+}
+
+bool ResourceParser::parseEnumOrFlagItem(XmlPullParser* parser, const StringPiece16& tag,
+                                         Attribute::Symbol* outSymbol) {
+    const auto attrIterEnd = parser->endAttributes();
+    const auto nameAttrIter = parser->findAttribute(u"", u"name");
+    if (nameAttrIter == attrIterEnd || nameAttrIter->value.empty()) {
+        mLogger.error(parser->getLineNumber())
+                << "no attribute 'name' found for tag <" << tag << ">."
+                << std::endl;
+        return false;
+    }
+
+    const auto valueAttrIter = parser->findAttribute(u"", u"value");
+    if (valueAttrIter == attrIterEnd || valueAttrIter->value.empty()) {
+        mLogger.error(parser->getLineNumber())
+                << "no attribute 'value' found for tag <" << tag << ">."
+                << std::endl;
+        return false;
+    }
+
+    android::Res_value val;
+    if (!android::ResTable::stringToInt(valueAttrIter->value.data(),
+                                        valueAttrIter->value.size(), &val)) {
+        mLogger.error(parser->getLineNumber())
+                << "invalid value '"
+                << valueAttrIter->value
+                << "' for <" << tag << ">; must be an integer."
+                << std::endl;
+        return false;
+    }
+
+    outSymbol->symbol.name = ResourceName {
+            mTable->getPackage(), ResourceType::kId, nameAttrIter->value };
+    outSymbol->value = val.data;
+    return true;
+}
+
+static bool parseXmlAttributeName(StringPiece16 str, ResourceNameRef* outRef) {
+    str = util::trimWhitespace(str);
+    const char16_t* const start = str.data();
+    const char16_t* const end = start + str.size();
+    const char16_t* p = start;
+
+    StringPiece16 package;
+    StringPiece16 name;
+    while (p != end) {
+        if (*p == u':') {
+            package = StringPiece16(start, p - start);
+            name = StringPiece16(p + 1, end - (p + 1));
+            break;
+        }
+        p++;
+    }
+
+    outRef->package = package;
+    outRef->type = ResourceType::kAttr;
+    if (name.size() == 0) {
+        outRef->entry = str;
+    } else {
+        outRef->entry = name;
+    }
+    return true;
+}
+
+bool ResourceParser::parseUntypedItem(XmlPullParser* parser, Style& style) {
+    const auto endAttrIter = parser->endAttributes();
+    const auto nameAttrIter = parser->findAttribute(u"", u"name");
+    if (nameAttrIter == endAttrIter || nameAttrIter->value.empty()) {
+        mLogger.error(parser->getLineNumber())
+                << "<item> must have a 'name' attribute."
+                << std::endl;
+        return false;
+    }
+
+    ResourceNameRef keyRef;
+    if (!parseXmlAttributeName(nameAttrIter->value, &keyRef)) {
+        mLogger.error(parser->getLineNumber())
+                << "invalid attribute name '"
+                << nameAttrIter->value
+                << "'."
+                << std::endl;
+        return false;
+    }
+
+    if (keyRef.package.empty()) {
+        keyRef.package = mTable->getPackage();
+    }
+
+    // Create a copy instead of a reference because we
+    // are about to invalidate keyRef when advancing the parser.
+    ResourceName key = keyRef.toResourceName();
+
+    std::unique_ptr<Item> value = parseXml(parser, 0, kAllowRawString);
+    if (!value) {
+        return false;
+    }
+
+    style.entries.push_back(Style::Entry{ Reference(key), std::move(value) });
+    return true;
+}
+
+bool ResourceParser::parseStyle(XmlPullParser* parser, const ResourceNameRef& resourceName) {
+    const SourceLine source = mSource.line(parser->getLineNumber());
+    std::unique_ptr<Style> style = util::make_unique<Style>();
+
+    const auto endAttrIter = parser->endAttributes();
+    const auto parentAttrIter = parser->findAttribute(u"", u"parent");
+    if (parentAttrIter != endAttrIter) {
+        ResourceNameRef ref;
+        bool create = false;
+        bool privateRef = false;
+        if (tryParseReference(parentAttrIter->value, &ref, &create, &privateRef)) {
+            if (create) {
+                mLogger.error(source.line)
+                        << "parent of style can not be an ID."
+                        << std::endl;
+                return false;
+            }
+            style->parent.name = ref.toResourceName();
+            style->parent.privateReference = privateRef;
+        } else if (tryParseAttributeReference(parentAttrIter->value, &ref)) {
+            style->parent.name = ref.toResourceName();
+        } else {
+            // TODO(adamlesinski): Try parsing without the '@' or '?'.
+            // Also, make sure to check the entry name for weird symbols.
+            style->parent.name = ResourceName {
+                {}, ResourceType::kStyle, parentAttrIter->value
+            };
+        }
+
+        if (style->parent.name.package.empty()) {
+            style->parent.name.package = mTable->getPackage();
+        }
+    }
+
+    bool success = true;
+    while (XmlPullParser::isGoodEvent(parser->next())) {
+        if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
+            continue;
+        }
+
+        ScopedXmlPullParser childParser(parser);
+        const std::u16string& name = childParser.getElementName();
+        if (name == u"item") {
+            success &= parseUntypedItem(&childParser, *style);
+        } else {
+            mLogger.error(childParser.getLineNumber())
+                    << "unexpected tag <"
+                    << name
+                    << "> in <style> resource."
+                    << std::endl;
+            success = false;
+        }
+    }
+
+    if (!success) {
+        return false;
+    }
+
+    return mTable->addResource(resourceName, mConfig, source, std::move(style));
+}
+
+bool ResourceParser::parseArray(XmlPullParser* parser, const ResourceNameRef& resourceName,
+                                uint32_t typeMask) {
+    const SourceLine source = mSource.line(parser->getLineNumber());
+    std::unique_ptr<Array> array = util::make_unique<Array>();
+
+    bool error = false;
+    while (XmlPullParser::isGoodEvent(parser->next())) {
+        if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
+            continue;
+        }
+
+        ScopedXmlPullParser childParser(parser);
+
+        if (childParser.getElementName() != u"item") {
+            mLogger.error(childParser.getLineNumber())
+                    << "unexpected tag <"
+                    << childParser.getElementName()
+                    << "> in <array> resource."
+                    << std::endl;
+            error = true;
+            continue;
+        }
+
+        std::unique_ptr<Item> item = parseXml(&childParser, typeMask, kNoRawString);
+        if (!item) {
+            error = true;
+            continue;
+        }
+        array->items.emplace_back(std::move(item));
+    }
+
+    if (error) {
+        return false;
+    }
+
+    return mTable->addResource(resourceName, mConfig, source, std::move(array));
+}
+
+bool ResourceParser::parsePlural(XmlPullParser* parser, const ResourceNameRef& resourceName) {
+    const SourceLine source = mSource.line(parser->getLineNumber());
+    std::unique_ptr<Plural> plural = util::make_unique<Plural>();
+
+    bool success = true;
+    while (XmlPullParser::isGoodEvent(parser->next())) {
+        if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
+            continue;
+        }
+
+        ScopedXmlPullParser childParser(parser);
+
+        if (!childParser.getElementNamespace().empty() ||
+                childParser.getElementName() != u"item") {
+            success = false;
+            continue;
+        }
+
+        const auto endAttrIter = childParser.endAttributes();
+        auto attrIter = childParser.findAttribute(u"", u"quantity");
+        if (attrIter == endAttrIter || attrIter->value.empty()) {
+            mLogger.error(childParser.getLineNumber())
+                    << "<item> in <plurals> requires attribute 'quantity'."
+                    << std::endl;
+            success = false;
+            continue;
+        }
+
+        StringPiece16 trimmedQuantity = util::trimWhitespace(attrIter->value);
+        size_t index = 0;
+        if (trimmedQuantity == u"zero") {
+            index = Plural::Zero;
+        } else if (trimmedQuantity == u"one") {
+            index = Plural::One;
+        } else if (trimmedQuantity == u"two") {
+            index = Plural::Two;
+        } else if (trimmedQuantity == u"few") {
+            index = Plural::Few;
+        } else if (trimmedQuantity == u"many") {
+            index = Plural::Many;
+        } else if (trimmedQuantity == u"other") {
+            index = Plural::Other;
+        } else {
+            mLogger.error(childParser.getLineNumber())
+                    << "<item> in <plural> has invalid value '"
+                    << trimmedQuantity
+                    << "' for attribute 'quantity'."
+                    << std::endl;
+            success = false;
+            continue;
+        }
+
+        if (plural->values[index]) {
+            mLogger.error(childParser.getLineNumber())
+                    << "duplicate quantity '"
+                    << trimmedQuantity
+                    << "'."
+                    << std::endl;
+            success = false;
+            continue;
+        }
+
+        if (!(plural->values[index] = parseXml(&childParser, android::ResTable_map::TYPE_STRING,
+                                               kNoRawString))) {
+            success = false;
+        }
+    }
+
+    if (!success) {
+        return false;
+    }
+
+    return mTable->addResource(resourceName, mConfig, source, std::move(plural));
+}
+
+bool ResourceParser::parseDeclareStyleable(XmlPullParser* parser,
+                                           const ResourceNameRef& resourceName) {
+    const SourceLine source = mSource.line(parser->getLineNumber());
+    std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
+
+    bool success = true;
+    while (XmlPullParser::isGoodEvent(parser->next())) {
+        if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
+            continue;
+        }
+
+        ScopedXmlPullParser childParser(parser);
+
+        const std::u16string& elementName = childParser.getElementName();
+        if (elementName == u"attr") {
+            const auto endAttrIter = childParser.endAttributes();
+            auto attrIter = childParser.findAttribute(u"", u"name");
+            if (attrIter == endAttrIter || attrIter->value.empty()) {
+                mLogger.error(childParser.getLineNumber())
+                        << "<attr> tag must have a 'name' attribute."
+                        << std::endl;
+                success = false;
+                continue;
+            }
+
+            // Copy because our iterator will be invalidated.
+            std::u16string attrName = attrIter->value;
+
+            ResourceNameRef attrResourceName = {
+                    mTable->getPackage(),
+                    ResourceType::kAttr,
+                    attrName
+            };
+
+            std::unique_ptr<Attribute> attr = parseAttrImpl(&childParser, attrResourceName, true);
+            if (!attr) {
+                success = false;
+                continue;
+            }
+
+            styleable->entries.emplace_back(attrResourceName);
+
+            success &= mTable->addResource(attrResourceName, mConfig,
+                                           mSource.line(childParser.getLineNumber()),
+                                           std::move(attr));
+
+        } else if (elementName != u"eat-comment" && elementName != u"skip") {
+            mLogger.error(childParser.getLineNumber())
+                    << "<"
+                    << elementName
+                    << "> is not allowed inside <declare-styleable>."
+                    << std::endl;
+            success = false;
+        }
+    }
+
+    if (!success) {
+        return false;
+    }
+
+    return mTable->addResource(resourceName, mConfig, source, std::move(styleable));
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
new file mode 100644
index 0000000..96bba4f
--- /dev/null
+++ b/tools/aapt2/ResourceParser.h
@@ -0,0 +1,188 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_RESOURCE_PARSER_H
+#define AAPT_RESOURCE_PARSER_H
+
+#include "ConfigDescription.h"
+#include "Logger.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "StringPiece.h"
+#include "StringPool.h"
+#include "XmlPullParser.h"
+
+#include <istream>
+#include <memory>
+
+namespace aapt {
+
+/*
+ * Parses an XML file for resources and adds them to a ResourceTable.
+ */
+class ResourceParser {
+public:
+    /*
+     * Extracts the package, type, and name from a string of the format:
+     *
+     *      [package:]type/name
+     *
+     * where the package can be empty. Validation must be performed on each
+     * individual extracted piece to verify that the pieces are valid.
+     */
+    static void extractResourceName(const StringPiece16& str, StringPiece16* outPackage,
+                                    StringPiece16* outType, StringPiece16* outEntry);
+
+    /*
+     * Returns true if the string was parsed as a reference (@[+][package:]type/name), with
+     * `outReference` set to the parsed reference.
+     *
+     * If '+' was present in the reference, `outCreate` is set to true.
+     * If '*' was present in the reference, `outPrivate` is set to true.
+     */
+    static bool tryParseReference(const StringPiece16& str, ResourceNameRef* outReference,
+                                  bool* outCreate, bool* outPrivate);
+
+    /*
+     * Returns true if the string was parsed as an attribute reference (?[package:]type/name),
+     * with `outReference` set to the parsed reference.
+     */
+    static bool tryParseAttributeReference(const StringPiece16& str,
+                                           ResourceNameRef* outReference);
+
+    /*
+     * Returns a Reference object if the string was parsed as a resource or attribute reference,
+     * ( @[+][package:]type/name | ?[package:]type/name )
+     * assigning defaultPackage if the package was not present in the string, and setting
+     * outCreate to true if the '+' was present in the string.
+     */
+    static std::unique_ptr<Reference> tryParseReference(const StringPiece16& str,
+                                                        const StringPiece16& defaultPackage,
+                                                        bool* outCreate);
+
+    /*
+     * Returns a BinaryPrimitve object representing @null or @empty if the string was parsed
+     * as one.
+     */
+    static std::unique_ptr<BinaryPrimitive> tryParseNullOrEmpty(const StringPiece16& str);
+
+    /*
+     * Returns a BinaryPrimitve object representing a color if the string was parsed
+     * as one.
+     */
+    static std::unique_ptr<BinaryPrimitive> tryParseColor(const StringPiece16& str);
+
+    /*
+     * Returns a BinaryPrimitve object representing a boolean if the string was parsed
+     * as one.
+     */
+    static std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece16& str);
+
+    /*
+     * Returns a BinaryPrimitve object representing an integer if the string was parsed
+     * as one.
+     */
+    static std::unique_ptr<BinaryPrimitive> tryParseInt(const StringPiece16& str);
+
+    /*
+     * Returns a BinaryPrimitve object representing a floating point number
+     * (float, dimension, etc) if the string was parsed as one.
+     */
+    static std::unique_ptr<BinaryPrimitive> tryParseFloat(const StringPiece16& str);
+
+    /*
+     * Returns a BinaryPrimitve object representing an enum symbol if the string was parsed
+     * as one.
+     */
+    static std::unique_ptr<BinaryPrimitive> tryParseEnumSymbol(const Attribute& enumAttr,
+                                                               const StringPiece16& str);
+
+    /*
+     * Returns a BinaryPrimitve object representing a flag symbol if the string was parsed
+     * as one.
+     */
+    static std::unique_ptr<BinaryPrimitive> tryParseFlagSymbol(const Attribute& enumAttr,
+                                                               const StringPiece16& str);
+
+    /*
+     * Try to convert a string to an Item for the given attribute. The attribute will
+     * restrict what values the string can be converted to.
+     * The defaultPackage is used when the string is a reference with no defined package.
+     * The callback function onCreateReference is called when the parsed item is a
+     * reference to an ID that must be created (@+id/foo).
+     */
+    static std::unique_ptr<Item> parseItemForAttribute(
+            const StringPiece16& value, const Attribute& attr, const StringPiece16& defaultPackage,
+            std::function<void(const ResourceName&)> onCreateReference = {});
+
+    static std::unique_ptr<Item> parseItemForAttribute(
+            const StringPiece16& value, uint32_t typeMask, const StringPiece16& defaultPackage,
+            std::function<void(const ResourceName&)> onCreateReference = {});
+
+    static uint32_t androidTypeToAttributeTypeMask(uint16_t type);
+
+    ResourceParser(const std::shared_ptr<ResourceTable>& table, const Source& source,
+                   const ConfigDescription& config, const std::shared_ptr<XmlPullParser>& parser);
+
+    ResourceParser(const ResourceParser&) = delete; // No copy.
+
+    bool parse();
+
+private:
+    /*
+     * Parses the XML subtree as a StyleString (flattened XML representation for strings
+     * with formatting). If successful, `outStyleString`
+     * contains the escaped and whitespace trimmed text, while `outRawString`
+     * contains the unescaped text. Returns true on success.
+     */
+    bool flattenXmlSubtree(XmlPullParser* parser, std::u16string* outRawString,\
+                           StyleString* outStyleString);
+
+    /*
+     * Parses the XML subtree and converts it to an Item. The type of Item that can be
+     * parsed is denoted by the `typeMask`. If `allowRawValue` is true and the subtree
+     * can not be parsed as a regular Item, then a RawString is returned. Otherwise
+     * this returns nullptr.
+     */
+    std::unique_ptr<Item> parseXml(XmlPullParser* parser, uint32_t typeMask, bool allowRawValue);
+
+    bool parseResources(XmlPullParser* parser);
+    bool parseString(XmlPullParser* parser, const ResourceNameRef& resourceName);
+    bool parseColor(XmlPullParser* parser, const ResourceNameRef& resourceName);
+    bool parsePrimitive(XmlPullParser* parser, const ResourceNameRef& resourceName);
+    bool parsePublic(XmlPullParser* parser, const StringPiece16& name);
+    bool parseAttr(XmlPullParser* parser, const ResourceNameRef& resourceName);
+    std::unique_ptr<Attribute> parseAttrImpl(XmlPullParser* parser,
+                                             const ResourceNameRef& resourceName,
+                                             bool weak);
+    bool parseEnumOrFlagItem(XmlPullParser* parser, const StringPiece16& tag,
+                             Attribute::Symbol* outSymbol);
+    bool parseStyle(XmlPullParser* parser, const ResourceNameRef& resourceName);
+    bool parseUntypedItem(XmlPullParser* parser, Style& style);
+    bool parseDeclareStyleable(XmlPullParser* parser, const ResourceNameRef& resourceName);
+    bool parseArray(XmlPullParser* parser, const ResourceNameRef& resourceName, uint32_t typeMask);
+    bool parsePlural(XmlPullParser* parser, const ResourceNameRef& resourceName);
+
+    std::shared_ptr<ResourceTable> mTable;
+    Source mSource;
+    ConfigDescription mConfig;
+    SourceLogger mLogger;
+    std::shared_ptr<XmlPullParser> mParser;
+};
+
+} // namespace aapt
+
+#endif // AAPT_RESOURCE_PARSER_H
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
new file mode 100644
index 0000000..5afbaf4
--- /dev/null
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -0,0 +1,399 @@
+/*
+ * 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.
+ */
+
+#include "ResourceParser.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "SourceXmlPullParser.h"
+
+#include <gtest/gtest.h>
+#include <sstream>
+#include <string>
+
+namespace aapt {
+
+constexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+
+TEST(ResourceParserReferenceTest, ParseReferenceWithNoPackage) {
+    ResourceNameRef expected = { {}, ResourceType::kColor, u"foo" };
+    ResourceNameRef actual;
+    bool create = false;
+    bool privateRef = false;
+    EXPECT_TRUE(ResourceParser::tryParseReference(u"@color/foo", &actual, &create, &privateRef));
+    EXPECT_EQ(expected, actual);
+    EXPECT_FALSE(create);
+    EXPECT_FALSE(privateRef);
+}
+
+TEST(ResourceParserReferenceTest, ParseReferenceWithPackage) {
+    ResourceNameRef expected = { u"android", ResourceType::kColor, u"foo" };
+    ResourceNameRef actual;
+    bool create = false;
+    bool privateRef = false;
+    EXPECT_TRUE(ResourceParser::tryParseReference(u"@android:color/foo", &actual, &create,
+                                                  &privateRef));
+    EXPECT_EQ(expected, actual);
+    EXPECT_FALSE(create);
+    EXPECT_FALSE(privateRef);
+}
+
+TEST(ResourceParserReferenceTest, ParseReferenceWithSurroundingWhitespace) {
+    ResourceNameRef expected = { u"android", ResourceType::kColor, u"foo" };
+    ResourceNameRef actual;
+    bool create = false;
+    bool privateRef = false;
+    EXPECT_TRUE(ResourceParser::tryParseReference(u"\t @android:color/foo\n \n\t", &actual,
+                                                  &create, &privateRef));
+    EXPECT_EQ(expected, actual);
+    EXPECT_FALSE(create);
+    EXPECT_FALSE(privateRef);
+}
+
+TEST(ResourceParserReferenceTest, ParseAutoCreateIdReference) {
+    ResourceNameRef expected = { u"android", ResourceType::kId, u"foo" };
+    ResourceNameRef actual;
+    bool create = false;
+    bool privateRef = false;
+    EXPECT_TRUE(ResourceParser::tryParseReference(u"@+android:id/foo", &actual, &create,
+                                                  &privateRef));
+    EXPECT_EQ(expected, actual);
+    EXPECT_TRUE(create);
+    EXPECT_FALSE(privateRef);
+}
+
+TEST(ResourceParserReferenceTest, ParsePrivateReference) {
+    ResourceNameRef expected = { u"android", ResourceType::kId, u"foo" };
+    ResourceNameRef actual;
+    bool create = false;
+    bool privateRef = false;
+    EXPECT_TRUE(ResourceParser::tryParseReference(u"@*android:id/foo", &actual, &create,
+                                                  &privateRef));
+    EXPECT_EQ(expected, actual);
+    EXPECT_FALSE(create);
+    EXPECT_TRUE(privateRef);
+}
+
+TEST(ResourceParserReferenceTest, FailToParseAutoCreateNonIdReference) {
+    bool create = false;
+    bool privateRef = false;
+    ResourceNameRef actual;
+    EXPECT_FALSE(ResourceParser::tryParseReference(u"@+android:color/foo", &actual, &create,
+                                                   &privateRef));
+}
+
+struct ResourceParserTest : public ::testing::Test {
+    virtual void SetUp() override {
+        mTable = std::make_shared<ResourceTable>();
+        mTable->setPackage(u"android");
+    }
+
+    ::testing::AssertionResult testParse(std::istream& in) {
+        std::stringstream input(kXmlPreamble);
+        input << "<resources>" << std::endl
+              << in.rdbuf() << std::endl
+              << "</resources>" << std::endl;
+        ResourceParser parser(mTable, Source{ "test" }, {},
+                              std::make_shared<SourceXmlPullParser>(input));
+        if (parser.parse()) {
+            return ::testing::AssertionSuccess();
+        }
+        return ::testing::AssertionFailure();
+    }
+
+    template <typename T>
+    const T* findResource(const ResourceNameRef& name, const ConfigDescription& config) {
+        using std::begin;
+        using std::end;
+
+        const ResourceTableType* type;
+        const ResourceEntry* entry;
+        std::tie(type, entry) = mTable->findResource(name);
+        if (!type || !entry) {
+            return nullptr;
+        }
+
+        for (const auto& configValue : entry->values) {
+            if (configValue.config == config) {
+                return dynamic_cast<const T*>(configValue.value.get());
+            }
+        }
+        return nullptr;
+    }
+
+    template <typename T>
+    const T* findResource(const ResourceNameRef& name) {
+        return findResource<T>(name, {});
+    }
+
+    std::shared_ptr<ResourceTable> mTable;
+};
+
+TEST_F(ResourceParserTest, FailToParseWithNoRootResourcesElement) {
+    std::stringstream input(kXmlPreamble);
+    input << "<attr name=\"foo\"/>" << std::endl;
+    ResourceParser parser(mTable, {}, {}, std::make_shared<SourceXmlPullParser>(input));
+    ASSERT_FALSE(parser.parse());
+}
+
+TEST_F(ResourceParserTest, ParseQuotedString) {
+    std::stringstream input("<string name=\"foo\">   \"  hey there \" </string>");
+    ASSERT_TRUE(testParse(input));
+
+    const String* str = findResource<String>(ResourceName{
+            u"android", ResourceType::kString, u"foo"});
+    ASSERT_NE(nullptr, str);
+    EXPECT_EQ(std::u16string(u"  hey there "), *str->value);
+}
+
+TEST_F(ResourceParserTest, ParseEscapedString) {
+    std::stringstream input("<string name=\"foo\">\\?123</string>");
+    ASSERT_TRUE(testParse(input));
+
+    const String* str = findResource<String>(ResourceName{
+            u"android", ResourceType::kString, u"foo" });
+    ASSERT_NE(nullptr, str);
+    EXPECT_EQ(std::u16string(u"?123"), *str->value);
+}
+
+TEST_F(ResourceParserTest, ParseAttr) {
+    std::stringstream input;
+    input << "<attr name=\"foo\" format=\"string\"/>" << std::endl
+          << "<attr name=\"bar\"/>" << std::endl;
+    ASSERT_TRUE(testParse(input));
+
+    const Attribute* attr = findResource<Attribute>(ResourceName{
+            u"android", ResourceType::kAttr, u"foo"});
+    EXPECT_NE(nullptr, attr);
+    EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->typeMask);
+
+    attr = findResource<Attribute>(ResourceName{
+            u"android", ResourceType::kAttr, u"bar"});
+    EXPECT_NE(nullptr, attr);
+    EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_ANY), attr->typeMask);
+}
+
+TEST_F(ResourceParserTest, ParseUseAndDeclOfAttr) {
+    std::stringstream input;
+    input << "<declare-styleable name=\"Styleable\">" << std::endl
+          << "  <attr name=\"foo\" />" << std::endl
+          << "</declare-styleable>" << std::endl
+          << "<attr name=\"foo\" format=\"string\"/>" << std::endl;
+    ASSERT_TRUE(testParse(input));
+
+    const Attribute* attr = findResource<Attribute>(ResourceName{
+            u"android", ResourceType::kAttr, u"foo"});
+    ASSERT_NE(nullptr, attr);
+    EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->typeMask);
+}
+
+TEST_F(ResourceParserTest, ParseDoubleUseOfAttr) {
+    std::stringstream input;
+    input << "<declare-styleable name=\"Theme\">" << std::endl
+          << "  <attr name=\"foo\" />" << std::endl
+          << "</declare-styleable>" << std::endl
+          << "<declare-styleable name=\"Window\">" << std::endl
+          << "  <attr name=\"foo\" format=\"boolean\"/>" << std::endl
+          << "</declare-styleable>" << std::endl;
+
+    ASSERT_TRUE(testParse(input));
+
+    const Attribute* attr = findResource<Attribute>(ResourceName{
+            u"android", ResourceType::kAttr, u"foo"});
+    ASSERT_NE(nullptr, attr);
+    EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_BOOLEAN), attr->typeMask);
+}
+
+TEST_F(ResourceParserTest, ParseEnumAttr) {
+    std::stringstream input;
+    input << "<attr name=\"foo\">" << std::endl
+          << "  <enum name=\"bar\" value=\"0\"/>" << std::endl
+          << "  <enum name=\"bat\" value=\"1\"/>" << std::endl
+          << "  <enum name=\"baz\" value=\"2\"/>" << std::endl
+          << "</attr>" << std::endl;
+    ASSERT_TRUE(testParse(input));
+
+    const Attribute* enumAttr = findResource<Attribute>(ResourceName{
+            u"android", ResourceType::kAttr, u"foo"});
+    ASSERT_NE(enumAttr, nullptr);
+    EXPECT_EQ(enumAttr->typeMask, android::ResTable_map::TYPE_ENUM);
+    ASSERT_EQ(enumAttr->symbols.size(), 3u);
+
+    EXPECT_EQ(enumAttr->symbols[0].symbol.name.entry, u"bar");
+    EXPECT_EQ(enumAttr->symbols[0].value, 0u);
+
+    EXPECT_EQ(enumAttr->symbols[1].symbol.name.entry, u"bat");
+    EXPECT_EQ(enumAttr->symbols[1].value, 1u);
+
+    EXPECT_EQ(enumAttr->symbols[2].symbol.name.entry, u"baz");
+    EXPECT_EQ(enumAttr->symbols[2].value, 2u);
+}
+
+TEST_F(ResourceParserTest, ParseFlagAttr) {
+    std::stringstream input;
+    input << "<attr name=\"foo\">" << std::endl
+          << "  <flag name=\"bar\" value=\"0\"/>" << std::endl
+          << "  <flag name=\"bat\" value=\"1\"/>" << std::endl
+          << "  <flag name=\"baz\" value=\"2\"/>" << std::endl
+          << "</attr>" << std::endl;
+    ASSERT_TRUE(testParse(input));
+
+    const Attribute* flagAttr = findResource<Attribute>(ResourceName{
+            u"android", ResourceType::kAttr, u"foo"});
+    ASSERT_NE(flagAttr, nullptr);
+    EXPECT_EQ(flagAttr->typeMask, android::ResTable_map::TYPE_FLAGS);
+    ASSERT_EQ(flagAttr->symbols.size(), 3u);
+
+    EXPECT_EQ(flagAttr->symbols[0].symbol.name.entry, u"bar");
+    EXPECT_EQ(flagAttr->symbols[0].value, 0u);
+
+    EXPECT_EQ(flagAttr->symbols[1].symbol.name.entry, u"bat");
+    EXPECT_EQ(flagAttr->symbols[1].value, 1u);
+
+    EXPECT_EQ(flagAttr->symbols[2].symbol.name.entry, u"baz");
+    EXPECT_EQ(flagAttr->symbols[2].value, 2u);
+
+    std::unique_ptr<BinaryPrimitive> flagValue =
+            ResourceParser::tryParseFlagSymbol(*flagAttr, u"baz|bat");
+    ASSERT_NE(flagValue, nullptr);
+    EXPECT_EQ(flagValue->value.data, 1u | 2u);
+}
+
+TEST_F(ResourceParserTest, FailToParseEnumAttrWithNonUniqueKeys) {
+    std::stringstream input;
+    input << "<attr name=\"foo\">" << std::endl
+          << "  <enum name=\"bar\" value=\"0\"/>" << std::endl
+          << "  <enum name=\"bat\" value=\"1\"/>" << std::endl
+          << "  <enum name=\"bat\" value=\"2\"/>" << std::endl
+          << "</attr>" << std::endl;
+    ASSERT_FALSE(testParse(input));
+}
+
+TEST_F(ResourceParserTest, ParseStyle) {
+    std::stringstream input;
+    input << "<style name=\"foo\" parent=\"fu\">" << std::endl
+          << "  <item name=\"bar\">#ffffffff</item>" << std::endl
+          << "  <item name=\"bat\">@string/hey</item>" << std::endl
+          << "  <item name=\"baz\"><b>hey</b></item>" << std::endl
+          << "</style>" << std::endl;
+    ASSERT_TRUE(testParse(input));
+
+    const Style* style = findResource<Style>(ResourceName{
+            u"android", ResourceType::kStyle, u"foo"});
+    ASSERT_NE(style, nullptr);
+    EXPECT_EQ(ResourceNameRef(u"android", ResourceType::kStyle, u"fu"), style->parent.name);
+    ASSERT_EQ(style->entries.size(), 3u);
+
+    EXPECT_EQ(style->entries[0].key.name,
+              (ResourceName{ u"android", ResourceType::kAttr, u"bar" }));
+    EXPECT_EQ(style->entries[1].key.name,
+              (ResourceName{ u"android", ResourceType::kAttr, u"bat" }));
+    EXPECT_EQ(style->entries[2].key.name,
+              (ResourceName{ u"android", ResourceType::kAttr, u"baz" }));
+}
+
+TEST_F(ResourceParserTest, ParseAutoGeneratedIdReference) {
+    std::stringstream input;
+    input << "<string name=\"foo\">@+id/bar</string>" << std::endl;
+    ASSERT_TRUE(testParse(input));
+
+    const Id* id = findResource<Id>(ResourceName{ u"android", ResourceType::kId, u"bar"});
+    ASSERT_NE(id, nullptr);
+}
+
+TEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) {
+    std::stringstream input;
+    input << "<declare-styleable name=\"foo\">" << std::endl
+          << "  <attr name=\"bar\" />" << std::endl
+          << "  <attr name=\"bat\" format=\"string|reference\"/>" << std::endl
+          << "</declare-styleable>" << std::endl;
+    ASSERT_TRUE(testParse(input));
+
+    const Attribute* attr = findResource<Attribute>(ResourceName{
+            u"android", ResourceType::kAttr, u"bar"});
+    ASSERT_NE(attr, nullptr);
+    EXPECT_TRUE(attr->isWeak());
+
+    attr = findResource<Attribute>(ResourceName{ u"android", ResourceType::kAttr, u"bat"});
+    ASSERT_NE(attr, nullptr);
+    EXPECT_TRUE(attr->isWeak());
+
+    const Styleable* styleable = findResource<Styleable>(ResourceName{
+            u"android", ResourceType::kStyleable, u"foo" });
+    ASSERT_NE(styleable, nullptr);
+    ASSERT_EQ(2u, styleable->entries.size());
+
+    EXPECT_EQ((ResourceName{u"android", ResourceType::kAttr, u"bar"}), styleable->entries[0].name);
+    EXPECT_EQ((ResourceName{u"android", ResourceType::kAttr, u"bat"}), styleable->entries[1].name);
+}
+
+TEST_F(ResourceParserTest, ParseArray) {
+    std::stringstream input;
+    input << "<array name=\"foo\">" << std::endl
+          << "  <item>@string/ref</item>" << std::endl
+          << "  <item>hey</item>" << std::endl
+          << "  <item>23</item>" << std::endl
+          << "</array>" << std::endl;
+    ASSERT_TRUE(testParse(input));
+
+    const Array* array = findResource<Array>(ResourceName{
+            u"android", ResourceType::kArray, u"foo" });
+    ASSERT_NE(array, nullptr);
+    ASSERT_EQ(3u, array->items.size());
+
+    EXPECT_NE(nullptr, dynamic_cast<const Reference*>(array->items[0].get()));
+    EXPECT_NE(nullptr, dynamic_cast<const String*>(array->items[1].get()));
+    EXPECT_NE(nullptr, dynamic_cast<const BinaryPrimitive*>(array->items[2].get()));
+}
+
+TEST_F(ResourceParserTest, ParsePlural) {
+    std::stringstream input;
+    input << "<plurals name=\"foo\">" << std::endl
+          << "  <item quantity=\"other\">apples</item>" << std::endl
+          << "  <item quantity=\"one\">apple</item>" << std::endl
+          << "</plurals>" << std::endl
+          << std::endl;
+    ASSERT_TRUE(testParse(input));
+}
+
+TEST_F(ResourceParserTest, ParseCommentsWithResource) {
+    std::stringstream input;
+    input << "<!-- This is a comment -->" << std::endl
+          << "<string name=\"foo\">Hi</string>" << std::endl;
+    ASSERT_TRUE(testParse(input));
+
+    const ResourceTableType* type;
+    const ResourceEntry* entry;
+    std::tie(type, entry) = mTable->findResource(ResourceName{
+            u"android", ResourceType::kString, u"foo"});
+    ASSERT_NE(type, nullptr);
+    ASSERT_NE(entry, nullptr);
+    ASSERT_FALSE(entry->values.empty());
+    EXPECT_EQ(entry->values.front().comment, u"This is a comment");
+}
+
+/*
+ * Declaring an ID as public should not require a separate definition
+ * (as an ID has no value).
+ */
+TEST_F(ResourceParserTest, ParsePublicIdAsDefinition) {
+    std::stringstream input("<public type=\"id\" name=\"foo\"/>");
+    ASSERT_TRUE(testParse(input));
+
+    const Id* id = findResource<Id>(ResourceName{ u"android", ResourceType::kId, u"foo" });
+    ASSERT_NE(nullptr, id);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
new file mode 100644
index 0000000..794090d0
--- /dev/null
+++ b/tools/aapt2/ResourceTable.cpp
@@ -0,0 +1,334 @@
+/*
+ * 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.
+ */
+
+#include "ConfigDescription.h"
+#include "Logger.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "Util.h"
+
+#include <algorithm>
+#include <androidfw/ResourceTypes.h>
+#include <memory>
+#include <string>
+#include <tuple>
+
+namespace aapt {
+
+static bool compareConfigs(const ResourceConfigValue& lhs, const ConfigDescription& rhs) {
+    return lhs.config < rhs;
+}
+
+static bool lessThanType(const std::unique_ptr<ResourceTableType>& lhs, ResourceType rhs) {
+    return lhs->type < rhs;
+}
+
+static bool lessThanEntry(const std::unique_ptr<ResourceEntry>& lhs, const StringPiece16& rhs) {
+    return lhs->name.compare(0, lhs->name.size(), rhs.data(), rhs.size()) < 0;
+}
+
+ResourceTable::ResourceTable() : mPackageId(kUnsetPackageId) {
+}
+
+std::unique_ptr<ResourceTableType>& ResourceTable::findOrCreateType(ResourceType type) {
+    auto last = mTypes.end();
+    auto iter = std::lower_bound(mTypes.begin(), last, type, lessThanType);
+    if (iter != last) {
+        if ((*iter)->type == type) {
+            return *iter;
+        }
+    }
+    return *mTypes.emplace(iter, new ResourceTableType{ type });
+}
+
+std::unique_ptr<ResourceEntry>& ResourceTable::findOrCreateEntry(
+        std::unique_ptr<ResourceTableType>& type, const StringPiece16& name) {
+    auto last = type->entries.end();
+    auto iter = std::lower_bound(type->entries.begin(), last, name, lessThanEntry);
+    if (iter != last) {
+        if (name == (*iter)->name) {
+            return *iter;
+        }
+    }
+    return *type->entries.emplace(iter, new ResourceEntry{ name });
+}
+
+struct IsAttributeVisitor : ConstValueVisitor {
+    bool isAttribute = false;
+
+    void visit(const Attribute&, ValueVisitorArgs&) override {
+        isAttribute = true;
+    }
+
+    operator bool() {
+        return isAttribute;
+    }
+};
+
+/**
+ * The default handler for collisions. A return value of -1 means keep the
+ * existing value, 0 means fail, and +1 means take the incoming value.
+ */
+static int defaultCollisionHandler(const Value& existing, const Value& incoming) {
+    IsAttributeVisitor existingIsAttr, incomingIsAttr;
+    existing.accept(existingIsAttr, {});
+    incoming.accept(incomingIsAttr, {});
+
+    if (!incomingIsAttr) {
+        if (incoming.isWeak()) {
+            // We're trying to add a weak resource but a resource
+            // already exists. Keep the existing.
+            return -1;
+        } else if (existing.isWeak()) {
+            // Override the weak resource with the new strong resource.
+            return 1;
+        }
+        // The existing and incoming values are strong, this is an error
+        // if the values are not both attributes.
+        return 0;
+    }
+
+    if (!existingIsAttr) {
+        if (existing.isWeak()) {
+            // The existing value is not an attribute and it is weak,
+            // so take the incoming attribute value.
+            return 1;
+        }
+        // The existing value is not an attribute and it is strong,
+        // so the incoming attribute value is an error.
+        return 0;
+    }
+
+    //
+    // Attribute specific handling. At this point we know both
+    // values are attributes. Since we can declare and define
+    // attributes all-over, we do special handling to see
+    // which definition sticks.
+    //
+    const Attribute& existingAttr = static_cast<const Attribute&>(existing);
+    const Attribute& incomingAttr = static_cast<const Attribute&>(incoming);
+    if (existingAttr.typeMask == incomingAttr.typeMask) {
+        // The two attributes are both DECLs, but they are plain attributes
+        // with the same formats.
+        // Keep the strongest one.
+        return existingAttr.isWeak() ? 1 : -1;
+    }
+
+    if (existingAttr.isWeak() && existingAttr.typeMask == android::ResTable_map::TYPE_ANY) {
+        // Any incoming attribute is better than this.
+        return 1;
+    }
+
+    if (incomingAttr.isWeak() && incomingAttr.typeMask == android::ResTable_map::TYPE_ANY) {
+        // The incoming attribute may be a USE instead of a DECL.
+        // Keep the existing attribute.
+        return -1;
+    }
+    return 0;
+}
+
+static constexpr const char16_t* kValidNameChars = u"._-";
+
+bool ResourceTable::addResource(const ResourceNameRef& name, const ResourceId resId,
+        const ConfigDescription& config, const SourceLine& source,
+        std::unique_ptr<Value> value) {
+    if (!name.package.empty() && name.package != mPackage) {
+        Logger::error(source)
+                << "resource '"
+                << name
+                << "' has incompatible package. Must be '"
+                << mPackage
+                << "'."
+                << std::endl;
+        return false;
+    }
+
+    auto badCharIter = util::findNonAlphaNumericAndNotInSet(name.entry, kValidNameChars);
+    if (badCharIter != name.entry.end()) {
+        Logger::error(source)
+                << "resource '"
+                << name
+                << "' has invalid entry name '"
+                << name.entry
+                << "'. Invalid character '"
+                << StringPiece16(badCharIter, 1)
+                << "'."
+                << std::endl;
+        return false;
+    }
+
+    std::unique_ptr<ResourceTableType>& type = findOrCreateType(name.type);
+    if (resId.isValid() && type->typeId != ResourceTableType::kUnsetTypeId &&
+            type->typeId != resId.typeId()) {
+        Logger::error(source)
+                << "trying to add resource '"
+                << name
+                << "' with ID "
+                << resId
+                << " but type '"
+                << type->type
+                << "' already has ID "
+                << std::hex << type->typeId << std::dec
+                << "."
+                << std::endl;
+        return false;
+    }
+
+    std::unique_ptr<ResourceEntry>& entry = findOrCreateEntry(type, name.entry);
+    if (resId.isValid() && entry->entryId != ResourceEntry::kUnsetEntryId &&
+            entry->entryId != resId.entryId()) {
+        Logger::error(source)
+                << "trying to add resource '"
+                << name
+                << "' with ID "
+                << resId
+                << " but resource already has ID "
+                << ResourceId(mPackageId, type->typeId, entry->entryId)
+                << "."
+                << std::endl;
+        return false;
+    }
+
+    const auto endIter = std::end(entry->values);
+    auto iter = std::lower_bound(std::begin(entry->values), endIter, config, compareConfigs);
+    if (iter == endIter || iter->config != config) {
+        // This resource did not exist before, add it.
+        entry->values.insert(iter, ResourceConfigValue{ config, source, {}, std::move(value) });
+    } else {
+        int collisionResult = defaultCollisionHandler(*iter->value, *value);
+        if (collisionResult > 0) {
+            // Take the incoming value.
+            *iter = ResourceConfigValue{ config, source, {}, std::move(value) };
+        } else if (collisionResult == 0) {
+            Logger::error(source)
+                    << "duplicate value for resource '" << name << "' "
+                    << "with config '" << iter->config << "'."
+                    << std::endl;
+
+            Logger::error(iter->source)
+                    << "resource previously defined here."
+                    << std::endl;
+            return false;
+        }
+    }
+
+    if (resId.isValid()) {
+        type->typeId = resId.typeId();
+        entry->entryId = resId.entryId();
+    }
+    return true;
+}
+
+bool ResourceTable::addResource(const ResourceNameRef& name, const ConfigDescription& config,
+                                const SourceLine& source, std::unique_ptr<Value> value) {
+    return addResource(name, ResourceId{}, config, source, std::move(value));
+}
+
+bool ResourceTable::markPublic(const ResourceNameRef& name, const ResourceId resId,
+                               const SourceLine& source) {
+    if (!name.package.empty() && name.package != mPackage) {
+        Logger::error(source)
+                << "resource '"
+                << name
+                << "' has incompatible package. Must be '"
+                << mPackage
+                << "'."
+            << std::endl;
+        return false;
+    }
+
+    auto badCharIter = util::findNonAlphaNumericAndNotInSet(name.entry, kValidNameChars);
+    if (badCharIter != name.entry.end()) {
+        Logger::error(source)
+                << "resource '"
+                << name
+                << "' has invalid entry name '"
+                << name.entry
+                << "'. Invalid character '"
+                << StringPiece16(badCharIter, 1)
+                << "'."
+                << std::endl;
+        return false;
+    }
+
+    std::unique_ptr<ResourceTableType>& type = findOrCreateType(name.type);
+    if (resId.isValid() && type->typeId != ResourceTableType::kUnsetTypeId &&
+            type->typeId != resId.typeId()) {
+        Logger::error(source)
+                << "trying to make resource '"
+                << name
+                << "' public with ID "
+                << resId
+                << " but type '"
+                << type->type
+                << "' already has ID "
+                << std::hex << type->typeId << std::dec
+                << "."
+                << std::endl;
+        return false;
+    }
+
+    std::unique_ptr<ResourceEntry>& entry = findOrCreateEntry(type, name.entry);
+    if (resId.isValid() && entry->entryId != ResourceEntry::kUnsetEntryId &&
+            entry->entryId != resId.entryId()) {
+        Logger::error(source)
+                << "trying to make resource '"
+                << name
+                << "' public with ID "
+                << resId
+                << " but resource already has ID "
+                << ResourceId(mPackageId, type->typeId, entry->entryId)
+                << "."
+                << std::endl;
+        return false;
+    }
+
+    type->publicStatus.isPublic = true;
+    entry->publicStatus.isPublic = true;
+
+    if (resId.isValid()) {
+        type->typeId = resId.typeId();
+        entry->entryId = resId.entryId();
+    }
+
+    if (entry->values.empty()) {
+        entry->values.push_back(ResourceConfigValue{ {}, source, {},
+                                    util::make_unique<Sentinel>() });
+    }
+    return true;
+}
+
+std::tuple<const ResourceTableType*, const ResourceEntry*>
+ResourceTable::findResource(const ResourceNameRef& name) const {
+    if (name.package != mPackage) {
+        return {};
+    }
+
+    auto iter = std::lower_bound(mTypes.begin(), mTypes.end(), name.type, lessThanType);
+    if (iter == mTypes.end() || (*iter)->type != name.type) {
+        return {};
+    }
+
+    const std::unique_ptr<ResourceTableType>& type = *iter;
+    auto iter2 = std::lower_bound(type->entries.begin(), type->entries.end(), name.entry,
+                                  lessThanEntry);
+    if (iter2 == type->entries.end() || name.entry != (*iter2)->name) {
+        return {};
+    }
+    return std::make_tuple(iter->get(), iter2->get());
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
new file mode 100644
index 0000000..57b5213
--- /dev/null
+++ b/tools/aapt2/ResourceTable.h
@@ -0,0 +1,254 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_RESOURCE_TABLE_H
+#define AAPT_RESOURCE_TABLE_H
+
+#include "ConfigDescription.h"
+#include "Resource.h"
+#include "ResourceValues.h"
+#include "Source.h"
+#include "StringPool.h"
+
+#include <memory>
+#include <string>
+#include <tuple>
+#include <vector>
+
+namespace aapt {
+
+/**
+ * The Public status of a resource.
+ */
+struct Public {
+    bool isPublic = false;
+    std::u16string comment;
+};
+
+/**
+ * The resource value for a specific configuration.
+ */
+struct ResourceConfigValue {
+    ConfigDescription config;
+    SourceLine source;
+    std::u16string comment;
+    std::unique_ptr<Value> value;
+};
+
+/**
+ * Represents a resource entry, which may have
+ * varying values for each defined configuration.
+ */
+struct ResourceEntry {
+    enum {
+        kUnsetEntryId = 0xffffffffu
+    };
+
+    /**
+     * The name of the resource. Immutable, as
+     * this determines the order of this resource
+     * when doing lookups.
+     */
+    const std::u16string name;
+
+    /**
+     * The entry ID for this resource.
+     */
+    size_t entryId;
+
+    /**
+     * Whether this resource is public (and must maintain the same
+     * entry ID across builds).
+     */
+    Public publicStatus;
+
+    /**
+     * The resource's values for each configuration.
+     */
+    std::vector<ResourceConfigValue> values;
+
+    inline ResourceEntry(const StringPiece16& _name);
+    inline ResourceEntry(const ResourceEntry* rhs);
+};
+
+/**
+ * Represents a resource type, which holds entries defined
+ * for this type.
+ */
+struct ResourceTableType {
+    enum {
+        kUnsetTypeId = 0xffffffffu
+    };
+
+    /**
+     * The logical type of resource (string, drawable, layout, etc.).
+     */
+    const ResourceType type;
+
+    /**
+     * The type ID for this resource.
+     */
+    size_t typeId;
+
+    /**
+     * Whether this type is public (and must maintain the same
+     * type ID across builds).
+     */
+    Public publicStatus;
+
+    /**
+     * List of resources for this type.
+     */
+    std::vector<std::unique_ptr<ResourceEntry>> entries;
+
+    ResourceTableType(const ResourceType _type);
+    ResourceTableType(const ResourceTableType* rhs);
+};
+
+/**
+ * The container and index for all resources defined for an app. This gets
+ * flattened into a binary resource table (resources.arsc).
+ */
+class ResourceTable {
+public:
+    using iterator = std::vector<std::unique_ptr<ResourceTableType>>::iterator;
+    using const_iterator = std::vector<std::unique_ptr<ResourceTableType>>::const_iterator;
+
+    enum {
+        kUnsetPackageId = 0xffffffff
+    };
+
+    ResourceTable();
+
+    size_t getPackageId() const;
+    void setPackageId(size_t packageId);
+
+    const std::u16string& getPackage() const;
+    void setPackage(const StringPiece16& package);
+
+    bool addResource(const ResourceNameRef& name, const ConfigDescription& config,
+                     const SourceLine& source, std::unique_ptr<Value> value);
+
+    bool addResource(const ResourceNameRef& name, const ResourceId resId,
+                     const ConfigDescription& config, const SourceLine& source,
+                     std::unique_ptr<Value> value);
+
+    bool markPublic(const ResourceNameRef& name, const ResourceId resId, const SourceLine& source);
+
+    /**
+     * Returns the string pool used by this ResourceTable.
+     * Values that reference strings should use this pool to create
+     * their strings.
+     */
+    StringPool& getValueStringPool();
+    const StringPool& getValueStringPool() const;
+
+    std::tuple<const ResourceTableType*, const ResourceEntry*>
+    findResource(const ResourceNameRef& name) const;
+
+    iterator begin();
+    iterator end();
+    const_iterator begin() const;
+    const_iterator end() const;
+
+private:
+    std::unique_ptr<ResourceTableType>& findOrCreateType(ResourceType type);
+    std::unique_ptr<ResourceEntry>& findOrCreateEntry(std::unique_ptr<ResourceTableType>& type,
+                                                      const StringPiece16& name);
+
+    std::u16string mPackage;
+    size_t mPackageId;
+
+    // StringPool must come before mTypes so that it is destroyed after.
+    // When StringPool references are destroyed (as they will be when mTypes
+    // is destroyed), they decrement a refCount, which would cause invalid
+    // memory access if the pool was already destroyed.
+    StringPool mValuePool;
+
+    std::vector<std::unique_ptr<ResourceTableType>> mTypes;
+};
+
+//
+// ResourceEntry implementation.
+//
+
+inline ResourceEntry::ResourceEntry(const StringPiece16& _name) :
+        name(_name.toString()), entryId(kUnsetEntryId) {
+}
+
+inline ResourceEntry::ResourceEntry(const ResourceEntry* rhs) :
+        name(rhs->name), entryId(rhs->entryId), publicStatus(rhs->publicStatus) {
+}
+
+//
+// ResourceTableType implementation.
+//
+
+inline ResourceTableType::ResourceTableType(const ResourceType _type) :
+        type(_type), typeId(kUnsetTypeId) {
+}
+
+inline ResourceTableType::ResourceTableType(const ResourceTableType* rhs) :
+        type(rhs->type), typeId(rhs->typeId), publicStatus(rhs->publicStatus) {
+}
+
+//
+// ResourceTable implementation.
+//
+
+inline StringPool& ResourceTable::getValueStringPool() {
+    return mValuePool;
+}
+
+inline const StringPool& ResourceTable::getValueStringPool() const {
+    return mValuePool;
+}
+
+inline ResourceTable::iterator ResourceTable::begin() {
+    return mTypes.begin();
+}
+
+inline ResourceTable::iterator ResourceTable::end() {
+    return mTypes.end();
+}
+
+inline ResourceTable::const_iterator ResourceTable::begin() const {
+    return mTypes.begin();
+}
+
+inline ResourceTable::const_iterator ResourceTable::end() const {
+    return mTypes.end();
+}
+
+inline const std::u16string& ResourceTable::getPackage() const {
+    return mPackage;
+}
+
+inline size_t ResourceTable::getPackageId() const {
+    return mPackageId;
+}
+
+inline void ResourceTable::setPackage(const StringPiece16& package) {
+    mPackage = package.toString();
+}
+
+inline void ResourceTable::setPackageId(size_t packageId) {
+    mPackageId = packageId;
+}
+
+} // namespace aapt
+
+#endif // AAPT_RESOURCE_TABLE_H
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
new file mode 100644
index 0000000..785ea15
--- /dev/null
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -0,0 +1,228 @@
+/*
+ * 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.
+ */
+
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "Util.h"
+
+#include <algorithm>
+#include <gtest/gtest.h>
+#include <ostream>
+#include <string>
+
+namespace aapt {
+
+struct TestValue : public Value {
+    std::u16string value;
+
+    TestValue(StringPiece16 str) : value(str.toString()) {
+    }
+
+    TestValue* clone() const override {
+        return new TestValue(value);
+    }
+
+    void print(std::ostream& out) const override {
+        out << "(test) " << value;
+    }
+
+    virtual void accept(ValueVisitor&, ValueVisitorArgs&&) override {}
+    virtual void accept(ConstValueVisitor&, ValueVisitorArgs&&) const override {}
+};
+
+struct TestWeakValue : public Value {
+    bool isWeak() const override {
+        return true;
+    }
+
+    TestWeakValue* clone() const override {
+        return new TestWeakValue();
+    }
+
+    void print(std::ostream& out) const override {
+        out << "(test) [weak]";
+    }
+
+    virtual void accept(ValueVisitor&, ValueVisitorArgs&&) override {}
+    virtual void accept(ConstValueVisitor&, ValueVisitorArgs&&) const override {}
+};
+
+TEST(ResourceTableTest, FailToAddResourceWithBadName) {
+    ResourceTable table;
+    table.setPackage(u"android");
+
+    EXPECT_FALSE(table.addResource(
+            ResourceNameRef{ u"android", ResourceType::kId, u"hey,there" },
+            {}, SourceLine{ "test.xml", 21 },
+            util::make_unique<TestValue>(u"rawValue")));
+
+    EXPECT_FALSE(table.addResource(
+            ResourceNameRef{ u"android", ResourceType::kId, u"hey:there" },
+            {}, SourceLine{ "test.xml", 21 },
+            util::make_unique<TestValue>(u"rawValue")));
+}
+
+TEST(ResourceTableTest, AddOneResource) {
+    const std::u16string kAndroidPackage = u"android";
+
+    ResourceTable table;
+    table.setPackage(kAndroidPackage);
+
+    const ResourceName name = { kAndroidPackage, ResourceType::kAttr, u"id" };
+
+    EXPECT_TRUE(table.addResource(name, {}, SourceLine{ "test/path/file.xml", 23 },
+                                  util::make_unique<TestValue>(u"rawValue")));
+
+    const ResourceTableType* type;
+    const ResourceEntry* entry;
+    std::tie(type, entry) = table.findResource(name);
+    ASSERT_NE(nullptr, type);
+    ASSERT_NE(nullptr, entry);
+    EXPECT_EQ(name.entry, entry->name);
+
+    ASSERT_NE(std::end(entry->values),
+              std::find_if(std::begin(entry->values), std::end(entry->values),
+                      [](const ResourceConfigValue& val) -> bool {
+                          return val.config == ConfigDescription{};
+                      }));
+}
+
+TEST(ResourceTableTest, AddMultipleResources) {
+    const std::u16string kAndroidPackage = u"android";
+    ResourceTable table;
+    table.setPackage(kAndroidPackage);
+
+    ConfigDescription config;
+    ConfigDescription languageConfig;
+    memcpy(languageConfig.language, "pl", sizeof(languageConfig.language));
+
+    EXPECT_TRUE(table.addResource(
+            ResourceName{ kAndroidPackage, ResourceType::kAttr, u"layout_width" },
+            config, SourceLine{ "test/path/file.xml", 10 },
+            util::make_unique<TestValue>(u"rawValue")));
+
+    EXPECT_TRUE(table.addResource(
+            ResourceName{ kAndroidPackage, ResourceType::kAttr, u"id" },
+            config, SourceLine{ "test/path/file.xml", 12 },
+            util::make_unique<TestValue>(u"rawValue")));
+
+    EXPECT_TRUE(table.addResource(
+            ResourceName{ kAndroidPackage, ResourceType::kString, u"ok" },
+            config, SourceLine{ "test/path/file.xml", 14 },
+            util::make_unique<TestValue>(u"Ok")));
+
+    EXPECT_TRUE(table.addResource(
+            ResourceName{ kAndroidPackage, ResourceType::kString, u"ok" },
+            languageConfig, SourceLine{ "test/path/file.xml", 20 },
+            util::make_unique<TestValue>(u"Tak")));
+
+    const auto endTypeIter = std::end(table);
+    auto typeIter = std::begin(table);
+
+    ASSERT_NE(endTypeIter, typeIter);
+    EXPECT_EQ(ResourceType::kAttr, (*typeIter)->type);
+
+    {
+        const std::unique_ptr<ResourceTableType>& type = *typeIter;
+        const auto endEntryIter = std::end(type->entries);
+        auto entryIter = std::begin(type->entries);
+        ASSERT_NE(endEntryIter, entryIter);
+        EXPECT_EQ(std::u16string(u"id"), (*entryIter)->name);
+
+        ++entryIter;
+        ASSERT_NE(endEntryIter, entryIter);
+        EXPECT_EQ(std::u16string(u"layout_width"), (*entryIter)->name);
+
+        ++entryIter;
+        ASSERT_EQ(endEntryIter, entryIter);
+    }
+
+    ++typeIter;
+    ASSERT_NE(endTypeIter, typeIter);
+    EXPECT_EQ(ResourceType::kString, (*typeIter)->type);
+
+    {
+        const std::unique_ptr<ResourceTableType>& type = *typeIter;
+        const auto endEntryIter = std::end(type->entries);
+        auto entryIter = std::begin(type->entries);
+        ASSERT_NE(endEntryIter, entryIter);
+        EXPECT_EQ(std::u16string(u"ok"), (*entryIter)->name);
+
+        {
+            const std::unique_ptr<ResourceEntry>& entry = *entryIter;
+            const auto endConfigIter = std::end(entry->values);
+            auto configIter = std::begin(entry->values);
+
+            ASSERT_NE(endConfigIter, configIter);
+            EXPECT_EQ(config, configIter->config);
+            const TestValue* value =
+                    dynamic_cast<const TestValue*>(configIter->value.get());
+            ASSERT_NE(nullptr, value);
+            EXPECT_EQ(std::u16string(u"Ok"), value->value);
+
+            ++configIter;
+            ASSERT_NE(endConfigIter, configIter);
+            EXPECT_EQ(languageConfig, configIter->config);
+            EXPECT_NE(nullptr, configIter->value);
+
+            value = dynamic_cast<const TestValue*>(configIter->value.get());
+            ASSERT_NE(nullptr, value);
+            EXPECT_EQ(std::u16string(u"Tak"), value->value);
+
+            ++configIter;
+            EXPECT_EQ(endConfigIter, configIter);
+        }
+
+        ++entryIter;
+        ASSERT_EQ(endEntryIter, entryIter);
+    }
+
+    ++typeIter;
+    EXPECT_EQ(endTypeIter, typeIter);
+}
+
+TEST(ResourceTableTest, OverrideWeakResourceValue) {
+    const std::u16string kAndroid = u"android";
+
+    ResourceTable table;
+    table.setPackage(kAndroid);
+    table.setPackageId(0x01);
+
+    ASSERT_TRUE(table.addResource(
+            ResourceName{ kAndroid, ResourceType::kAttr, u"foo" },
+            {}, {}, util::make_unique<TestWeakValue>()));
+
+    const ResourceTableType* type;
+    const ResourceEntry* entry;
+    std::tie(type, entry) = table.findResource(
+            ResourceNameRef{ kAndroid, ResourceType::kAttr, u"foo" });
+    ASSERT_NE(nullptr, type);
+    ASSERT_NE(nullptr, entry);
+    ASSERT_EQ(entry->values.size(), 1u);
+    EXPECT_TRUE(entry->values.front().value->isWeak());
+
+    ASSERT_TRUE(table.addResource(ResourceName{ kAndroid, ResourceType::kAttr, u"foo" }, {}, {},
+                                  util::make_unique<TestValue>(u"bar")));
+
+    std::tie(type, entry) = table.findResource(
+            ResourceNameRef{ kAndroid, ResourceType::kAttr, u"foo" });
+    ASSERT_NE(nullptr, type);
+    ASSERT_NE(nullptr, entry);
+    ASSERT_EQ(entry->values.size(), 1u);
+    EXPECT_FALSE(entry->values.front().value->isWeak());
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ResourceTypeExtensions.h b/tools/aapt2/ResourceTypeExtensions.h
new file mode 100644
index 0000000..60e225e
--- /dev/null
+++ b/tools/aapt2/ResourceTypeExtensions.h
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_RESOURCE_TYPE_EXTENSIONS_H
+#define AAPT_RESOURCE_TYPE_EXTENSIONS_H
+
+#include <androidfw/ResourceTypes.h>
+
+namespace aapt {
+
+/**
+ * New android::ResChunk_header types defined
+ * for AAPT to use.
+ *
+ * TODO(adamlesinski): Consider reserving these
+ * enums in androidfw/ResourceTypes.h to avoid
+ * future collisions.
+ */
+enum {
+    /**
+     * A chunk that holds the string pool
+     * for source entries (path/to/source:line).
+     */
+    RES_TABLE_SOURCE_POOL_TYPE = 0x000e,
+
+    /**
+     * A chunk holding names of externally
+     * defined symbols and offsets to where
+     * they are referenced in the table.
+     */
+    RES_TABLE_SYMBOL_TABLE_TYPE = 0x000f,
+};
+
+/**
+ * New resource types that are meant to only be used
+ * by AAPT and will not end up on the device.
+ */
+struct ExtendedTypes {
+    enum {
+        /**
+         * A sentinel value used when a resource is defined as
+         * public but it has no defined value yet. If we don't
+         * flatten it with some value, we will lose its name.
+         */
+        TYPE_SENTINEL = 0xff,
+
+        /**
+         * A raw string value that hasn't had its escape sequences
+         * processed nor whitespace removed.
+         */
+        TYPE_RAW_STRING = 0xfe
+    };
+};
+
+/**
+ * A chunk with type RES_TABLE_SYMBOL_TABLE_TYPE.
+ * Following the header are count number of SymbolTable_entry
+ * structures, followed by an android::ResStringPool_header.
+ */
+struct SymbolTable_header {
+    android::ResChunk_header header;
+
+    /**
+     * Number of SymbolTable_entry structures following
+     * this header.
+     */
+    uint32_t count;
+};
+
+struct SymbolTable_entry {
+    /**
+     * Offset from the beginning of the resource table
+     * where the symbol entry is referenced.
+     */
+    uint32_t offset;
+
+    /**
+     * The index into the string pool where the name of this
+     * symbol exists.
+     */
+    uint32_t stringIndex;
+};
+
+/**
+ * A structure representing the source of a resourc entry.
+ * Appears after an android::ResTable_entry or android::ResTable_map_entry.
+ *
+ * TODO(adamlesinski): This causes some issues when runtime code checks
+ * the size of an android::ResTable_entry. It assumes it is an
+ * android::ResTable_map_entry if the size is bigger than an android::ResTable_entry
+ * which may not be true if this structure is present.
+ */
+struct ResTable_entry_source {
+    /**
+     * Index into the source string pool.
+     */
+    uint32_t pathIndex;
+
+    /**
+     * Line number this resource was defined on.
+     */
+    uint32_t line;
+};
+
+} // namespace aapt
+
+#endif // AAPT_RESOURCE_TYPE_EXTENSIONS_H
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
new file mode 100644
index 0000000..60ef1a8
--- /dev/null
+++ b/tools/aapt2/ResourceValues.cpp
@@ -0,0 +1,447 @@
+/*
+ * 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.
+ */
+
+#include "Resource.h"
+#include "ResourceTypeExtensions.h"
+#include "ResourceValues.h"
+#include "Util.h"
+
+#include <androidfw/ResourceTypes.h>
+#include <limits>
+
+namespace aapt {
+
+bool Value::isItem() const {
+    return false;
+}
+
+bool Value::isWeak() const {
+    return false;
+}
+
+bool Item::isItem() const {
+    return true;
+}
+
+RawString::RawString(const StringPool::Ref& ref) : value(ref) {
+}
+
+RawString* RawString::clone() const {
+    return new RawString(value);
+}
+
+bool RawString::flatten(android::Res_value& outValue) const {
+    outValue.dataType = ExtendedTypes::TYPE_RAW_STRING;
+    outValue.data = static_cast<uint32_t>(value.getIndex());
+    return true;
+}
+
+void RawString::print(std::ostream& out) const {
+    out << "(raw string) " << *value;
+}
+
+Reference::Reference() : referenceType(Reference::Type::kResource) {
+}
+
+Reference::Reference(const ResourceNameRef& n, Type t) :
+        name(n.toResourceName()), referenceType(t) {
+}
+
+Reference::Reference(const ResourceId& i, Type type) : id(i), referenceType(type) {
+}
+
+bool Reference::flatten(android::Res_value& outValue) const {
+    outValue.dataType = (referenceType == Reference::Type::kResource)
+        ? android::Res_value::TYPE_REFERENCE
+        : android::Res_value::TYPE_ATTRIBUTE;
+    outValue.data = id.id;
+    return true;
+}
+
+Reference* Reference::clone() const {
+    Reference* ref = new Reference();
+    ref->referenceType = referenceType;
+    ref->name = name;
+    ref->id = id;
+    return ref;
+}
+
+void Reference::print(std::ostream& out) const {
+    out << "(reference) ";
+    if (referenceType == Reference::Type::kResource) {
+        out << "@";
+    } else {
+        out << "?";
+    }
+
+    if (name.isValid()) {
+        out << name;
+    }
+
+    if (id.isValid() || Res_INTERNALID(id.id)) {
+        out << " " << id;
+    }
+}
+
+bool Id::isWeak() const {
+    return true;
+}
+
+bool Id::flatten(android::Res_value& out) const {
+    out.dataType = android::Res_value::TYPE_NULL;
+    out.data = android::Res_value::DATA_NULL_UNDEFINED;
+    return true;
+}
+
+Id* Id::clone() const {
+    return new Id();
+}
+
+void Id::print(std::ostream& out) const {
+    out << "(id)";
+}
+
+String::String(const StringPool::Ref& ref) : value(ref) {
+}
+
+bool String::flatten(android::Res_value& outValue) const {
+    // Verify that our StringPool index is within encodeable limits.
+    if (value.getIndex() > std::numeric_limits<uint32_t>::max()) {
+        return false;
+    }
+
+    outValue.dataType = android::Res_value::TYPE_STRING;
+    outValue.data = static_cast<uint32_t>(value.getIndex());
+    return true;
+}
+
+String* String::clone() const {
+    return new String(value);
+}
+
+void String::print(std::ostream& out) const {
+    out << "(string) \"" << *value << "\"";
+}
+
+StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref) {
+}
+
+bool StyledString::flatten(android::Res_value& outValue) const {
+    if (value.getIndex() > std::numeric_limits<uint32_t>::max()) {
+        return false;
+    }
+
+    outValue.dataType = android::Res_value::TYPE_STRING;
+    outValue.data = static_cast<uint32_t>(value.getIndex());
+    return true;
+}
+
+StyledString* StyledString::clone() const {
+    return new StyledString(value);
+}
+
+void StyledString::print(std::ostream& out) const {
+    out << "(styled string) \"" << *value->str << "\"";
+}
+
+FileReference::FileReference(const StringPool::Ref& _path) : path(_path) {
+}
+
+bool FileReference::flatten(android::Res_value& outValue) const {
+    if (path.getIndex() > std::numeric_limits<uint32_t>::max()) {
+        return false;
+    }
+
+    outValue.dataType = android::Res_value::TYPE_STRING;
+    outValue.data = static_cast<uint32_t>(path.getIndex());
+    return true;
+}
+
+FileReference* FileReference::clone() const {
+    return new FileReference(path);
+}
+
+void FileReference::print(std::ostream& out) const {
+    out << "(file) " << *path;
+}
+
+BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {
+}
+
+bool BinaryPrimitive::flatten(android::Res_value& outValue) const {
+    outValue = value;
+    return true;
+}
+
+BinaryPrimitive* BinaryPrimitive::clone() const {
+    return new BinaryPrimitive(value);
+}
+
+void BinaryPrimitive::print(std::ostream& out) const {
+    switch (value.dataType) {
+        case android::Res_value::TYPE_NULL:
+            out << "(null)";
+            break;
+        case android::Res_value::TYPE_INT_DEC:
+            out << "(integer) " << value.data;
+            break;
+        case android::Res_value::TYPE_INT_HEX:
+            out << "(integer) " << std::hex << value.data << std::dec;
+            break;
+        case android::Res_value::TYPE_INT_BOOLEAN:
+            out << "(boolean) " << (value.data != 0 ? "true" : "false");
+            break;
+        case android::Res_value::TYPE_INT_COLOR_ARGB8:
+        case android::Res_value::TYPE_INT_COLOR_RGB8:
+        case android::Res_value::TYPE_INT_COLOR_ARGB4:
+        case android::Res_value::TYPE_INT_COLOR_RGB4:
+            out << "(color) #" << std::hex << value.data << std::dec;
+            break;
+        default:
+            out << "(unknown 0x" << std::hex << (int) value.dataType << ") 0x"
+                << std::hex << value.data << std::dec;
+            break;
+    }
+}
+
+bool Sentinel::isWeak() const {
+    return true;
+}
+
+bool Sentinel::flatten(android::Res_value& outValue) const {
+    outValue.dataType = ExtendedTypes::TYPE_SENTINEL;
+    outValue.data = 0;
+    return true;
+}
+
+Sentinel* Sentinel::clone() const {
+    return new Sentinel();
+}
+
+void Sentinel::print(std::ostream& out) const {
+    out << "(sentinel)";
+    return;
+}
+
+Attribute::Attribute(bool w, uint32_t t) : weak(w), typeMask(t) {
+}
+
+bool Attribute::isWeak() const {
+    return weak;
+}
+
+Attribute* Attribute::clone() const {
+    Attribute* attr = new Attribute(weak);
+    attr->typeMask = typeMask;
+    std::copy(symbols.begin(), symbols.end(), std::back_inserter(attr->symbols));
+    return attr;
+}
+
+void Attribute::print(std::ostream& out) const {
+    out << "(attr)";
+    if (typeMask == android::ResTable_map::TYPE_ANY) {
+        out << " any";
+        return;
+    }
+
+    bool set = false;
+    if ((typeMask & android::ResTable_map::TYPE_REFERENCE) != 0) {
+        if (!set) {
+            out << " ";
+            set = true;
+        } else {
+            out << "|";
+        }
+        out << "reference";
+    }
+
+    if ((typeMask & android::ResTable_map::TYPE_STRING) != 0) {
+        if (!set) {
+            out << " ";
+            set = true;
+        } else {
+            out << "|";
+        }
+        out << "string";
+    }
+
+    if ((typeMask & android::ResTable_map::TYPE_INTEGER) != 0) {
+        if (!set) {
+            out << " ";
+            set = true;
+        } else {
+            out << "|";
+        }
+        out << "integer";
+    }
+
+    if ((typeMask & android::ResTable_map::TYPE_BOOLEAN) != 0) {
+        if (!set) {
+            out << " ";
+            set = true;
+        } else {
+            out << "|";
+        }
+        out << "boolean";
+    }
+
+    if ((typeMask & android::ResTable_map::TYPE_COLOR) != 0) {
+        if (!set) {
+            out << " ";
+            set = true;
+        } else {
+            out << "|";
+        }
+        out << "color";
+    }
+
+    if ((typeMask & android::ResTable_map::TYPE_FLOAT) != 0) {
+        if (!set) {
+            out << " ";
+            set = true;
+        } else {
+            out << "|";
+        }
+        out << "float";
+    }
+
+    if ((typeMask & android::ResTable_map::TYPE_DIMENSION) != 0) {
+        if (!set) {
+            out << " ";
+            set = true;
+        } else {
+            out << "|";
+        }
+        out << "dimension";
+    }
+
+    if ((typeMask & android::ResTable_map::TYPE_FRACTION) != 0) {
+        if (!set) {
+            out << " ";
+            set = true;
+        } else {
+            out << "|";
+        }
+        out << "fraction";
+    }
+
+    if ((typeMask & android::ResTable_map::TYPE_ENUM) != 0) {
+        if (!set) {
+            out << " ";
+            set = true;
+        } else {
+            out << "|";
+        }
+        out << "enum";
+    }
+
+    if ((typeMask & android::ResTable_map::TYPE_FLAGS) != 0) {
+        if (!set) {
+            out << " ";
+            set = true;
+        } else {
+            out << "|";
+        }
+        out << "flags";
+    }
+
+    out << " ["
+        << util::joiner(symbols.begin(), symbols.end(), ", ")
+        << "]";
+
+    if (weak) {
+        out << " [weak]";
+    }
+}
+
+static ::std::ostream& operator<<(::std::ostream& out, const Attribute::Symbol& s) {
+    return out << s.symbol.name.entry << "=" << s.value;
+}
+
+Style* Style::clone() const {
+    Style* style = new Style();
+    style->parent = parent;
+    for (auto& entry : entries) {
+        style->entries.push_back(Entry{
+                entry.key,
+                std::unique_ptr<Item>(entry.value->clone())
+        });
+    }
+    return style;
+}
+
+void Style::print(std::ostream& out) const {
+    out << "(style) ";
+    if (!parent.name.entry.empty()) {
+        out << parent.name;
+    }
+    out << " ["
+        << util::joiner(entries.begin(), entries.end(), ", ")
+        << "]";
+}
+
+static ::std::ostream& operator<<(::std::ostream& out, const Style::Entry& value) {
+    out << value.key.name << " = ";
+    value.value->print(out);
+    return out;
+}
+
+Array* Array::clone() const {
+    Array* array = new Array();
+    for (auto& item : items) {
+        array->items.emplace_back(std::unique_ptr<Item>(item->clone()));
+    }
+    return array;
+}
+
+void Array::print(std::ostream& out) const {
+    out << "(array) ["
+        << util::joiner(items.begin(), items.end(), ", ")
+        << "]";
+}
+
+Plural* Plural::clone() const {
+    Plural* p = new Plural();
+    const size_t count = values.size();
+    for (size_t i = 0; i < count; i++) {
+        if (values[i]) {
+            p->values[i] = std::unique_ptr<Item>(values[i]->clone());
+        }
+    }
+    return p;
+}
+
+void Plural::print(std::ostream& out) const {
+    out << "(plural)";
+}
+
+static ::std::ostream& operator<<(::std::ostream& out, const std::unique_ptr<Item>& item) {
+    return out << *item;
+}
+
+Styleable* Styleable::clone() const {
+    Styleable* styleable = new Styleable();
+    std::copy(entries.begin(), entries.end(), std::back_inserter(styleable->entries));
+    return styleable;
+}
+
+void Styleable::print(std::ostream& out) const {
+    out << "(styleable) " << " ["
+        << util::joiner(entries.begin(), entries.end(), ", ")
+        << "]";
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
new file mode 100644
index 0000000..f25bcf0
--- /dev/null
+++ b/tools/aapt2/ResourceValues.h
@@ -0,0 +1,456 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_RESOURCE_VALUES_H
+#define AAPT_RESOURCE_VALUES_H
+
+#include "Resource.h"
+#include "StringPool.h"
+
+#include <array>
+#include <androidfw/ResourceTypes.h>
+#include <ostream>
+#include <vector>
+
+namespace aapt {
+
+struct ValueVisitor;
+struct ConstValueVisitor;
+struct ValueVisitorArgs;
+
+/**
+ * A resource value. This is an all-encompassing representation
+ * of Item and Map and their subclasses. The way to do
+ * type specific operations is to check the Value's type() and
+ * cast it to the appropriate subclass. This isn't super clean,
+ * but it is the simplest strategy.
+ */
+struct Value {
+    /**
+     * Whether or not this is an Item.
+     */
+    virtual bool isItem() const;
+
+    /**
+     * Whether this value is weak and can be overriden without
+     * warning or error. Default for base class is false.
+     */
+    virtual bool isWeak() const;
+
+    /**
+     * Calls the appropriate overload of ValueVisitor.
+     */
+    virtual void accept(ValueVisitor& visitor, ValueVisitorArgs&& args) = 0;
+
+    /**
+     * Const version of accept().
+     */
+    virtual void accept(ConstValueVisitor& visitor, ValueVisitorArgs&& args) const = 0;
+
+    /**
+     * Clone the value.
+     */
+    virtual Value* clone() const = 0;
+
+    /**
+     * Human readable printout of this value.
+     */
+    virtual void print(std::ostream& out) const = 0;
+};
+
+/**
+ * Inherit from this to get visitor accepting implementations for free.
+ */
+template <typename Derived>
+struct BaseValue : public Value {
+    virtual void accept(ValueVisitor& visitor, ValueVisitorArgs&& args) override;
+    virtual void accept(ConstValueVisitor& visitor, ValueVisitorArgs&& args) const override;
+};
+
+/**
+ * A resource item with a single value. This maps to android::ResTable_entry.
+ */
+struct Item : public Value {
+    /**
+     * An Item is, of course, an Item.
+     */
+    virtual bool isItem() const override;
+
+    /**
+     * Clone the Item.
+     */
+    virtual Item* clone() const override = 0;
+
+    /**
+     * Fills in an android::Res_value structure with this Item's binary representation.
+     * Returns false if an error ocurred.
+     */
+    virtual bool flatten(android::Res_value& outValue) const = 0;
+};
+
+/**
+ * Inherit from this to get visitor accepting implementations for free.
+ */
+template <typename Derived>
+struct BaseItem : public Item {
+    virtual void accept(ValueVisitor& visitor, ValueVisitorArgs&& args) override;
+    virtual void accept(ConstValueVisitor& visitor, ValueVisitorArgs&& args) const override;
+};
+
+/**
+ * A reference to another resource. This maps to android::Res_value::TYPE_REFERENCE.
+ *
+ * A reference can be symbolic (with the name set to a valid resource name) or be
+ * numeric (the id is set to a valid resource ID).
+ */
+struct Reference : public BaseItem<Reference> {
+    enum class Type {
+        kResource,
+        kAttribute,
+    };
+
+    ResourceName name;
+    ResourceId id;
+    Reference::Type referenceType;
+    bool privateReference = false;
+
+    Reference();
+    Reference(const ResourceNameRef& n, Type type = Type::kResource);
+    Reference(const ResourceId& i, Type type = Type::kResource);
+
+    bool flatten(android::Res_value& outValue) const override;
+    Reference* clone() const override;
+    void print(std::ostream& out) const override;
+};
+
+/**
+ * An ID resource. Has no real value, just a place holder.
+ */
+struct Id : public BaseItem<Id> {
+    bool isWeak() const override;
+    bool flatten(android::Res_value& out) const override;
+    Id* clone() const override;
+    void print(std::ostream& out) const override;
+};
+
+/**
+ * A raw, unprocessed string. This may contain quotations,
+ * escape sequences, and whitespace. This shall *NOT*
+ * end up in the final resource table.
+ */
+struct RawString : public BaseItem<RawString> {
+    StringPool::Ref value;
+
+    RawString(const StringPool::Ref& ref);
+
+    bool flatten(android::Res_value& outValue) const override;
+    RawString* clone() const override;
+    void print(std::ostream& out) const override;
+};
+
+struct String : public BaseItem<String> {
+    StringPool::Ref value;
+
+    String(const StringPool::Ref& ref);
+
+    bool flatten(android::Res_value& outValue) const override;
+    String* clone() const override;
+    void print(std::ostream& out) const override;
+};
+
+struct StyledString : public BaseItem<StyledString> {
+    StringPool::StyleRef value;
+
+    StyledString(const StringPool::StyleRef& ref);
+
+    bool flatten(android::Res_value& outValue) const override;
+    StyledString* clone() const override;
+    void print(std::ostream& out) const override;
+};
+
+struct FileReference : public BaseItem<FileReference> {
+    StringPool::Ref path;
+
+    FileReference() = default;
+    FileReference(const StringPool::Ref& path);
+
+    bool flatten(android::Res_value& outValue) const override;
+    FileReference* clone() const override;
+    void print(std::ostream& out) const override;
+};
+
+/**
+ * Represents any other android::Res_value.
+ */
+struct BinaryPrimitive : public BaseItem<BinaryPrimitive> {
+    android::Res_value value;
+
+    BinaryPrimitive() = default;
+    BinaryPrimitive(const android::Res_value& val);
+
+    bool flatten(android::Res_value& outValue) const override;
+    BinaryPrimitive* clone() const override;
+    void print(::std::ostream& out) const override;
+};
+
+/**
+ * Sentinel value that should be ignored in the final output.
+ * Mainly used as a placeholder for public entries with no
+ * values defined yet.
+ */
+struct Sentinel : public BaseItem<Sentinel> {
+    bool isWeak() const override;
+    bool flatten(android::Res_value& outValue) const override;
+    Sentinel* clone() const override;
+    void print(::std::ostream& out) const override;
+};
+
+struct Attribute : public BaseValue<Attribute> {
+    struct Symbol {
+        Reference symbol;
+        uint32_t value;
+    };
+
+    bool weak;
+    uint32_t typeMask;
+    uint32_t minInt;
+    uint32_t maxInt;
+    std::vector<Symbol> symbols;
+
+    Attribute(bool w, uint32_t t = 0u);
+
+    bool isWeak() const override;
+    virtual Attribute* clone() const override;
+    virtual void print(std::ostream& out) const override;
+};
+
+struct Style : public BaseValue<Style> {
+    struct Entry {
+        Reference key;
+        std::unique_ptr<Item> value;
+    };
+
+    Reference parent;
+    std::vector<Entry> entries;
+
+    Style* clone() const override;
+    void print(std::ostream& out) const override;
+};
+
+struct Array : public BaseValue<Array> {
+    std::vector<std::unique_ptr<Item>> items;
+
+    Array* clone() const override;
+    void print(std::ostream& out) const override;
+};
+
+struct Plural : public BaseValue<Plural> {
+    enum {
+        Zero = 0,
+        One,
+        Two,
+        Few,
+        Many,
+        Other,
+        Count
+    };
+
+    std::array<std::unique_ptr<Item>, Count> values;
+
+    Plural* clone() const override;
+    void print(std::ostream& out) const override;
+};
+
+struct Styleable : public BaseValue<Styleable> {
+    std::vector<Reference> entries;
+
+    Styleable* clone() const override;
+    void print(std::ostream& out) const override;
+};
+
+/**
+ * Stream operator for printing Value objects.
+ */
+inline ::std::ostream& operator<<(::std::ostream& out, const Value& value) {
+    value.print(out);
+    return out;
+}
+
+/**
+ * The argument object that gets passed through the value
+ * back to the ValueVisitor. Subclasses of ValueVisitor should
+ * subclass ValueVisitorArgs to contain the data they need
+ * to operate.
+ */
+struct ValueVisitorArgs {};
+
+/**
+ * Visits a value and runs the appropriate method based on its type.
+ */
+struct ValueVisitor {
+    virtual void visit(Reference& reference, ValueVisitorArgs& args) {
+        visitItem(reference, args);
+    }
+
+    virtual void visit(RawString& string, ValueVisitorArgs& args) {
+        visitItem(string, args);
+    }
+
+    virtual void visit(String& string, ValueVisitorArgs& args) {
+        visitItem(string, args);
+    }
+
+    virtual void visit(StyledString& string, ValueVisitorArgs& args) {
+        visitItem(string, args);
+    }
+
+    virtual void visit(FileReference& file, ValueVisitorArgs& args) {
+        visitItem(file, args);
+    }
+
+    virtual void visit(Id& id, ValueVisitorArgs& args) {
+        visitItem(id, args);
+    }
+
+    virtual void visit(BinaryPrimitive& primitive, ValueVisitorArgs& args) {
+        visitItem(primitive, args);
+    }
+
+    virtual void visit(Sentinel& sentinel, ValueVisitorArgs& args) {
+        visitItem(sentinel, args);
+    }
+
+    virtual void visit(Attribute& attr, ValueVisitorArgs& args) {}
+    virtual void visit(Style& style, ValueVisitorArgs& args) {}
+    virtual void visit(Array& array, ValueVisitorArgs& args) {}
+    virtual void visit(Plural& array, ValueVisitorArgs& args) {}
+    virtual void visit(Styleable& styleable, ValueVisitorArgs& args) {}
+
+    virtual void visitItem(Item& item, ValueVisitorArgs& args) {}
+};
+
+/**
+ * Const version of ValueVisitor.
+ */
+struct ConstValueVisitor {
+    virtual void visit(const Reference& reference, ValueVisitorArgs& args) {
+        visitItem(reference, args);
+    }
+
+    virtual void visit(const RawString& string, ValueVisitorArgs& args) {
+        visitItem(string, args);
+    }
+
+    virtual void visit(const String& string, ValueVisitorArgs& args) {
+        visitItem(string, args);
+    }
+
+    virtual void visit(const StyledString& string, ValueVisitorArgs& args) {
+        visitItem(string, args);
+    }
+
+    virtual void visit(const FileReference& file, ValueVisitorArgs& args) {
+        visitItem(file, args);
+    }
+
+    virtual void visit(const Id& id, ValueVisitorArgs& args) {
+        visitItem(id, args);
+    }
+
+    virtual void visit(const BinaryPrimitive& primitive, ValueVisitorArgs& args) {
+        visitItem(primitive, args);
+    }
+
+    virtual void visit(const Sentinel& sentinel, ValueVisitorArgs& args) {
+        visitItem(sentinel, args);
+    }
+
+    virtual void visit(const Attribute& attr, ValueVisitorArgs& args) {}
+    virtual void visit(const Style& style, ValueVisitorArgs& args) {}
+    virtual void visit(const Array& array, ValueVisitorArgs& args) {}
+    virtual void visit(const Plural& array, ValueVisitorArgs& args) {}
+    virtual void visit(const Styleable& styleable, ValueVisitorArgs& args) {}
+
+    virtual void visitItem(const Item& item, ValueVisitorArgs& args) {}
+};
+
+/**
+ * Convenience Visitor that forwards a specific type to a function.
+ * Args are not used as the function can bind variables. Do not use
+ * directly, use the wrapper visitFunc() method.
+ */
+template <typename T, typename TFunc>
+struct ValueVisitorFunc : ValueVisitor {
+    TFunc func;
+
+    ValueVisitorFunc(TFunc f) : func(f) {
+    }
+
+    void visit(T& value, ValueVisitorArgs&) override {
+        func(value);
+    }
+};
+
+/**
+ * Const version of ValueVisitorFunc.
+ */
+template <typename T, typename TFunc>
+struct ConstValueVisitorFunc : ConstValueVisitor {
+    TFunc func;
+
+    ConstValueVisitorFunc(TFunc f) : func(f) {
+    }
+
+    void visit(const T& value, ValueVisitorArgs&) override {
+        func(value);
+    }
+};
+
+template <typename T, typename TFunc>
+void visitFunc(Value& value, TFunc f) {
+    ValueVisitorFunc<T, TFunc> visitor(f);
+    value.accept(visitor, ValueVisitorArgs{});
+}
+
+template <typename T, typename TFunc>
+void visitFunc(const Value& value, TFunc f) {
+    ConstValueVisitorFunc<T, TFunc> visitor(f);
+    value.accept(visitor, ValueVisitorArgs{});
+}
+
+template <typename Derived>
+void BaseValue<Derived>::accept(ValueVisitor& visitor, ValueVisitorArgs&& args) {
+    visitor.visit(static_cast<Derived&>(*this), args);
+}
+
+template <typename Derived>
+void BaseValue<Derived>::accept(ConstValueVisitor& visitor, ValueVisitorArgs&& args) const {
+    visitor.visit(static_cast<const Derived&>(*this), args);
+}
+
+template <typename Derived>
+void BaseItem<Derived>::accept(ValueVisitor& visitor, ValueVisitorArgs&& args) {
+    visitor.visit(static_cast<Derived&>(*this), args);
+}
+
+template <typename Derived>
+void BaseItem<Derived>::accept(ConstValueVisitor& visitor, ValueVisitorArgs&& args) const {
+    visitor.visit(static_cast<const Derived&>(*this), args);
+}
+
+} // namespace aapt
+
+#endif // AAPT_RESOURCE_VALUES_H
diff --git a/tools/aapt2/Resource_test.cpp b/tools/aapt2/Resource_test.cpp
new file mode 100644
index 0000000..d957999
--- /dev/null
+++ b/tools/aapt2/Resource_test.cpp
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "Resource.h"
+
+namespace aapt {
+
+TEST(ResourceTypeTest, ParseResourceTypes) {
+    const ResourceType* type = parseResourceType(u"anim");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kAnim);
+
+    type = parseResourceType(u"animator");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kAnimator);
+
+    type = parseResourceType(u"array");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kArray);
+
+    type = parseResourceType(u"attr");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kAttr);
+
+    type = parseResourceType(u"^attr-private");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kAttrPrivate);
+
+    type = parseResourceType(u"bool");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kBool);
+
+    type = parseResourceType(u"color");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kColor);
+
+    type = parseResourceType(u"dimen");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kDimen);
+
+    type = parseResourceType(u"drawable");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kDrawable);
+
+    type = parseResourceType(u"fraction");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kFraction);
+
+    type = parseResourceType(u"id");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kId);
+
+    type = parseResourceType(u"integer");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kInteger);
+
+    type = parseResourceType(u"integer-array");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kIntegerArray);
+
+    type = parseResourceType(u"interpolator");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kInterpolator);
+
+    type = parseResourceType(u"layout");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kLayout);
+
+    type = parseResourceType(u"menu");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kMenu);
+
+    type = parseResourceType(u"mipmap");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kMipmap);
+
+    type = parseResourceType(u"plurals");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kPlurals);
+
+    type = parseResourceType(u"raw");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kRaw);
+
+    type = parseResourceType(u"string");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kString);
+
+    type = parseResourceType(u"style");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kStyle);
+
+    type = parseResourceType(u"transition");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kTransition);
+
+    type = parseResourceType(u"xml");
+    ASSERT_NE(type, nullptr);
+    EXPECT_EQ(*type, ResourceType::kXml);
+
+    type = parseResourceType(u"blahaha");
+    EXPECT_EQ(type, nullptr);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ScopedXmlPullParser.cpp b/tools/aapt2/ScopedXmlPullParser.cpp
new file mode 100644
index 0000000..d9ae72c
--- /dev/null
+++ b/tools/aapt2/ScopedXmlPullParser.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#include "ScopedXmlPullParser.h"
+
+#include <string>
+
+namespace aapt {
+
+ScopedXmlPullParser::ScopedXmlPullParser(XmlPullParser* parser) :
+        mParser(parser), mDepth(parser->getDepth()), mDone(false) {
+}
+
+ScopedXmlPullParser::~ScopedXmlPullParser() {
+    while (isGoodEvent(next()));
+}
+
+XmlPullParser::Event ScopedXmlPullParser::next() {
+    if (mDone) {
+        return Event::kEndDocument;
+    }
+
+    const Event event = mParser->next();
+    if (mParser->getDepth() <= mDepth) {
+        mDone = true;
+    }
+    return event;
+}
+
+XmlPullParser::Event ScopedXmlPullParser::getEvent() const {
+    return mParser->getEvent();
+}
+
+const std::string& ScopedXmlPullParser::getLastError() const {
+    return mParser->getLastError();
+}
+
+const std::u16string& ScopedXmlPullParser::getComment() const {
+    return mParser->getComment();
+}
+
+size_t ScopedXmlPullParser::getLineNumber() const {
+    return mParser->getLineNumber();
+}
+
+size_t ScopedXmlPullParser::getDepth() const {
+    const size_t depth = mParser->getDepth();
+    if (depth < mDepth) {
+        return 0;
+    }
+    return depth - mDepth;
+}
+
+const std::u16string& ScopedXmlPullParser::getText() const {
+    return mParser->getText();
+}
+
+const std::u16string& ScopedXmlPullParser::getNamespacePrefix() const {
+    return mParser->getNamespacePrefix();
+}
+
+const std::u16string& ScopedXmlPullParser::getNamespaceUri() const {
+    return mParser->getNamespaceUri();
+}
+
+const std::u16string& ScopedXmlPullParser::getElementNamespace() const {
+    return mParser->getElementNamespace();
+}
+
+const std::u16string& ScopedXmlPullParser::getElementName() const {
+    return mParser->getElementName();
+}
+
+size_t ScopedXmlPullParser::getAttributeCount() const {
+    return mParser->getAttributeCount();
+}
+
+XmlPullParser::const_iterator ScopedXmlPullParser::beginAttributes() const {
+    return mParser->beginAttributes();
+}
+
+XmlPullParser::const_iterator ScopedXmlPullParser::endAttributes() const {
+    return mParser->endAttributes();
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ScopedXmlPullParser.h b/tools/aapt2/ScopedXmlPullParser.h
new file mode 100644
index 0000000..e660499
--- /dev/null
+++ b/tools/aapt2/ScopedXmlPullParser.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_SCOPED_XML_PULL_PARSER_H
+#define AAPT_SCOPED_XML_PULL_PARSER_H
+
+#include "XmlPullParser.h"
+
+#include <string>
+
+namespace aapt {
+
+/**
+ * An XmlPullParser that will not read past the depth
+ * of the underlying parser. When this parser is destroyed,
+ * it moves the underlying parser to the same depth it
+ * started with.
+ *
+ * You can write code like this:
+ *
+ *   while (XmlPullParser::isGoodEvent(parser.next())) {
+ *     if (parser.getEvent() != XmlPullParser::Event::StartElement) {
+ *       continue;
+ *     }
+ *
+ *     ScopedXmlPullParser scoped(parser);
+ *     if (parser.getElementName() == u"id") {
+ *       // do work.
+ *     } else {
+ *       // do nothing, as all the sub elements will be skipped
+ *       // when scoped goes out of scope.
+ *     }
+ *   }
+ */
+class ScopedXmlPullParser : public XmlPullParser {
+public:
+    ScopedXmlPullParser(XmlPullParser* parser);
+    ScopedXmlPullParser(const ScopedXmlPullParser&) = delete;
+    ScopedXmlPullParser& operator=(const ScopedXmlPullParser&) = delete;
+    ~ScopedXmlPullParser();
+
+    Event getEvent() const;
+    const std::string& getLastError() const;
+    Event next();
+
+    const std::u16string& getComment() const;
+    size_t getLineNumber() const;
+    size_t getDepth() const;
+
+    const std::u16string& getText() const;
+
+    const std::u16string& getNamespacePrefix() const;
+    const std::u16string& getNamespaceUri() const;
+
+    const std::u16string& getElementNamespace() const;
+    const std::u16string& getElementName() const;
+
+    const_iterator beginAttributes() const;
+    const_iterator endAttributes() const;
+    size_t getAttributeCount() const;
+
+private:
+    XmlPullParser* mParser;
+    size_t mDepth;
+    bool mDone;
+};
+
+} // namespace aapt
+
+#endif // AAPT_SCOPED_XML_PULL_PARSER_H
diff --git a/tools/aapt2/ScopedXmlPullParser_test.cpp b/tools/aapt2/ScopedXmlPullParser_test.cpp
new file mode 100644
index 0000000..342f305
--- /dev/null
+++ b/tools/aapt2/ScopedXmlPullParser_test.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+#include "ScopedXmlPullParser.h"
+#include "SourceXmlPullParser.h"
+
+#include <gtest/gtest.h>
+#include <sstream>
+#include <string>
+
+namespace aapt {
+
+TEST(ScopedXmlPullParserTest, StopIteratingAtNoNZeroDepth) {
+    std::stringstream input;
+    input << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl
+          << "<resources><string></string></resources>" << std::endl;
+
+    SourceXmlPullParser sourceParser(input);
+    EXPECT_EQ(XmlPullParser::Event::kStartElement, sourceParser.next());
+    EXPECT_EQ(std::u16string(u"resources"), sourceParser.getElementName());
+
+    EXPECT_EQ(XmlPullParser::Event::kStartElement, sourceParser.next());
+    EXPECT_EQ(std::u16string(u"string"), sourceParser.getElementName());
+
+    {
+        ScopedXmlPullParser scopedParser(&sourceParser);
+        EXPECT_EQ(XmlPullParser::Event::kEndElement, scopedParser.next());
+        EXPECT_EQ(std::u16string(u"string"), sourceParser.getElementName());
+
+        EXPECT_EQ(XmlPullParser::Event::kEndDocument, scopedParser.next());
+    }
+
+    EXPECT_EQ(XmlPullParser::Event::kEndElement, sourceParser.next());
+    EXPECT_EQ(std::u16string(u"resources"), sourceParser.getElementName());
+
+    EXPECT_EQ(XmlPullParser::Event::kEndDocument, sourceParser.next());
+}
+
+TEST(ScopedXmlPullParserTest, FinishCurrentElementOnDestruction) {
+    std::stringstream input;
+    input << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl
+          << "<resources><string></string></resources>" << std::endl;
+
+    SourceXmlPullParser sourceParser(input);
+    EXPECT_EQ(XmlPullParser::Event::kStartElement, sourceParser.next());
+    EXPECT_EQ(std::u16string(u"resources"), sourceParser.getElementName());
+
+    EXPECT_EQ(XmlPullParser::Event::kStartElement, sourceParser.next());
+    EXPECT_EQ(std::u16string(u"string"), sourceParser.getElementName());
+
+    {
+        ScopedXmlPullParser scopedParser(&sourceParser);
+        EXPECT_EQ(std::u16string(u"string"), sourceParser.getElementName());
+    }
+
+    EXPECT_EQ(XmlPullParser::Event::kEndElement, sourceParser.next());
+    EXPECT_EQ(std::u16string(u"resources"), sourceParser.getElementName());
+
+    EXPECT_EQ(XmlPullParser::Event::kEndDocument, sourceParser.next());
+}
+
+TEST(ScopedXmlPullParserTest, NestedParsersOperateCorrectly) {
+    std::stringstream input;
+    input << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl
+          << "<resources><string><foo></foo></string></resources>" << std::endl;
+
+    SourceXmlPullParser sourceParser(input);
+    EXPECT_EQ(XmlPullParser::Event::kStartElement, sourceParser.next());
+    EXPECT_EQ(std::u16string(u"resources"), sourceParser.getElementName());
+
+    EXPECT_EQ(XmlPullParser::Event::kStartElement, sourceParser.next());
+    EXPECT_EQ(std::u16string(u"string"), sourceParser.getElementName());
+
+    {
+        ScopedXmlPullParser scopedParser(&sourceParser);
+        EXPECT_EQ(std::u16string(u"string"), scopedParser.getElementName());
+        while (XmlPullParser::isGoodEvent(scopedParser.next())) {
+            if (scopedParser.getEvent() != XmlPullParser::Event::kStartElement) {
+                continue;
+            }
+
+            ScopedXmlPullParser subScopedParser(&scopedParser);
+            EXPECT_EQ(std::u16string(u"foo"), subScopedParser.getElementName());
+        }
+    }
+
+    EXPECT_EQ(XmlPullParser::Event::kEndElement, sourceParser.next());
+    EXPECT_EQ(std::u16string(u"resources"), sourceParser.getElementName());
+
+    EXPECT_EQ(XmlPullParser::Event::kEndDocument, sourceParser.next());
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
new file mode 100644
index 0000000..3f156a6
--- /dev/null
+++ b/tools/aapt2/SdkConstants.cpp
@@ -0,0 +1,693 @@
+/*
+ * 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.
+ */
+
+#include <string>
+#include <unordered_map>
+
+namespace aapt {
+
+static const std::unordered_map<std::u16string, size_t> sAttrMap = {
+    { u"marqueeRepeatLimit", 2 },
+    { u"windowNoDisplay", 3 },
+    { u"backgroundDimEnabled", 3 },
+    { u"inputType", 3 },
+    { u"isDefault", 3 },
+    { u"windowDisablePreview", 3 },
+    { u"privateImeOptions", 3 },
+    { u"editorExtras", 3 },
+    { u"settingsActivity", 3 },
+    { u"fastScrollEnabled", 3 },
+    { u"reqTouchScreen", 3 },
+    { u"reqKeyboardType", 3 },
+    { u"reqHardKeyboard", 3 },
+    { u"reqNavigation", 3 },
+    { u"windowSoftInputMode", 3 },
+    { u"imeFullscreenBackground", 3 },
+    { u"noHistory", 3 },
+    { u"headerDividersEnabled", 3 },
+    { u"footerDividersEnabled", 3 },
+    { u"candidatesTextStyleSpans", 3 },
+    { u"smoothScrollbar", 3 },
+    { u"reqFiveWayNav", 3 },
+    { u"keyBackground", 3 },
+    { u"keyTextSize", 3 },
+    { u"labelTextSize", 3 },
+    { u"keyTextColor", 3 },
+    { u"keyPreviewLayout", 3 },
+    { u"keyPreviewOffset", 3 },
+    { u"keyPreviewHeight", 3 },
+    { u"verticalCorrection", 3 },
+    { u"popupLayout", 3 },
+    { u"state_long_pressable", 3 },
+    { u"keyWidth", 3 },
+    { u"keyHeight", 3 },
+    { u"horizontalGap", 3 },
+    { u"verticalGap", 3 },
+    { u"rowEdgeFlags", 3 },
+    { u"codes", 3 },
+    { u"popupKeyboard", 3 },
+    { u"popupCharacters", 3 },
+    { u"keyEdgeFlags", 3 },
+    { u"isModifier", 3 },
+    { u"isSticky", 3 },
+    { u"isRepeatable", 3 },
+    { u"iconPreview", 3 },
+    { u"keyOutputText", 3 },
+    { u"keyLabel", 3 },
+    { u"keyIcon", 3 },
+    { u"keyboardMode", 3 },
+    { u"isScrollContainer", 3 },
+    { u"fillEnabled", 3 },
+    { u"updatePeriodMillis", 3 },
+    { u"initialLayout", 3 },
+    { u"voiceSearchMode", 3 },
+    { u"voiceLanguageModel", 3 },
+    { u"voicePromptText", 3 },
+    { u"voiceLanguage", 3 },
+    { u"voiceMaxResults", 3 },
+    { u"bottomOffset", 3 },
+    { u"topOffset", 3 },
+    { u"allowSingleTap", 3 },
+    { u"handle", 3 },
+    { u"content", 3 },
+    { u"animateOnClick", 3 },
+    { u"configure", 3 },
+    { u"hapticFeedbackEnabled", 3 },
+    { u"innerRadius", 3 },
+    { u"thickness", 3 },
+    { u"sharedUserLabel", 3 },
+    { u"dropDownWidth", 3 },
+    { u"dropDownAnchor", 3 },
+    { u"imeOptions", 3 },
+    { u"imeActionLabel", 3 },
+    { u"imeActionId", 3 },
+    { u"imeExtractEnterAnimation", 3 },
+    { u"imeExtractExitAnimation", 3 },
+    { u"tension", 4 },
+    { u"extraTension", 4 },
+    { u"anyDensity", 4 },
+    { u"searchSuggestThreshold", 4 },
+    { u"includeInGlobalSearch", 4 },
+    { u"onClick", 4 },
+    { u"targetSdkVersion", 4 },
+    { u"maxSdkVersion", 4 },
+    { u"testOnly", 4 },
+    { u"contentDescription", 4 },
+    { u"gestureStrokeWidth", 4 },
+    { u"gestureColor", 4 },
+    { u"uncertainGestureColor", 4 },
+    { u"fadeOffset", 4 },
+    { u"fadeDuration", 4 },
+    { u"gestureStrokeType", 4 },
+    { u"gestureStrokeLengthThreshold", 4 },
+    { u"gestureStrokeSquarenessThreshold", 4 },
+    { u"gestureStrokeAngleThreshold", 4 },
+    { u"eventsInterceptionEnabled", 4 },
+    { u"fadeEnabled", 4 },
+    { u"backupAgent", 4 },
+    { u"allowBackup", 4 },
+    { u"glEsVersion", 4 },
+    { u"queryAfterZeroResults", 4 },
+    { u"dropDownHeight", 4 },
+    { u"smallScreens", 4 },
+    { u"normalScreens", 4 },
+    { u"largeScreens", 4 },
+    { u"progressBarStyleInverse", 4 },
+    { u"progressBarStyleSmallInverse", 4 },
+    { u"progressBarStyleLargeInverse", 4 },
+    { u"searchSettingsDescription", 4 },
+    { u"textColorPrimaryInverseDisableOnly", 4 },
+    { u"autoUrlDetect", 4 },
+    { u"resizeable", 4 },
+    { u"required", 5 },
+    { u"accountType", 5 },
+    { u"contentAuthority", 5 },
+    { u"userVisible", 5 },
+    { u"windowShowWallpaper", 5 },
+    { u"wallpaperOpenEnterAnimation", 5 },
+    { u"wallpaperOpenExitAnimation", 5 },
+    { u"wallpaperCloseEnterAnimation", 5 },
+    { u"wallpaperCloseExitAnimation", 5 },
+    { u"wallpaperIntraOpenEnterAnimation", 5 },
+    { u"wallpaperIntraOpenExitAnimation", 5 },
+    { u"wallpaperIntraCloseEnterAnimation", 5 },
+    { u"wallpaperIntraCloseExitAnimation", 5 },
+    { u"supportsUploading", 5 },
+    { u"killAfterRestore", 5 },
+    { u"restoreNeedsApplication", 5 },
+    { u"smallIcon", 5 },
+    { u"accountPreferences", 5 },
+    { u"textAppearanceSearchResultSubtitle", 5 },
+    { u"textAppearanceSearchResultTitle", 5 },
+    { u"summaryColumn", 5 },
+    { u"detailColumn", 5 },
+    { u"detailSocialSummary", 5 },
+    { u"thumbnail", 5 },
+    { u"detachWallpaper", 5 },
+    { u"finishOnCloseSystemDialogs", 5 },
+    { u"scrollbarFadeDuration", 5 },
+    { u"scrollbarDefaultDelayBeforeFade", 5 },
+    { u"fadeScrollbars", 5 },
+    { u"colorBackgroundCacheHint", 5 },
+    { u"dropDownHorizontalOffset", 5 },
+    { u"dropDownVerticalOffset", 5 },
+    { u"quickContactBadgeStyleWindowSmall", 6 },
+    { u"quickContactBadgeStyleWindowMedium", 6 },
+    { u"quickContactBadgeStyleWindowLarge", 6 },
+    { u"quickContactBadgeStyleSmallWindowSmall", 6 },
+    { u"quickContactBadgeStyleSmallWindowMedium", 6 },
+    { u"quickContactBadgeStyleSmallWindowLarge", 6 },
+    { u"author", 7 },
+    { u"autoStart", 7 },
+    { u"expandableListViewWhiteStyle", 8 },
+    { u"installLocation", 8 },
+    { u"vmSafeMode", 8 },
+    { u"webTextViewStyle", 8 },
+    { u"restoreAnyVersion", 8 },
+    { u"tabStripLeft", 8 },
+    { u"tabStripRight", 8 },
+    { u"tabStripEnabled", 8 },
+    { u"logo", 9 },
+    { u"xlargeScreens", 9 },
+    { u"immersive", 9 },
+    { u"overScrollMode", 9 },
+    { u"overScrollHeader", 9 },
+    { u"overScrollFooter", 9 },
+    { u"filterTouchesWhenObscured", 9 },
+    { u"textSelectHandleLeft", 9 },
+    { u"textSelectHandleRight", 9 },
+    { u"textSelectHandle", 9 },
+    { u"textSelectHandleWindowStyle", 9 },
+    { u"popupAnimationStyle", 9 },
+    { u"screenSize", 9 },
+    { u"screenDensity", 9 },
+    { u"allContactsName", 11 },
+    { u"windowActionBar", 11 },
+    { u"actionBarStyle", 11 },
+    { u"navigationMode", 11 },
+    { u"displayOptions", 11 },
+    { u"subtitle", 11 },
+    { u"customNavigationLayout", 11 },
+    { u"hardwareAccelerated", 11 },
+    { u"measureWithLargestChild", 11 },
+    { u"animateFirstView", 11 },
+    { u"dropDownSpinnerStyle", 11 },
+    { u"actionDropDownStyle", 11 },
+    { u"actionButtonStyle", 11 },
+    { u"showAsAction", 11 },
+    { u"previewImage", 11 },
+    { u"actionModeBackground", 11 },
+    { u"actionModeCloseDrawable", 11 },
+    { u"windowActionModeOverlay", 11 },
+    { u"valueFrom", 11 },
+    { u"valueTo", 11 },
+    { u"valueType", 11 },
+    { u"propertyName", 11 },
+    { u"ordering", 11 },
+    { u"fragment", 11 },
+    { u"windowActionBarOverlay", 11 },
+    { u"fragmentOpenEnterAnimation", 11 },
+    { u"fragmentOpenExitAnimation", 11 },
+    { u"fragmentCloseEnterAnimation", 11 },
+    { u"fragmentCloseExitAnimation", 11 },
+    { u"fragmentFadeEnterAnimation", 11 },
+    { u"fragmentFadeExitAnimation", 11 },
+    { u"actionBarSize", 11 },
+    { u"imeSubtypeLocale", 11 },
+    { u"imeSubtypeMode", 11 },
+    { u"imeSubtypeExtraValue", 11 },
+    { u"splitMotionEvents", 11 },
+    { u"listChoiceBackgroundIndicator", 11 },
+    { u"spinnerMode", 11 },
+    { u"animateLayoutChanges", 11 },
+    { u"actionBarTabStyle", 11 },
+    { u"actionBarTabBarStyle", 11 },
+    { u"actionBarTabTextStyle", 11 },
+    { u"actionOverflowButtonStyle", 11 },
+    { u"actionModeCloseButtonStyle", 11 },
+    { u"titleTextStyle", 11 },
+    { u"subtitleTextStyle", 11 },
+    { u"iconifiedByDefault", 11 },
+    { u"actionLayout", 11 },
+    { u"actionViewClass", 11 },
+    { u"activatedBackgroundIndicator", 11 },
+    { u"state_activated", 11 },
+    { u"listPopupWindowStyle", 11 },
+    { u"popupMenuStyle", 11 },
+    { u"textAppearanceLargePopupMenu", 11 },
+    { u"textAppearanceSmallPopupMenu", 11 },
+    { u"breadCrumbTitle", 11 },
+    { u"breadCrumbShortTitle", 11 },
+    { u"listDividerAlertDialog", 11 },
+    { u"textColorAlertDialogListItem", 11 },
+    { u"loopViews", 11 },
+    { u"dialogTheme", 11 },
+    { u"alertDialogTheme", 11 },
+    { u"dividerVertical", 11 },
+    { u"homeAsUpIndicator", 11 },
+    { u"enterFadeDuration", 11 },
+    { u"exitFadeDuration", 11 },
+    { u"selectableItemBackground", 11 },
+    { u"autoAdvanceViewId", 11 },
+    { u"useIntrinsicSizeAsMinimum", 11 },
+    { u"actionModeCutDrawable", 11 },
+    { u"actionModeCopyDrawable", 11 },
+    { u"actionModePasteDrawable", 11 },
+    { u"textEditPasteWindowLayout", 11 },
+    { u"textEditNoPasteWindowLayout", 11 },
+    { u"textIsSelectable", 11 },
+    { u"windowEnableSplitTouch", 11 },
+    { u"indeterminateProgressStyle", 11 },
+    { u"progressBarPadding", 11 },
+    { u"animationResolution", 11 },
+    { u"state_accelerated", 11 },
+    { u"baseline", 11 },
+    { u"homeLayout", 11 },
+    { u"opacity", 11 },
+    { u"alpha", 11 },
+    { u"transformPivotX", 11 },
+    { u"transformPivotY", 11 },
+    { u"translationX", 11 },
+    { u"translationY", 11 },
+    { u"scaleX", 11 },
+    { u"scaleY", 11 },
+    { u"rotation", 11 },
+    { u"rotationX", 11 },
+    { u"rotationY", 11 },
+    { u"showDividers", 11 },
+    { u"dividerPadding", 11 },
+    { u"borderlessButtonStyle", 11 },
+    { u"dividerHorizontal", 11 },
+    { u"itemPadding", 11 },
+    { u"buttonBarStyle", 11 },
+    { u"buttonBarButtonStyle", 11 },
+    { u"segmentedButtonStyle", 11 },
+    { u"staticWallpaperPreview", 11 },
+    { u"allowParallelSyncs", 11 },
+    { u"isAlwaysSyncable", 11 },
+    { u"verticalScrollbarPosition", 11 },
+    { u"fastScrollAlwaysVisible", 11 },
+    { u"fastScrollThumbDrawable", 11 },
+    { u"fastScrollPreviewBackgroundLeft", 11 },
+    { u"fastScrollPreviewBackgroundRight", 11 },
+    { u"fastScrollTrackDrawable", 11 },
+    { u"fastScrollOverlayPosition", 11 },
+    { u"customTokens", 11 },
+    { u"nextFocusForward", 11 },
+    { u"firstDayOfWeek", 11 },
+    { u"showWeekNumber", 11 },
+    { u"minDate", 11 },
+    { u"maxDate", 11 },
+    { u"shownWeekCount", 11 },
+    { u"selectedWeekBackgroundColor", 11 },
+    { u"focusedMonthDateColor", 11 },
+    { u"unfocusedMonthDateColor", 11 },
+    { u"weekNumberColor", 11 },
+    { u"weekSeparatorLineColor", 11 },
+    { u"selectedDateVerticalBar", 11 },
+    { u"weekDayTextAppearance", 11 },
+    { u"dateTextAppearance", 11 },
+    { u"solidColor", 11 },
+    { u"spinnersShown", 11 },
+    { u"calendarViewShown", 11 },
+    { u"state_multiline", 11 },
+    { u"detailsElementBackground", 11 },
+    { u"textColorHighlightInverse", 11 },
+    { u"textColorLinkInverse", 11 },
+    { u"editTextColor", 11 },
+    { u"editTextBackground", 11 },
+    { u"horizontalScrollViewStyle", 11 },
+    { u"layerType", 11 },
+    { u"alertDialogIcon", 11 },
+    { u"windowMinWidthMajor", 11 },
+    { u"windowMinWidthMinor", 11 },
+    { u"queryHint", 11 },
+    { u"fastScrollTextColor", 11 },
+    { u"largeHeap", 11 },
+    { u"windowCloseOnTouchOutside", 11 },
+    { u"datePickerStyle", 11 },
+    { u"calendarViewStyle", 11 },
+    { u"textEditSidePasteWindowLayout", 11 },
+    { u"textEditSideNoPasteWindowLayout", 11 },
+    { u"actionMenuTextAppearance", 11 },
+    { u"actionMenuTextColor", 11 },
+    { u"textCursorDrawable", 12 },
+    { u"resizeMode", 12 },
+    { u"requiresSmallestWidthDp", 12 },
+    { u"compatibleWidthLimitDp", 12 },
+    { u"largestWidthLimitDp", 12 },
+    { u"state_hovered", 13 },
+    { u"state_drag_can_accept", 13 },
+    { u"state_drag_hovered", 13 },
+    { u"stopWithTask", 13 },
+    { u"switchTextOn", 13 },
+    { u"switchTextOff", 13 },
+    { u"switchPreferenceStyle", 13 },
+    { u"switchTextAppearance", 13 },
+    { u"track", 13 },
+    { u"switchMinWidth", 13 },
+    { u"switchPadding", 13 },
+    { u"thumbTextPadding", 13 },
+    { u"textSuggestionsWindowStyle", 13 },
+    { u"textEditSuggestionItemLayout", 13 },
+    { u"rowCount", 13 },
+    { u"rowOrderPreserved", 13 },
+    { u"columnCount", 13 },
+    { u"columnOrderPreserved", 13 },
+    { u"useDefaultMargins", 13 },
+    { u"alignmentMode", 13 },
+    { u"layout_row", 13 },
+    { u"layout_rowSpan", 13 },
+    { u"layout_columnSpan", 13 },
+    { u"actionModeSelectAllDrawable", 13 },
+    { u"isAuxiliary", 13 },
+    { u"accessibilityEventTypes", 13 },
+    { u"packageNames", 13 },
+    { u"accessibilityFeedbackType", 13 },
+    { u"notificationTimeout", 13 },
+    { u"accessibilityFlags", 13 },
+    { u"canRetrieveWindowContent", 13 },
+    { u"listPreferredItemHeightLarge", 13 },
+    { u"listPreferredItemHeightSmall", 13 },
+    { u"actionBarSplitStyle", 13 },
+    { u"actionProviderClass", 13 },
+    { u"backgroundStacked", 13 },
+    { u"backgroundSplit", 13 },
+    { u"textAllCaps", 13 },
+    { u"colorPressedHighlight", 13 },
+    { u"colorLongPressedHighlight", 13 },
+    { u"colorFocusedHighlight", 13 },
+    { u"colorActivatedHighlight", 13 },
+    { u"colorMultiSelectHighlight", 13 },
+    { u"drawableStart", 13 },
+    { u"drawableEnd", 13 },
+    { u"actionModeStyle", 13 },
+    { u"minResizeWidth", 13 },
+    { u"minResizeHeight", 13 },
+    { u"actionBarWidgetTheme", 13 },
+    { u"uiOptions", 13 },
+    { u"subtypeLocale", 13 },
+    { u"subtypeExtraValue", 13 },
+    { u"actionBarDivider", 13 },
+    { u"actionBarItemBackground", 13 },
+    { u"actionModeSplitBackground", 13 },
+    { u"textAppearanceListItem", 13 },
+    { u"textAppearanceListItemSmall", 13 },
+    { u"targetDescriptions", 13 },
+    { u"directionDescriptions", 13 },
+    { u"overridesImplicitlyEnabledSubtype", 13 },
+    { u"listPreferredItemPaddingLeft", 13 },
+    { u"listPreferredItemPaddingRight", 13 },
+    { u"requiresFadingEdge", 13 },
+    { u"publicKey", 13 },
+    { u"parentActivityName", 16 },
+    { u"isolatedProcess", 16 },
+    { u"importantForAccessibility", 16 },
+    { u"keyboardLayout", 16 },
+    { u"fontFamily", 16 },
+    { u"mediaRouteButtonStyle", 16 },
+    { u"mediaRouteTypes", 16 },
+    { u"supportsRtl", 17 },
+    { u"textDirection", 17 },
+    { u"textAlignment", 17 },
+    { u"layoutDirection", 17 },
+    { u"paddingStart", 17 },
+    { u"paddingEnd", 17 },
+    { u"layout_marginStart", 17 },
+    { u"layout_marginEnd", 17 },
+    { u"layout_toStartOf", 17 },
+    { u"layout_toEndOf", 17 },
+    { u"layout_alignStart", 17 },
+    { u"layout_alignEnd", 17 },
+    { u"layout_alignParentStart", 17 },
+    { u"layout_alignParentEnd", 17 },
+    { u"listPreferredItemPaddingStart", 17 },
+    { u"listPreferredItemPaddingEnd", 17 },
+    { u"singleUser", 17 },
+    { u"presentationTheme", 17 },
+    { u"subtypeId", 17 },
+    { u"initialKeyguardLayout", 17 },
+    { u"widgetCategory", 17 },
+    { u"permissionGroupFlags", 17 },
+    { u"labelFor", 17 },
+    { u"permissionFlags", 17 },
+    { u"checkedTextViewStyle", 17 },
+    { u"showOnLockScreen", 17 },
+    { u"format12Hour", 17 },
+    { u"format24Hour", 17 },
+    { u"timeZone", 17 },
+    { u"mipMap", 18 },
+    { u"mirrorForRtl", 18 },
+    { u"windowOverscan", 18 },
+    { u"requiredForAllUsers", 18 },
+    { u"indicatorStart", 18 },
+    { u"indicatorEnd", 18 },
+    { u"childIndicatorStart", 18 },
+    { u"childIndicatorEnd", 18 },
+    { u"restrictedAccountType", 18 },
+    { u"requiredAccountType", 18 },
+    { u"canRequestTouchExplorationMode", 18 },
+    { u"canRequestEnhancedWebAccessibility", 18 },
+    { u"canRequestFilterKeyEvents", 18 },
+    { u"layoutMode", 18 },
+    { u"keySet", 19 },
+    { u"targetId", 19 },
+    { u"fromScene", 19 },
+    { u"toScene", 19 },
+    { u"transition", 19 },
+    { u"transitionOrdering", 19 },
+    { u"fadingMode", 19 },
+    { u"startDelay", 19 },
+    { u"ssp", 19 },
+    { u"sspPrefix", 19 },
+    { u"sspPattern", 19 },
+    { u"addPrintersActivity", 19 },
+    { u"vendor", 19 },
+    { u"category", 19 },
+    { u"isAsciiCapable", 19 },
+    { u"autoMirrored", 19 },
+    { u"supportsSwitchingToNextInputMethod", 19 },
+    { u"requireDeviceUnlock", 19 },
+    { u"apduServiceBanner", 19 },
+    { u"accessibilityLiveRegion", 19 },
+    { u"windowTranslucentStatus", 19 },
+    { u"windowTranslucentNavigation", 19 },
+    { u"advancedPrintOptionsActivity", 19 },
+    { u"banner", 20 },
+    { u"windowSwipeToDismiss", 20 },
+    { u"isGame", 20 },
+    { u"allowEmbedded", 20 },
+    { u"setupActivity", 20 },
+    { u"fastScrollStyle", 21 },
+    { u"windowContentTransitions", 21 },
+    { u"windowContentTransitionManager", 21 },
+    { u"translationZ", 21 },
+    { u"tintMode", 21 },
+    { u"controlX1", 21 },
+    { u"controlY1", 21 },
+    { u"controlX2", 21 },
+    { u"controlY2", 21 },
+    { u"transitionName", 21 },
+    { u"transitionGroup", 21 },
+    { u"viewportWidth", 21 },
+    { u"viewportHeight", 21 },
+    { u"fillColor", 21 },
+    { u"pathData", 21 },
+    { u"strokeColor", 21 },
+    { u"strokeWidth", 21 },
+    { u"trimPathStart", 21 },
+    { u"trimPathEnd", 21 },
+    { u"trimPathOffset", 21 },
+    { u"strokeLineCap", 21 },
+    { u"strokeLineJoin", 21 },
+    { u"strokeMiterLimit", 21 },
+    { u"colorControlNormal", 21 },
+    { u"colorControlActivated", 21 },
+    { u"colorButtonNormal", 21 },
+    { u"colorControlHighlight", 21 },
+    { u"persistableMode", 21 },
+    { u"titleTextAppearance", 21 },
+    { u"subtitleTextAppearance", 21 },
+    { u"slideEdge", 21 },
+    { u"actionBarTheme", 21 },
+    { u"textAppearanceListItemSecondary", 21 },
+    { u"colorPrimary", 21 },
+    { u"colorPrimaryDark", 21 },
+    { u"colorAccent", 21 },
+    { u"nestedScrollingEnabled", 21 },
+    { u"windowEnterTransition", 21 },
+    { u"windowExitTransition", 21 },
+    { u"windowSharedElementEnterTransition", 21 },
+    { u"windowSharedElementExitTransition", 21 },
+    { u"windowAllowReturnTransitionOverlap", 21 },
+    { u"windowAllowEnterTransitionOverlap", 21 },
+    { u"sessionService", 21 },
+    { u"stackViewStyle", 21 },
+    { u"switchStyle", 21 },
+    { u"elevation", 21 },
+    { u"excludeId", 21 },
+    { u"excludeClass", 21 },
+    { u"hideOnContentScroll", 21 },
+    { u"actionOverflowMenuStyle", 21 },
+    { u"documentLaunchMode", 21 },
+    { u"maxRecents", 21 },
+    { u"autoRemoveFromRecents", 21 },
+    { u"stateListAnimator", 21 },
+    { u"toId", 21 },
+    { u"fromId", 21 },
+    { u"reversible", 21 },
+    { u"splitTrack", 21 },
+    { u"targetName", 21 },
+    { u"excludeName", 21 },
+    { u"matchOrder", 21 },
+    { u"windowDrawsSystemBarBackgrounds", 21 },
+    { u"statusBarColor", 21 },
+    { u"navigationBarColor", 21 },
+    { u"contentInsetStart", 21 },
+    { u"contentInsetEnd", 21 },
+    { u"contentInsetLeft", 21 },
+    { u"contentInsetRight", 21 },
+    { u"paddingMode", 21 },
+    { u"layout_rowWeight", 21 },
+    { u"layout_columnWeight", 21 },
+    { u"translateX", 21 },
+    { u"translateY", 21 },
+    { u"selectableItemBackgroundBorderless", 21 },
+    { u"elegantTextHeight", 21 },
+    { u"searchKeyphraseId", 21 },
+    { u"searchKeyphrase", 21 },
+    { u"searchKeyphraseSupportedLocales", 21 },
+    { u"windowTransitionBackgroundFadeDuration", 21 },
+    { u"overlapAnchor", 21 },
+    { u"progressTint", 21 },
+    { u"progressTintMode", 21 },
+    { u"progressBackgroundTint", 21 },
+    { u"progressBackgroundTintMode", 21 },
+    { u"secondaryProgressTint", 21 },
+    { u"secondaryProgressTintMode", 21 },
+    { u"indeterminateTint", 21 },
+    { u"indeterminateTintMode", 21 },
+    { u"backgroundTint", 21 },
+    { u"backgroundTintMode", 21 },
+    { u"foregroundTint", 21 },
+    { u"foregroundTintMode", 21 },
+    { u"buttonTint", 21 },
+    { u"buttonTintMode", 21 },
+    { u"thumbTint", 21 },
+    { u"thumbTintMode", 21 },
+    { u"fullBackupOnly", 21 },
+    { u"propertyXName", 21 },
+    { u"propertyYName", 21 },
+    { u"relinquishTaskIdentity", 21 },
+    { u"tileModeX", 21 },
+    { u"tileModeY", 21 },
+    { u"actionModeShareDrawable", 21 },
+    { u"actionModeFindDrawable", 21 },
+    { u"actionModeWebSearchDrawable", 21 },
+    { u"transitionVisibilityMode", 21 },
+    { u"minimumHorizontalAngle", 21 },
+    { u"minimumVerticalAngle", 21 },
+    { u"maximumAngle", 21 },
+    { u"searchViewStyle", 21 },
+    { u"closeIcon", 21 },
+    { u"goIcon", 21 },
+    { u"searchIcon", 21 },
+    { u"voiceIcon", 21 },
+    { u"commitIcon", 21 },
+    { u"suggestionRowLayout", 21 },
+    { u"queryBackground", 21 },
+    { u"submitBackground", 21 },
+    { u"buttonBarPositiveButtonStyle", 21 },
+    { u"buttonBarNeutralButtonStyle", 21 },
+    { u"buttonBarNegativeButtonStyle", 21 },
+    { u"popupElevation", 21 },
+    { u"actionBarPopupTheme", 21 },
+    { u"multiArch", 21 },
+    { u"touchscreenBlocksFocus", 21 },
+    { u"windowElevation", 21 },
+    { u"launchTaskBehindTargetAnimation", 21 },
+    { u"launchTaskBehindSourceAnimation", 21 },
+    { u"restrictionType", 21 },
+    { u"dayOfWeekBackground", 21 },
+    { u"dayOfWeekTextAppearance", 21 },
+    { u"headerMonthTextAppearance", 21 },
+    { u"headerDayOfMonthTextAppearance", 21 },
+    { u"headerYearTextAppearance", 21 },
+    { u"yearListItemTextAppearance", 21 },
+    { u"yearListSelectorColor", 21 },
+    { u"calendarTextColor", 21 },
+    { u"recognitionService", 21 },
+    { u"timePickerStyle", 21 },
+    { u"timePickerDialogTheme", 21 },
+    { u"headerTimeTextAppearance", 21 },
+    { u"headerAmPmTextAppearance", 21 },
+    { u"numbersTextColor", 21 },
+    { u"numbersBackgroundColor", 21 },
+    { u"numbersSelectorColor", 21 },
+    { u"amPmTextColor", 21 },
+    { u"amPmBackgroundColor", 21 },
+    { u"searchKeyphraseRecognitionFlags", 21 },
+    { u"checkMarkTint", 21 },
+    { u"checkMarkTintMode", 21 },
+    { u"popupTheme", 21 },
+    { u"toolbarStyle", 21 },
+    { u"windowClipToOutline", 21 },
+    { u"datePickerDialogTheme", 21 },
+    { u"showText", 21 },
+    { u"windowReturnTransition", 21 },
+    { u"windowReenterTransition", 21 },
+    { u"windowSharedElementReturnTransition", 21 },
+    { u"windowSharedElementReenterTransition", 21 },
+    { u"resumeWhilePausing", 21 },
+    { u"datePickerMode", 21 },
+    { u"timePickerMode", 21 },
+    { u"inset", 21 },
+    { u"letterSpacing", 21 },
+    { u"fontFeatureSettings", 21 },
+    { u"outlineProvider", 21 },
+    { u"contentAgeHint", 21 },
+    { u"country", 21 },
+    { u"windowSharedElementsUseOverlay", 21 },
+    { u"reparent", 21 },
+    { u"reparentWithOverlay", 21 },
+    { u"ambientShadowAlpha", 21 },
+    { u"spotShadowAlpha", 21 },
+    { u"navigationIcon", 21 },
+    { u"navigationContentDescription", 21 },
+    { u"fragmentExitTransition", 21 },
+    { u"fragmentEnterTransition", 21 },
+    { u"fragmentSharedElementEnterTransition", 21 },
+    { u"fragmentReturnTransition", 21 },
+    { u"fragmentSharedElementReturnTransition", 21 },
+    { u"fragmentReenterTransition", 21 },
+    { u"fragmentAllowEnterTransitionOverlap", 21 },
+    { u"fragmentAllowReturnTransitionOverlap", 21 },
+    { u"patternPathData", 21 },
+    { u"strokeAlpha", 21 },
+    { u"fillAlpha", 21 },
+    { u"windowActivityTransitions", 21 },
+    { u"colorEdgeEffect", 21 }
+};
+
+size_t findAttributeSdkLevel(const std::u16string& name) {
+    auto iter = sAttrMap.find(name);
+    if (iter != sAttrMap.end()) {
+        return iter->second;
+    }
+    return 0;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
new file mode 100644
index 0000000..469c355
--- /dev/null
+++ b/tools/aapt2/SdkConstants.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_SDK_CONSTANTS_H
+#define AAPT_SDK_CONSTANTS_H
+
+#include "Resource.h"
+
+#include <string>
+
+namespace aapt {
+
+enum {
+    SDK_CUPCAKE = 3,
+    SDK_DONUT = 4,
+    SDK_ECLAIR = 5,
+    SDK_ECLAIR_0_1 = 6,
+    SDK_ECLAIR_MR1 = 7,
+    SDK_FROYO = 8,
+    SDK_GINGERBREAD = 9,
+    SDK_GINGERBREAD_MR1 = 10,
+    SDK_HONEYCOMB = 11,
+    SDK_HONEYCOMB_MR1 = 12,
+    SDK_HONEYCOMB_MR2 = 13,
+    SDK_ICE_CREAM_SANDWICH = 14,
+    SDK_ICE_CREAM_SANDWICH_MR1 = 15,
+    SDK_JELLY_BEAN = 16,
+    SDK_JELLY_BEAN_MR1 = 17,
+    SDK_JELLY_BEAN_MR2 = 18,
+    SDK_KITKAT = 19,
+    SDK_KITKAT_WATCH = 20,
+    SDK_LOLLIPOP = 21,
+    SDK_LOLLIPOP_MR1 = 22,
+};
+
+size_t findAttributeSdkLevel(const std::u16string& name);
+
+} // namespace aapt
+
+#endif // AAPT_SDK_CONSTANTS_H
diff --git a/tools/aapt2/Source.h b/tools/aapt2/Source.h
new file mode 100644
index 0000000..10c75aa
--- /dev/null
+++ b/tools/aapt2/Source.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_SOURCE_H
+#define AAPT_SOURCE_H
+
+#include <ostream>
+#include <string>
+
+namespace aapt {
+
+struct SourceLineColumn;
+struct SourceLine;
+
+/**
+ * Represents a file on disk. Used for logging and
+ * showing errors.
+ */
+struct Source {
+    std::string path;
+
+    inline SourceLine line(size_t line) const;
+};
+
+/**
+ * Represents a file on disk and a line number in that file.
+ * Used for logging and showing errors.
+ */
+struct SourceLine {
+    std::string path;
+    size_t line;
+
+    inline SourceLineColumn column(size_t column) const;
+};
+
+/**
+ * Represents a file on disk and a line:column number in that file.
+ * Used for logging and showing errors.
+ */
+struct SourceLineColumn {
+    std::string path;
+    size_t line;
+    size_t column;
+};
+
+//
+// Implementations
+//
+
+SourceLine Source::line(size_t line) const {
+    return SourceLine{ path, line };
+}
+
+SourceLineColumn SourceLine::column(size_t column) const {
+    return SourceLineColumn{ path, line, column };
+}
+
+inline ::std::ostream& operator<<(::std::ostream& out, const Source& source) {
+    return out << source.path;
+}
+
+inline ::std::ostream& operator<<(::std::ostream& out, const SourceLine& source) {
+    return out << source.path << ":" << source.line;
+}
+
+inline ::std::ostream& operator<<(::std::ostream& out, const SourceLineColumn& source) {
+    return out << source.path << ":" << source.line << ":" << source.column;
+}
+
+} // namespace aapt
+
+#endif // AAPT_SOURCE_H
diff --git a/tools/aapt2/SourceXmlPullParser.cpp b/tools/aapt2/SourceXmlPullParser.cpp
new file mode 100644
index 0000000..cb6a3c0
--- /dev/null
+++ b/tools/aapt2/SourceXmlPullParser.cpp
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ */
+
+#include <iostream>
+#include <string>
+
+#include "SourceXmlPullParser.h"
+#include "Util.h"
+
+namespace aapt {
+
+constexpr char kXmlNamespaceSep = 1;
+
+SourceXmlPullParser::SourceXmlPullParser(std::istream& in) : mIn(in), mEmpty(), mDepth(0) {
+    mParser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
+    XML_SetUserData(mParser, this);
+    XML_SetElementHandler(mParser, startElementHandler, endElementHandler);
+    XML_SetNamespaceDeclHandler(mParser, startNamespaceHandler, endNamespaceHandler);
+    XML_SetCharacterDataHandler(mParser, characterDataHandler);
+    XML_SetCommentHandler(mParser, commentDataHandler);
+    mEventQueue.push(EventData{ Event::kStartDocument, 0, mDepth++ });
+}
+
+SourceXmlPullParser::~SourceXmlPullParser() {
+    XML_ParserFree(mParser);
+}
+
+SourceXmlPullParser::Event SourceXmlPullParser::next() {
+    const Event currentEvent = getEvent();
+    if (currentEvent == Event::kBadDocument || currentEvent == Event::kEndDocument) {
+        return currentEvent;
+    }
+
+    mEventQueue.pop();
+    while (mEventQueue.empty()) {
+        mIn.read(mBuffer, sizeof(mBuffer) / sizeof(*mBuffer));
+
+        const bool done = mIn.eof();
+        if (mIn.bad() && !done) {
+            mLastError = strerror(errno);
+            mEventQueue.push(EventData{ Event::kBadDocument });
+            continue;
+        }
+
+        if (XML_Parse(mParser, mBuffer, mIn.gcount(), done) == XML_STATUS_ERROR) {
+            mLastError = XML_ErrorString(XML_GetErrorCode(mParser));
+            mEventQueue.push(EventData{ Event::kBadDocument });
+            continue;
+        }
+
+        if (done) {
+            mEventQueue.push(EventData{ Event::kEndDocument, 0, 0 });
+        }
+    }
+
+    return getEvent();
+}
+
+SourceXmlPullParser::Event SourceXmlPullParser::getEvent() const {
+    return mEventQueue.front().event;
+}
+
+const std::string& SourceXmlPullParser::getLastError() const {
+    return mLastError;
+}
+
+const std::u16string& SourceXmlPullParser::getComment() const {
+    return mEventQueue.front().comment;
+}
+
+size_t SourceXmlPullParser::getLineNumber() const {
+    return mEventQueue.front().lineNumber;
+}
+
+size_t SourceXmlPullParser::getDepth() const {
+    return mEventQueue.front().depth;
+}
+
+const std::u16string& SourceXmlPullParser::getText() const {
+    if (getEvent() != Event::kText) {
+        return mEmpty;
+    }
+    return mEventQueue.front().data1;
+}
+
+const std::u16string& SourceXmlPullParser::getNamespacePrefix() const {
+    const Event currentEvent = getEvent();
+    if (currentEvent != Event::kStartNamespace && currentEvent != Event::kEndNamespace) {
+        return mEmpty;
+    }
+    return mEventQueue.front().data1;
+}
+
+const std::u16string& SourceXmlPullParser::getNamespaceUri() const {
+    const Event currentEvent = getEvent();
+    if (currentEvent != Event::kStartNamespace && currentEvent != Event::kEndNamespace) {
+        return mEmpty;
+    }
+    return mEventQueue.front().data2;
+}
+
+const std::u16string& SourceXmlPullParser::getElementNamespace() const {
+    const Event currentEvent = getEvent();
+    if (currentEvent != Event::kStartElement && currentEvent != Event::kEndElement) {
+        return mEmpty;
+    }
+    return mEventQueue.front().data1;
+}
+
+const std::u16string& SourceXmlPullParser::getElementName() const {
+    const Event currentEvent = getEvent();
+    if (currentEvent != Event::kStartElement && currentEvent != Event::kEndElement) {
+        return mEmpty;
+    }
+    return mEventQueue.front().data2;
+}
+
+XmlPullParser::const_iterator SourceXmlPullParser::beginAttributes() const {
+    return mEventQueue.front().attributes.begin();
+}
+
+XmlPullParser::const_iterator SourceXmlPullParser::endAttributes() const {
+    return mEventQueue.front().attributes.end();
+}
+
+size_t SourceXmlPullParser::getAttributeCount() const {
+    if (getEvent() != Event::kStartElement) {
+        return 0;
+    }
+    return mEventQueue.front().attributes.size();
+}
+
+/**
+ * Extracts the namespace and name of an expanded element or attribute name.
+ */
+static void splitName(const char* name, std::u16string& outNs, std::u16string& outName) {
+    const char* p = name;
+    while (*p != 0 && *p != kXmlNamespaceSep) {
+        p++;
+    }
+
+    if (*p == 0) {
+        outNs = std::u16string();
+        outName = util::utf8ToUtf16(name);
+    } else {
+        outNs = util::utf8ToUtf16(StringPiece(name, (p - name)));
+        outName = util::utf8ToUtf16(p + 1);
+    }
+}
+
+void XMLCALL SourceXmlPullParser::startNamespaceHandler(void* userData, const char* prefix,
+        const char* uri) {
+    SourceXmlPullParser* parser = reinterpret_cast<SourceXmlPullParser*>(userData);
+    std::u16string namespaceUri = uri != nullptr ? util::utf8ToUtf16(uri) : std::u16string();
+    parser->mNamespaceUris.push(namespaceUri);
+    parser->mEventQueue.push(EventData{
+            Event::kStartNamespace,
+            XML_GetCurrentLineNumber(parser->mParser),
+            parser->mDepth++,
+            prefix != nullptr ? util::utf8ToUtf16(prefix) : std::u16string(),
+            namespaceUri
+    });
+}
+
+void XMLCALL SourceXmlPullParser::startElementHandler(void* userData, const char* name,
+        const char** attrs) {
+    SourceXmlPullParser* parser = reinterpret_cast<SourceXmlPullParser*>(userData);
+
+    EventData data = {
+            Event::kStartElement, XML_GetCurrentLineNumber(parser->mParser), parser->mDepth++
+    };
+    splitName(name, data.data1, data.data2);
+
+    while (*attrs) {
+        Attribute attribute;
+        splitName(*attrs++, attribute.namespaceUri, attribute.name);
+        attribute.value = util::utf8ToUtf16(*attrs++);
+
+        // Insert in sorted order.
+        auto iter = std::lower_bound(data.attributes.begin(), data.attributes.end(), attribute);
+        data.attributes.insert(iter, std::move(attribute));
+    }
+
+    // Move the structure into the queue (no copy).
+    parser->mEventQueue.push(std::move(data));
+}
+
+void XMLCALL SourceXmlPullParser::characterDataHandler(void* userData, const char* s, int len) {
+    SourceXmlPullParser* parser = reinterpret_cast<SourceXmlPullParser*>(userData);
+
+    parser->mEventQueue.push(EventData{
+            Event::kText,
+            XML_GetCurrentLineNumber(parser->mParser),
+            parser->mDepth,
+            util::utf8ToUtf16(StringPiece(s, len))
+    });
+}
+
+void XMLCALL SourceXmlPullParser::endElementHandler(void* userData, const char* name) {
+    SourceXmlPullParser* parser = reinterpret_cast<SourceXmlPullParser*>(userData);
+
+    EventData data = {
+            Event::kEndElement, XML_GetCurrentLineNumber(parser->mParser), --(parser->mDepth)
+    };
+    splitName(name, data.data1, data.data2);
+
+    // Move the data into the queue (no copy).
+    parser->mEventQueue.push(std::move(data));
+}
+
+void XMLCALL SourceXmlPullParser::endNamespaceHandler(void* userData, const char* prefix) {
+    SourceXmlPullParser* parser = reinterpret_cast<SourceXmlPullParser*>(userData);
+
+    parser->mEventQueue.push(EventData{
+            Event::kEndNamespace,
+            XML_GetCurrentLineNumber(parser->mParser),
+            --(parser->mDepth),
+            prefix != nullptr ? util::utf8ToUtf16(prefix) : std::u16string(),
+            parser->mNamespaceUris.top()
+    });
+    parser->mNamespaceUris.pop();
+}
+
+void XMLCALL SourceXmlPullParser::commentDataHandler(void* userData, const char* comment) {
+    SourceXmlPullParser* parser = reinterpret_cast<SourceXmlPullParser*>(userData);
+
+    parser->mEventQueue.push(EventData{
+            Event::kComment,
+            XML_GetCurrentLineNumber(parser->mParser),
+            parser->mDepth,
+            util::utf8ToUtf16(comment)
+    });
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/SourceXmlPullParser.h b/tools/aapt2/SourceXmlPullParser.h
new file mode 100644
index 0000000..ba904ba
--- /dev/null
+++ b/tools/aapt2/SourceXmlPullParser.h
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_SOURCE_XML_PULL_PARSER_H
+#define AAPT_SOURCE_XML_PULL_PARSER_H
+
+#include <istream>
+#include <libexpat/expat.h>
+#include <queue>
+#include <stack>
+#include <string>
+#include <vector>
+
+#include "XmlPullParser.h"
+
+namespace aapt {
+
+class SourceXmlPullParser : public XmlPullParser {
+public:
+    SourceXmlPullParser(std::istream& in);
+    SourceXmlPullParser(const SourceXmlPullParser& rhs) = delete;
+    ~SourceXmlPullParser();
+
+    Event getEvent() const;
+    const std::string& getLastError() const;
+    Event next();
+
+    const std::u16string& getComment() const;
+    size_t getLineNumber() const;
+    size_t getDepth() const;
+
+    const std::u16string& getText() const;
+
+    const std::u16string& getNamespacePrefix() const;
+    const std::u16string& getNamespaceUri() const;
+
+    const std::u16string& getElementNamespace() const;
+    const std::u16string& getElementName() const;
+
+    const_iterator beginAttributes() const;
+    const_iterator endAttributes() const;
+    size_t getAttributeCount() const;
+
+private:
+    static void XMLCALL startNamespaceHandler(void* userData, const char* prefix, const char* uri);
+    static void XMLCALL startElementHandler(void* userData, const char* name, const char** attrs);
+    static void XMLCALL characterDataHandler(void* userData, const char* s, int len);
+    static void XMLCALL endElementHandler(void* userData, const char* name);
+    static void XMLCALL endNamespaceHandler(void* userData, const char* prefix);
+    static void XMLCALL commentDataHandler(void* userData, const char* comment);
+
+    struct EventData {
+        Event event;
+        size_t lineNumber;
+        size_t depth;
+        std::u16string data1;
+        std::u16string data2;
+        std::u16string comment;
+        std::vector<Attribute> attributes;
+    };
+
+    std::istream& mIn;
+    XML_Parser mParser;
+    char mBuffer[16384];
+    std::queue<EventData> mEventQueue;
+    std::string mLastError;
+    const std::u16string mEmpty;
+    size_t mDepth;
+    std::stack<std::u16string> mNamespaceUris;
+};
+
+} // namespace aapt
+
+#endif // AAPT_SOURCE_XML_PULL_PARSER_H
diff --git a/tools/aapt2/StringPiece.h b/tools/aapt2/StringPiece.h
new file mode 100644
index 0000000..e2a1597
--- /dev/null
+++ b/tools/aapt2/StringPiece.h
@@ -0,0 +1,232 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_STRING_PIECE_H
+#define AAPT_STRING_PIECE_H
+
+#include <ostream>
+#include <string>
+#include <utils/String8.h>
+#include <utils/Unicode.h>
+
+namespace aapt {
+
+/**
+ * Read only wrapper around basic C strings.
+ * Prevents excessive copying.
+ *
+ * WARNING: When creating from std::basic_string<>, moving the original
+ * std::basic_string<> will invalidate the data held in a BasicStringPiece<>.
+ * BasicStringPiece<> should only be used transitively.
+ */
+template <typename TChar>
+class BasicStringPiece {
+public:
+    using const_iterator = const TChar*;
+
+    BasicStringPiece();
+    BasicStringPiece(const BasicStringPiece<TChar>& str);
+    BasicStringPiece(const std::basic_string<TChar>& str);
+    BasicStringPiece(const TChar* str);
+    BasicStringPiece(const TChar* str, size_t len);
+
+    BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs);
+    BasicStringPiece<TChar>& assign(const TChar* str, size_t len);
+
+    BasicStringPiece<TChar> substr(size_t start, size_t len) const;
+    BasicStringPiece<TChar> substr(BasicStringPiece<TChar>::const_iterator begin,
+                                   BasicStringPiece<TChar>::const_iterator end) const;
+
+    const TChar* data() const;
+    size_t length() const;
+    size_t size() const;
+    bool empty() const;
+    std::basic_string<TChar> toString() const;
+
+    int compare(const BasicStringPiece<TChar>& rhs) const;
+    bool operator<(const BasicStringPiece<TChar>& rhs) const;
+    bool operator>(const BasicStringPiece<TChar>& rhs) const;
+    bool operator==(const BasicStringPiece<TChar>& rhs) const;
+    bool operator!=(const BasicStringPiece<TChar>& rhs) const;
+
+    const_iterator begin() const;
+    const_iterator end() const;
+
+private:
+    const TChar* mData;
+    size_t mLength;
+};
+
+using StringPiece = BasicStringPiece<char>;
+using StringPiece16 = BasicStringPiece<char16_t>;
+
+//
+// BasicStringPiece implementation.
+//
+
+template <typename TChar>
+inline BasicStringPiece<TChar>::BasicStringPiece() : mData(nullptr) , mLength(0) {
+}
+
+template <typename TChar>
+inline BasicStringPiece<TChar>::BasicStringPiece(const BasicStringPiece<TChar>& str) :
+        mData(str.mData), mLength(str.mLength) {
+}
+
+template <typename TChar>
+inline BasicStringPiece<TChar>::BasicStringPiece(const std::basic_string<TChar>& str) :
+        mData(str.data()), mLength(str.length()) {
+}
+
+template <>
+inline BasicStringPiece<char>::BasicStringPiece(const char* str) :
+        mData(str), mLength(str != nullptr ? strlen(str) : 0) {
+}
+
+template <>
+inline BasicStringPiece<char16_t>::BasicStringPiece(const char16_t* str) :
+        mData(str), mLength(str != nullptr ? strlen16(str) : 0) {
+}
+
+template <typename TChar>
+inline BasicStringPiece<TChar>::BasicStringPiece(const TChar* str, size_t len) :
+        mData(str), mLength(len) {
+}
+
+template <typename TChar>
+inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::operator=(
+        const BasicStringPiece<TChar>& rhs) {
+    mData = rhs.mData;
+    mLength = rhs.mLength;
+    return *this;
+}
+
+template <typename TChar>
+inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(const TChar* str, size_t len) {
+    mData = str;
+    mLength = len;
+    return *this;
+}
+
+
+template <typename TChar>
+inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(size_t start, size_t len) const {
+    if (start + len > mLength) {
+        return BasicStringPiece<TChar>();
+    }
+    return BasicStringPiece<TChar>(mData + start, len);
+}
+
+template <typename TChar>
+inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(
+        BasicStringPiece<TChar>::const_iterator begin,
+        BasicStringPiece<TChar>::const_iterator end) const {
+    return BasicStringPiece<TChar>(begin, end - begin);
+}
+
+template <typename TChar>
+inline const TChar* BasicStringPiece<TChar>::data() const {
+    return mData;
+}
+
+template <typename TChar>
+inline size_t BasicStringPiece<TChar>::length() const {
+    return mLength;
+}
+
+template <typename TChar>
+inline size_t BasicStringPiece<TChar>::size() const {
+    return mLength;
+}
+
+template <typename TChar>
+inline bool BasicStringPiece<TChar>::empty() const {
+    return mLength == 0;
+}
+
+template <typename TChar>
+inline std::basic_string<TChar> BasicStringPiece<TChar>::toString() const {
+    return std::basic_string<TChar>(mData, mLength);
+}
+
+template <>
+inline int BasicStringPiece<char>::compare(const BasicStringPiece<char>& rhs) const {
+    const char nullStr = '\0';
+    const char* b1 = mData != nullptr ? mData : &nullStr;
+    const char* e1 = b1 + mLength;
+    const char* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
+    const char* e2 = b2 + rhs.mLength;
+
+    while (b1 < e1 && b2 < e2) {
+        const int d = static_cast<int>(*b1++) - static_cast<int>(*b2++);
+        if (d) {
+            return d;
+        }
+    }
+    return static_cast<int>(mLength - rhs.mLength);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char16_t>& str) {
+    android::String8 utf8(str.data(), str.size());
+    return out.write(utf8.string(), utf8.size());
+}
+
+
+template <>
+inline int BasicStringPiece<char16_t>::compare(const BasicStringPiece<char16_t>& rhs) const {
+    const char16_t nullStr = u'\0';
+    const char16_t* b1 = mData != nullptr ? mData : &nullStr;
+    const char16_t* b2 = rhs.mData != nullptr ? rhs.mData : &nullStr;
+    return strzcmp16(b1, mLength, b2, rhs.mLength);
+}
+
+template <typename TChar>
+inline bool BasicStringPiece<TChar>::operator<(const BasicStringPiece<TChar>& rhs) const {
+    return compare(rhs) < 0;
+}
+
+template <typename TChar>
+inline bool BasicStringPiece<TChar>::operator>(const BasicStringPiece<TChar>& rhs) const {
+    return compare(rhs) > 0;
+}
+
+template <typename TChar>
+inline bool BasicStringPiece<TChar>::operator==(const BasicStringPiece<TChar>& rhs) const {
+    return compare(rhs) == 0;
+}
+
+template <typename TChar>
+inline bool BasicStringPiece<TChar>::operator!=(const BasicStringPiece<TChar>& rhs) const {
+    return compare(rhs) != 0;
+}
+
+template <typename TChar>
+inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::begin() const {
+    return mData;
+}
+
+template <typename TChar>
+inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::end() const {
+    return mData + mLength;
+}
+
+inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) {
+    return out.write(str.data(), str.size());
+}
+
+} // namespace aapt
+
+#endif // AAPT_STRING_PIECE_H
diff --git a/tools/aapt2/StringPiece_test.cpp b/tools/aapt2/StringPiece_test.cpp
new file mode 100644
index 0000000..43f7a37
--- /dev/null
+++ b/tools/aapt2/StringPiece_test.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#include <algorithm>
+#include <gtest/gtest.h>
+#include <string>
+#include <vector>
+
+#include "StringPiece.h"
+
+namespace aapt {
+
+TEST(StringPieceTest, CompareNonNullTerminatedPiece) {
+    StringPiece a("hello world", 5);
+    StringPiece b("hello moon", 5);
+    EXPECT_EQ(a, b);
+
+    StringPiece16 a16(u"hello world", 5);
+    StringPiece16 b16(u"hello moon", 5);
+    EXPECT_EQ(a16, b16);
+}
+
+TEST(StringPieceTest, PiecesHaveCorrectSortOrder) {
+    std::u16string testing(u"testing");
+    std::u16string banana(u"banana");
+    std::u16string car(u"car");
+
+    EXPECT_TRUE(StringPiece16(testing) > banana);
+    EXPECT_TRUE(StringPiece16(testing) > car);
+    EXPECT_TRUE(StringPiece16(banana) < testing);
+    EXPECT_TRUE(StringPiece16(banana) < car);
+    EXPECT_TRUE(StringPiece16(car) < testing);
+    EXPECT_TRUE(StringPiece16(car) > banana);
+}
+
+TEST(StringPieceTest, PiecesHaveCorrectSortOrderUtf8) {
+    std::string testing("testing");
+    std::string banana("banana");
+    std::string car("car");
+
+    EXPECT_TRUE(StringPiece(testing) > banana);
+    EXPECT_TRUE(StringPiece(testing) > car);
+    EXPECT_TRUE(StringPiece(banana) < testing);
+    EXPECT_TRUE(StringPiece(banana) < car);
+    EXPECT_TRUE(StringPiece(car) < testing);
+    EXPECT_TRUE(StringPiece(car) > banana);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp
new file mode 100644
index 0000000..b159a00
--- /dev/null
+++ b/tools/aapt2/StringPool.cpp
@@ -0,0 +1,348 @@
+/*
+ * 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.
+ */
+
+#include "BigBuffer.h"
+#include "StringPiece.h"
+#include "StringPool.h"
+#include "Util.h"
+
+#include <algorithm>
+#include <androidfw/ResourceTypes.h>
+#include <memory>
+#include <string>
+
+namespace aapt {
+
+StringPool::Ref::Ref() : mEntry(nullptr) {
+}
+
+StringPool::Ref::Ref(const StringPool::Ref& rhs) : mEntry(rhs.mEntry) {
+    if (mEntry != nullptr) {
+        mEntry->ref++;
+    }
+}
+
+StringPool::Ref::Ref(StringPool::Entry* entry) : mEntry(entry) {
+    if (mEntry != nullptr) {
+        mEntry->ref++;
+    }
+}
+
+StringPool::Ref::~Ref() {
+    if (mEntry != nullptr) {
+        mEntry->ref--;
+    }
+}
+
+StringPool::Ref& StringPool::Ref::operator=(const StringPool::Ref& rhs) {
+    if (rhs.mEntry != nullptr) {
+        rhs.mEntry->ref++;
+    }
+
+    if (mEntry != nullptr) {
+        mEntry->ref--;
+    }
+    mEntry = rhs.mEntry;
+    return *this;
+}
+
+const std::u16string* StringPool::Ref::operator->() const {
+    return &mEntry->value;
+}
+
+const std::u16string& StringPool::Ref::operator*() const {
+    return mEntry->value;
+}
+
+size_t StringPool::Ref::getIndex() const {
+    return mEntry->index;
+}
+
+const StringPool::Context& StringPool::Ref::getContext() const {
+    return mEntry->context;
+}
+
+StringPool::StyleRef::StyleRef() : mEntry(nullptr) {
+}
+
+StringPool::StyleRef::StyleRef(const StringPool::StyleRef& rhs) : mEntry(rhs.mEntry) {
+    if (mEntry != nullptr) {
+        mEntry->ref++;
+    }
+}
+
+StringPool::StyleRef::StyleRef(StringPool::StyleEntry* entry) : mEntry(entry) {
+    if (mEntry != nullptr) {
+        mEntry->ref++;
+    }
+}
+
+StringPool::StyleRef::~StyleRef() {
+    if (mEntry != nullptr) {
+        mEntry->ref--;
+    }
+}
+
+StringPool::StyleRef& StringPool::StyleRef::operator=(const StringPool::StyleRef& rhs) {
+    if (rhs.mEntry != nullptr) {
+        rhs.mEntry->ref++;
+    }
+
+    if (mEntry != nullptr) {
+        mEntry->ref--;
+    }
+    mEntry = rhs.mEntry;
+    return *this;
+}
+
+const StringPool::StyleEntry* StringPool::StyleRef::operator->() const {
+    return mEntry;
+}
+
+const StringPool::StyleEntry& StringPool::StyleRef::operator*() const {
+    return *mEntry;
+}
+
+size_t StringPool::StyleRef::getIndex() const {
+    return mEntry->str.getIndex();
+}
+
+const StringPool::Context& StringPool::StyleRef::getContext() const {
+    return mEntry->str.getContext();
+}
+
+StringPool::Ref StringPool::makeRef(const StringPiece16& str) {
+    return makeRefImpl(str, Context{}, true);
+}
+
+StringPool::Ref StringPool::makeRef(const StringPiece16& str, const Context& context) {
+    return makeRefImpl(str, context, true);
+}
+
+StringPool::Ref StringPool::makeRefImpl(const StringPiece16& str, const Context& context,
+        bool unique) {
+    if (unique) {
+        auto iter = mIndexedStrings.find(str);
+        if (iter != std::end(mIndexedStrings)) {
+            return Ref(iter->second);
+        }
+    }
+
+    Entry* entry = new Entry();
+    entry->value = str.toString();
+    entry->context = context;
+    entry->index = mStrings.size();
+    entry->ref = 0;
+    mStrings.emplace_back(entry);
+    mIndexedStrings.insert(std::make_pair(StringPiece16(entry->value), entry));
+    return Ref(entry);
+}
+
+StringPool::StyleRef StringPool::makeRef(const StyleString& str) {
+    return makeRef(str, Context{});
+}
+
+StringPool::StyleRef StringPool::makeRef(const StyleString& str, const Context& context) {
+    Entry* entry = new Entry();
+    entry->value = str.str;
+    entry->context = context;
+    entry->index = mStrings.size();
+    entry->ref = 0;
+    mStrings.emplace_back(entry);
+    mIndexedStrings.insert(std::make_pair(StringPiece16(entry->value), entry));
+
+    StyleEntry* styleEntry = new StyleEntry();
+    styleEntry->str = Ref(entry);
+    for (const aapt::Span& span : str.spans) {
+        styleEntry->spans.emplace_back(Span{makeRef(span.name),
+                span.firstChar, span.lastChar});
+    }
+    styleEntry->ref = 0;
+    mStyles.emplace_back(styleEntry);
+    return StyleRef(styleEntry);
+}
+
+void StringPool::merge(StringPool&& pool) {
+    mIndexedStrings.insert(pool.mIndexedStrings.begin(), pool.mIndexedStrings.end());
+    pool.mIndexedStrings.clear();
+    std::move(pool.mStrings.begin(), pool.mStrings.end(), std::back_inserter(mStrings));
+    pool.mStrings.clear();
+    std::move(pool.mStyles.begin(), pool.mStyles.end(), std::back_inserter(mStyles));
+    pool.mStyles.clear();
+
+    // Assign the indices.
+    const size_t len = mStrings.size();
+    for (size_t index = 0; index < len; index++) {
+        mStrings[index]->index = index;
+    }
+}
+
+void StringPool::hintWillAdd(size_t stringCount, size_t styleCount) {
+    mStrings.reserve(mStrings.size() + stringCount);
+    mStyles.reserve(mStyles.size() + styleCount);
+}
+
+void StringPool::prune() {
+    const auto iterEnd = std::end(mIndexedStrings);
+    auto indexIter = std::begin(mIndexedStrings);
+    while (indexIter != iterEnd) {
+        if (indexIter->second->ref <= 0) {
+            mIndexedStrings.erase(indexIter++);
+        } else {
+            ++indexIter;
+        }
+    }
+
+    auto endIter2 = std::remove_if(std::begin(mStrings), std::end(mStrings),
+            [](const std::unique_ptr<Entry>& entry) -> bool {
+                return entry->ref <= 0;
+            }
+    );
+
+    auto endIter3 = std::remove_if(std::begin(mStyles), std::end(mStyles),
+            [](const std::unique_ptr<StyleEntry>& entry) -> bool {
+                return entry->ref <= 0;
+            }
+    );
+
+    // Remove the entries at the end or else we'll be accessing
+    // a deleted string from the StyleEntry.
+    mStrings.erase(endIter2, std::end(mStrings));
+    mStyles.erase(endIter3, std::end(mStyles));
+}
+
+void StringPool::sort(const std::function<bool(const Entry&, const Entry&)>& cmp) {
+    std::sort(std::begin(mStrings), std::end(mStrings),
+            [&cmp](const std::unique_ptr<Entry>& a, const std::unique_ptr<Entry>& b) -> bool {
+                return cmp(*a, *b);
+            }
+    );
+
+    // Assign the indices.
+    const size_t len = mStrings.size();
+    for (size_t index = 0; index < len; index++) {
+        mStrings[index]->index = index;
+    }
+
+    // Reorder the styles.
+    std::sort(std::begin(mStyles), std::end(mStyles),
+            [](const std::unique_ptr<StyleEntry>& lhs,
+               const std::unique_ptr<StyleEntry>& rhs) -> bool {
+                return lhs->str.getIndex() < rhs->str.getIndex();
+            }
+    );
+}
+
+static uint8_t* encodeLength(uint8_t* data, size_t length) {
+    if (length > 0x7fu) {
+        *data++ = 0x80u | (0x000000ffu & (length >> 8));
+    }
+    *data++ = 0x000000ffu & length;
+    return data;
+}
+
+static size_t encodedLengthByteCount(size_t length) {
+    return length > 0x7fu ? 2 : 1;
+}
+
+bool StringPool::flattenUtf8(BigBuffer* out, const StringPool& pool) {
+    const size_t startIndex = out->size();
+    android::ResStringPool_header* header = out->nextBlock<android::ResStringPool_header>();
+    header->header.type = android::RES_STRING_POOL_TYPE;
+    header->header.headerSize = sizeof(*header);
+    header->stringCount = pool.size();
+    header->flags |= android::ResStringPool_header::UTF8_FLAG;
+
+    uint32_t* indices = out->nextBlock<uint32_t>(pool.size());
+
+    uint32_t* styleIndices = nullptr;
+    if (!pool.mStyles.empty()) {
+        header->styleCount = pool.mStyles.back()->str.getIndex() + 1;
+        styleIndices = out->nextBlock<uint32_t>(header->styleCount);
+    }
+
+    const size_t beforeStringsIndex = out->size();
+    header->stringsStart = beforeStringsIndex - startIndex;
+
+    for (const auto& entry : pool) {
+        *indices = out->size() - beforeStringsIndex;
+        indices++;
+
+        std::string encoded = util::utf16ToUtf8(entry->value);
+
+        const size_t stringByteLength = sizeof(char) * encoded.length();
+        const size_t totalSize = encodedLengthByteCount(entry->value.size())
+                + encodedLengthByteCount(encoded.length())
+                + stringByteLength
+                + sizeof(char);
+
+        uint8_t* data = out->nextBlock<uint8_t>(totalSize);
+
+        // First encode the actual UTF16 string length.
+        data = encodeLength(data, entry->value.size());
+
+        // Now encode the size of the converted UTF8 string.
+        data = encodeLength(data, encoded.length());
+
+        memcpy(data, encoded.data(), stringByteLength);
+        data += stringByteLength;
+        *data = 0;
+    }
+
+    out->align4();
+
+    if (!pool.mStyles.empty()) {
+        const size_t beforeStylesIndex = out->size();
+        header->stylesStart = beforeStylesIndex - startIndex;
+
+        size_t currentIndex = 0;
+        for (const auto& entry : pool.mStyles) {
+            while (entry->str.getIndex() > currentIndex) {
+                styleIndices[currentIndex++] = out->size() - beforeStylesIndex;
+
+                uint32_t* spanOffset = out->nextBlock<uint32_t>();
+                *spanOffset = android::ResStringPool_span::END;
+            }
+            styleIndices[currentIndex++] = out->size() - beforeStylesIndex;
+
+            android::ResStringPool_span* span =
+                    out->nextBlock<android::ResStringPool_span>(entry->spans.size());
+            for (const auto& s : entry->spans) {
+                span->name.index = s.name.getIndex();
+                span->firstChar = s.firstChar;
+                span->lastChar = s.lastChar;
+                span++;
+            }
+
+            uint32_t* spanEnd = out->nextBlock<uint32_t>();
+            *spanEnd = android::ResStringPool_span::END;
+        }
+
+        // The error checking code in the platform looks for an entire
+        // ResStringPool_span structure worth of 0xFFFFFFFF at the end
+        // of the style block, so fill in the remaining 2 32bit words
+        // with 0xFFFFFFFF.
+        const size_t paddingLength = sizeof(android::ResStringPool_span)
+                - sizeof(android::ResStringPool_span::name);
+        uint8_t* padding = out->nextBlock<uint8_t>(paddingLength);
+        memset(padding, 0xff, paddingLength);
+        out->align4();
+    }
+    header->header.size = out->size() - startIndex;
+    return true;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
new file mode 100644
index 0000000..2aa5b65
--- /dev/null
+++ b/tools/aapt2/StringPool.h
@@ -0,0 +1,215 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_STRING_POOL_H
+#define AAPT_STRING_POOL_H
+
+#include "BigBuffer.h"
+#include "ConfigDescription.h"
+#include "StringPiece.h"
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace aapt {
+
+struct Span {
+    std::u16string name;
+    uint32_t firstChar;
+    uint32_t lastChar;
+};
+
+struct StyleString {
+    std::u16string str;
+    std::vector<Span> spans;
+};
+
+class StringPool {
+public:
+    struct Context {
+        uint32_t priority;
+        ConfigDescription config;
+    };
+
+    class Entry;
+
+    class Ref {
+    public:
+        Ref();
+        Ref(const Ref&);
+        ~Ref();
+
+        Ref& operator=(const Ref& rhs);
+        const std::u16string* operator->() const;
+        const std::u16string& operator*() const;
+
+        size_t getIndex() const;
+        const Context& getContext() const;
+
+    private:
+        friend class StringPool;
+
+        Ref(Entry* entry);
+
+        Entry* mEntry;
+    };
+
+    class StyleEntry;
+
+    class StyleRef {
+    public:
+        StyleRef();
+        StyleRef(const StyleRef&);
+        ~StyleRef();
+
+        StyleRef& operator=(const StyleRef& rhs);
+        const StyleEntry* operator->() const;
+        const StyleEntry& operator*() const;
+
+        size_t getIndex() const;
+        const Context& getContext() const;
+
+    private:
+        friend class StringPool;
+
+        StyleRef(StyleEntry* entry);
+
+        StyleEntry* mEntry;
+    };
+
+    class Entry {
+    public:
+        std::u16string value;
+        Context context;
+        size_t index;
+
+    private:
+        friend class StringPool;
+        friend class Ref;
+
+        int ref;
+    };
+
+    struct Span {
+        Ref name;
+        uint32_t firstChar;
+        uint32_t lastChar;
+    };
+
+    class StyleEntry {
+    public:
+        Ref str;
+        std::vector<Span> spans;
+
+    private:
+        friend class StringPool;
+        friend class StyleRef;
+
+        int ref;
+    };
+
+    using const_iterator = std::vector<std::unique_ptr<Entry>>::const_iterator;
+
+    static bool flattenUtf8(BigBuffer* out, const StringPool& pool);
+    static bool flatten(BigBuffer* out, const StringPool& pool);
+
+    StringPool() = default;
+    StringPool(const StringPool&) = delete;
+
+    /**
+     * Adds a string to the pool, unless it already exists. Returns
+     * a reference to the string in the pool.
+     */
+    Ref makeRef(const StringPiece16& str);
+
+    /**
+     * Adds a string to the pool, unless it already exists, with a context
+     * object that can be used when sorting the string pool. Returns
+     * a reference to the string in the pool.
+     */
+    Ref makeRef(const StringPiece16& str, const Context& context);
+
+    /**
+     * Adds a style to the string pool and returns a reference to it.
+     */
+    StyleRef makeRef(const StyleString& str);
+
+    /**
+     * Adds a style to the string pool with a context object that
+     * can be used when sorting the string pool. Returns a reference
+     * to the style in the string pool.
+     */
+    StyleRef makeRef(const StyleString& str, const Context& context);
+
+    /**
+     * Moves pool into this one without coalescing strings. When this
+     * function returns, pool will be empty.
+     */
+    void merge(StringPool&& pool);
+
+    /**
+     * Retuns the number of strings in the table.
+     */
+    inline size_t size() const;
+
+    /**
+     * Reserves space for strings and styles as an optimization.
+     */
+    void hintWillAdd(size_t stringCount, size_t styleCount);
+
+    /**
+     * Sorts the strings according to some comparison function.
+     */
+    void sort(const std::function<bool(const Entry&, const Entry&)>& cmp);
+
+    /**
+     * Removes any strings that have no references.
+     */
+    void prune();
+
+private:
+    friend const_iterator begin(const StringPool& pool);
+    friend const_iterator end(const StringPool& pool);
+
+    Ref makeRefImpl(const StringPiece16& str, const Context& context, bool unique);
+
+    std::vector<std::unique_ptr<Entry>> mStrings;
+    std::vector<std::unique_ptr<StyleEntry>> mStyles;
+    std::multimap<StringPiece16, Entry*> mIndexedStrings;
+};
+
+//
+// Inline implementation
+//
+
+inline size_t StringPool::size() const {
+    return mStrings.size();
+}
+
+inline StringPool::const_iterator begin(const StringPool& pool) {
+    return pool.mStrings.begin();
+}
+
+inline StringPool::const_iterator end(const StringPool& pool) {
+    return pool.mStrings.end();
+}
+
+} // namespace aapt
+
+#endif // AAPT_STRING_POOL_H
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
new file mode 100644
index 0000000..85d101a
--- /dev/null
+++ b/tools/aapt2/StringPool_test.cpp
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
+
+#include "StringPool.h"
+#include "Util.h"
+
+#include <gtest/gtest.h>
+#include <string>
+
+using namespace android;
+
+namespace aapt {
+
+TEST(StringPoolTest, InsertOneString) {
+    StringPool pool;
+
+    StringPool::Ref ref = pool.makeRef(u"wut");
+    EXPECT_EQ(*ref, u"wut");
+}
+
+TEST(StringPoolTest, InsertTwoUniqueStrings) {
+    StringPool pool;
+
+    StringPool::Ref ref = pool.makeRef(u"wut");
+    StringPool::Ref ref2 = pool.makeRef(u"hey");
+
+    EXPECT_EQ(*ref, u"wut");
+    EXPECT_EQ(*ref2, u"hey");
+}
+
+TEST(StringPoolTest, DoNotInsertNewDuplicateString) {
+    StringPool pool;
+
+    StringPool::Ref ref = pool.makeRef(u"wut");
+    StringPool::Ref ref2 = pool.makeRef(u"wut");
+
+    EXPECT_EQ(*ref, u"wut");
+    EXPECT_EQ(*ref2, u"wut");
+    EXPECT_EQ(1u, pool.size());
+}
+
+TEST(StringPoolTest, MaintainInsertionOrderIndex) {
+    StringPool pool;
+
+    StringPool::Ref ref = pool.makeRef(u"z");
+    StringPool::Ref ref2 = pool.makeRef(u"a");
+    StringPool::Ref ref3 = pool.makeRef(u"m");
+
+    EXPECT_EQ(0u, ref.getIndex());
+    EXPECT_EQ(1u, ref2.getIndex());
+    EXPECT_EQ(2u, ref3.getIndex());
+}
+
+TEST(StringPoolTest, PruneStringsWithNoReferences) {
+    StringPool pool;
+
+    {
+        StringPool::Ref ref = pool.makeRef(u"wut");
+        EXPECT_EQ(*ref, u"wut");
+        EXPECT_EQ(1u, pool.size());
+    }
+
+    EXPECT_EQ(1u, pool.size());
+    pool.prune();
+    EXPECT_EQ(0u, pool.size());
+}
+
+TEST(StringPoolTest, SortAndMaintainIndexesInReferences) {
+    StringPool pool;
+
+    StringPool::Ref ref = pool.makeRef(u"z");
+    StringPool::StyleRef ref2 = pool.makeRef(StyleString{ {u"a"} });
+    StringPool::Ref ref3 = pool.makeRef(u"m");
+
+    EXPECT_EQ(*ref, u"z");
+    EXPECT_EQ(0u, ref.getIndex());
+
+    EXPECT_EQ(*(ref2->str), u"a");
+    EXPECT_EQ(1u, ref2.getIndex());
+
+    EXPECT_EQ(*ref3, u"m");
+    EXPECT_EQ(2u, ref3.getIndex());
+
+    pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
+        return a.value < b.value;
+    });
+
+
+    EXPECT_EQ(*ref, u"z");
+    EXPECT_EQ(2u, ref.getIndex());
+
+    EXPECT_EQ(*(ref2->str), u"a");
+    EXPECT_EQ(0u, ref2.getIndex());
+
+    EXPECT_EQ(*ref3, u"m");
+    EXPECT_EQ(1u, ref3.getIndex());
+}
+
+TEST(StringPoolTest, SortAndStillDedupe) {
+    StringPool pool;
+
+    StringPool::Ref ref = pool.makeRef(u"z");
+    StringPool::Ref ref2 = pool.makeRef(u"a");
+    StringPool::Ref ref3 = pool.makeRef(u"m");
+
+    pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
+        return a.value < b.value;
+    });
+
+    StringPool::Ref ref4 = pool.makeRef(u"z");
+    StringPool::Ref ref5 = pool.makeRef(u"a");
+    StringPool::Ref ref6 = pool.makeRef(u"m");
+
+    EXPECT_EQ(ref4.getIndex(), ref.getIndex());
+    EXPECT_EQ(ref5.getIndex(), ref2.getIndex());
+    EXPECT_EQ(ref6.getIndex(), ref3.getIndex());
+}
+
+TEST(StringPoolTest, AddStyles) {
+    StringPool pool;
+
+    StyleString str {
+        { u"android" },
+        {
+            Span{ { u"b" }, 2, 6 }
+        }
+    };
+
+    StringPool::StyleRef ref = pool.makeRef(str);
+
+    EXPECT_EQ(0u, ref.getIndex());
+    EXPECT_EQ(std::u16string(u"android"), *(ref->str));
+    ASSERT_EQ(1u, ref->spans.size());
+
+    const StringPool::Span& span = ref->spans.front();
+    EXPECT_EQ(*(span.name), u"b");
+    EXPECT_EQ(2u, span.firstChar);
+    EXPECT_EQ(6u, span.lastChar);
+}
+
+TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) {
+    StringPool pool;
+
+    StringPool::Ref ref = pool.makeRef(u"android");
+
+    StyleString str { { u"android" } };
+    StringPool::StyleRef styleRef = pool.makeRef(str);
+
+    EXPECT_NE(ref.getIndex(), styleRef.getIndex());
+}
+
+constexpr const char16_t* sLongString = u"バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限します。メール、SMSや、同期を使 用するその他のアプリは、起動しても更新されないことがあります。バッテリーセーバーは端末の充電中は自動的にOFFになります。";
+
+TEST(StringPoolTest, FlattenUtf8) {
+    StringPool pool;
+
+    StringPool::Ref ref1 = pool.makeRef(u"hello");
+    StringPool::Ref ref2 = pool.makeRef(u"goodbye");
+    StringPool::Ref ref3 = pool.makeRef(sLongString);
+    StringPool::StyleRef ref4 = pool.makeRef(StyleString{
+            { u"style" },
+            { Span{ { u"b" }, 0, 1 }, Span{ { u"i" }, 2, 3 } }
+    });
+
+    EXPECT_EQ(0u, ref1.getIndex());
+    EXPECT_EQ(1u, ref2.getIndex());
+    EXPECT_EQ(2u, ref3.getIndex());
+    EXPECT_EQ(3u, ref4.getIndex());
+
+    BigBuffer buffer(1024);
+    StringPool::flattenUtf8(&buffer, pool);
+
+    uint8_t* data = new uint8_t[buffer.size()];
+    uint8_t* p = data;
+    for (const auto& b : buffer) {
+        memcpy(p, b.buffer.get(), b.size);
+        p += b.size;
+    }
+
+    {
+        ResStringPool test;
+        ASSERT_TRUE(test.setTo(data, buffer.size()) == NO_ERROR);
+
+        EXPECT_EQ(util::getString(test, 0), u"hello");
+        EXPECT_EQ(util::getString(test, 1), u"goodbye");
+        EXPECT_EQ(util::getString(test, 2), sLongString);
+        EXPECT_EQ(util::getString(test, 3), u"style");
+
+        const ResStringPool_span* span = test.styleAt(3);
+        ASSERT_NE(nullptr, span);
+        EXPECT_EQ(util::getString(test, span->name.index), u"b");
+        EXPECT_EQ(0u, span->firstChar);
+        EXPECT_EQ(1u, span->lastChar);
+        span++;
+
+        ASSERT_NE(ResStringPool_span::END, span->name.index);
+        EXPECT_EQ(util::getString(test, span->name.index), u"i");
+        EXPECT_EQ(2u, span->firstChar);
+        EXPECT_EQ(3u, span->lastChar);
+        span++;
+
+        EXPECT_EQ(ResStringPool_span::END, span->name.index);
+    }
+    delete[] data;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/TableFlattener.cpp b/tools/aapt2/TableFlattener.cpp
new file mode 100644
index 0000000..67c56e7
--- /dev/null
+++ b/tools/aapt2/TableFlattener.cpp
@@ -0,0 +1,512 @@
+/*
+ * 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.
+ */
+
+#include "BigBuffer.h"
+#include "ConfigDescription.h"
+#include "Logger.h"
+#include "ResourceTable.h"
+#include "ResourceTypeExtensions.h"
+#include "ResourceValues.h"
+#include "StringPool.h"
+#include "TableFlattener.h"
+#include "Util.h"
+
+#include <algorithm>
+#include <androidfw/ResourceTypes.h>
+#include <sstream>
+
+namespace aapt {
+
+struct FlatEntry {
+    const ResourceEntry& entry;
+    const Value& value;
+    uint32_t entryKey;
+    uint32_t sourcePathKey;
+    uint32_t sourceLine;
+};
+
+/**
+ * Visitor that knows how to encode Map values.
+ */
+class MapFlattener : public ConstValueVisitor {
+public:
+    MapFlattener(BigBuffer* out, const FlatEntry& flatEntry,
+                 std::vector<std::pair<ResourceNameRef, uint32_t>>& symbols) :
+            mOut(out), mSymbols(symbols) {
+        mMap = mOut->nextBlock<android::ResTable_map_entry>();
+        mMap->key.index = flatEntry.entryKey;
+        mMap->flags = android::ResTable_entry::FLAG_COMPLEX;
+        if (flatEntry.entry.publicStatus.isPublic) {
+            mMap->flags |= android::ResTable_entry::FLAG_PUBLIC;
+        }
+        if (flatEntry.value.isWeak()) {
+            mMap->flags |= android::ResTable_entry::FLAG_WEAK;
+        }
+
+        ResTable_entry_source* sourceBlock = mOut->nextBlock<ResTable_entry_source>();
+        sourceBlock->pathIndex = flatEntry.sourcePathKey;
+        sourceBlock->line = flatEntry.sourceLine;
+
+        mMap->size = sizeof(*mMap) + sizeof(*sourceBlock);
+    }
+
+    void flattenParent(const Reference& ref) {
+        if (!ref.id.isValid()) {
+            mSymbols.push_back({
+                    ResourceNameRef(ref.name),
+                    (mOut->size() - mMap->size) + sizeof(*mMap) - sizeof(android::ResTable_entry)
+            });
+        }
+        mMap->parent.ident = ref.id.id;
+    }
+
+    void flattenEntry(const Reference& key, const Item& value) {
+        mMap->count++;
+
+        android::ResTable_map* outMapEntry = mOut->nextBlock<android::ResTable_map>();
+
+        // Write the key.
+        if (!Res_INTERNALID(key.id.id) && !key.id.isValid()) {
+            mSymbols.push_back(std::make_pair(ResourceNameRef(key.name),
+                    mOut->size() - sizeof(*outMapEntry)));
+        }
+        outMapEntry->name.ident = key.id.id;
+
+        // Write the value.
+        value.flatten(outMapEntry->value);
+
+        if (outMapEntry->value.data == 0x0) {
+            visitFunc<Reference>(value, [&](const Reference& reference) {
+                mSymbols.push_back(std::make_pair(ResourceNameRef(reference.name),
+                        mOut->size() - sizeof(outMapEntry->value.data)));
+            });
+        }
+        outMapEntry->value.size = sizeof(outMapEntry->value);
+    }
+
+    static bool compareStyleEntries(const Style::Entry* lhs, const Style::Entry* rhs) {
+        return lhs->key.id < rhs->key.id;
+    }
+
+    void visit(const Style& style, ValueVisitorArgs&) override {
+        if (style.parent.name.isValid()) {
+            flattenParent(style.parent);
+        }
+
+        // First sort the entries by ID.
+        std::vector<const Style::Entry*> sortedEntries;
+        for (const auto& styleEntry : style.entries) {
+            auto iter = std::lower_bound(sortedEntries.begin(), sortedEntries.end(),
+                    &styleEntry, compareStyleEntries);
+            sortedEntries.insert(iter, &styleEntry);
+        }
+
+        for (const Style::Entry* styleEntry : sortedEntries) {
+            flattenEntry(styleEntry->key, *styleEntry->value);
+        }
+    }
+
+    void visit(const Attribute& attr, ValueVisitorArgs&) override {
+        android::Res_value tempVal;
+        tempVal.dataType = android::Res_value::TYPE_INT_DEC;
+        tempVal.data = attr.typeMask;
+        flattenEntry(Reference(ResourceId{android::ResTable_map::ATTR_TYPE}),
+                BinaryPrimitive(tempVal));
+
+        for (const auto& symbol : attr.symbols) {
+            tempVal.data = symbol.value;
+            flattenEntry(symbol.symbol, BinaryPrimitive(tempVal));
+        }
+    }
+
+    void visit(const Styleable& styleable, ValueVisitorArgs&) override {
+        for (const auto& attr : styleable.entries) {
+            flattenEntry(attr, BinaryPrimitive(android::Res_value{}));
+        }
+    }
+
+    void visit(const Array& array, ValueVisitorArgs&) override {
+        for (const auto& item : array.items) {
+            flattenEntry({}, *item);
+        }
+    }
+
+    void visit(const Plural& plural, ValueVisitorArgs&) override {
+        const size_t count = plural.values.size();
+        for (size_t i = 0; i < count; i++) {
+            if (!plural.values[i]) {
+                continue;
+            }
+
+            ResourceId q;
+            switch (i) {
+                case Plural::Zero:
+                    q.id = android::ResTable_map::ATTR_ZERO;
+                    break;
+
+                case Plural::One:
+                    q.id = android::ResTable_map::ATTR_ONE;
+                    break;
+
+                case Plural::Two:
+                    q.id = android::ResTable_map::ATTR_TWO;
+                    break;
+
+                case Plural::Few:
+                    q.id = android::ResTable_map::ATTR_FEW;
+                    break;
+
+                case Plural::Many:
+                    q.id = android::ResTable_map::ATTR_MANY;
+                    break;
+
+                case Plural::Other:
+                    q.id = android::ResTable_map::ATTR_OTHER;
+                    break;
+
+                default:
+                    assert(false);
+                    break;
+            }
+
+            flattenEntry(Reference(q), *plural.values[i]);
+        }
+    }
+
+private:
+    BigBuffer* mOut;
+    std::vector<std::pair<ResourceNameRef, uint32_t>>& mSymbols;
+    android::ResTable_map_entry* mMap;
+};
+
+TableFlattener::TableFlattener(Options options)
+: mOptions(options) {
+}
+
+bool TableFlattener::flattenValue(BigBuffer* out, const FlatEntry& flatEntry,
+        std::vector<std::pair<ResourceNameRef, uint32_t>>& symbolEntries) {
+    if (flatEntry.value.isItem()) {
+        android::ResTable_entry* entry = out->nextBlock<android::ResTable_entry>();
+
+        if (flatEntry.entry.publicStatus.isPublic) {
+            entry->flags |= android::ResTable_entry::FLAG_PUBLIC;
+        }
+
+        if (flatEntry.value.isWeak()) {
+            entry->flags |= android::ResTable_entry::FLAG_WEAK;
+        }
+
+        entry->key.index = flatEntry.entryKey;
+        entry->size = sizeof(*entry);
+
+        if (mOptions.useExtendedChunks) {
+            // Write the extra source block. This will be ignored by
+            // the Android runtime.
+            ResTable_entry_source* sourceBlock = out->nextBlock<ResTable_entry_source>();
+            sourceBlock->pathIndex = flatEntry.sourcePathKey;
+            sourceBlock->line = flatEntry.sourceLine;
+
+            entry->size += sizeof(*sourceBlock);
+        }
+
+        android::Res_value* outValue = out->nextBlock<android::Res_value>();
+
+        const Item& item = static_cast<const Item&>(flatEntry.value);
+        if (!item.flatten(*outValue)) {
+            return false;
+        }
+
+        if (outValue->data == 0x0) {
+            visitFunc<Reference>(item, [&](const Reference& reference) {
+                symbolEntries.push_back({
+                        ResourceNameRef(reference.name),
+                        out->size() - sizeof(outValue->data)
+                });
+            });
+        }
+        outValue->size = sizeof(*outValue);
+        return true;
+    }
+
+    MapFlattener flattener(out, flatEntry, symbolEntries);
+    flatEntry.value.accept(flattener, {});
+    return true;
+}
+
+bool TableFlattener::flatten(BigBuffer* out, const ResourceTable& table) {
+    const size_t beginning = out->size();
+
+    if (table.getPackage().size() == 0) {
+        Logger::error()
+                << "ResourceTable has no package name."
+                << std::endl;
+        return false;
+    }
+
+    if (table.getPackageId() == ResourceTable::kUnsetPackageId) {
+        Logger::error()
+                << "ResourceTable has no package ID set."
+                << std::endl;
+        return false;
+    }
+
+    std::vector<std::pair<ResourceNameRef, uint32_t>> symbolEntries;
+
+    StringPool typePool;
+    StringPool keyPool;
+    StringPool sourcePool;
+
+    // Sort the types by their IDs. They will be inserted into the StringPool
+    // in this order.
+    std::vector<ResourceTableType*> sortedTypes;
+    for (const auto& type : table) {
+        if (type->type == ResourceType::kStyleable && !mOptions.useExtendedChunks) {
+            continue;
+        }
+
+        auto iter = std::lower_bound(std::begin(sortedTypes), std::end(sortedTypes), type.get(),
+                [](const ResourceTableType* lhs, const ResourceTableType* rhs) -> bool {
+                    return lhs->typeId < rhs->typeId;
+                });
+        sortedTypes.insert(iter, type.get());
+    }
+
+    BigBuffer typeBlock(1024);
+    size_t expectedTypeId = 1;
+    for (const ResourceTableType* type : sortedTypes) {
+        if (type->typeId == ResourceTableType::kUnsetTypeId
+                || type->typeId == 0) {
+            Logger::error()
+                    << "resource type '"
+                    << type->type
+                    << "' from package '"
+                    << table.getPackage()
+                    << "' has no ID."
+                    << std::endl;
+            return false;
+        }
+
+        // If there is a gap in the type IDs, fill in the StringPool
+        // with empty values until we reach the ID we expect.
+        while (type->typeId > expectedTypeId) {
+            std::u16string typeName(u"?");
+            typeName += expectedTypeId;
+            typePool.makeRef(typeName);
+            expectedTypeId++;
+        }
+        expectedTypeId++;
+        typePool.makeRef(toString(type->type));
+
+        android::ResTable_typeSpec* spec = typeBlock.nextBlock<android::ResTable_typeSpec>();
+        spec->header.type = android::RES_TABLE_TYPE_SPEC_TYPE;
+        spec->header.headerSize = sizeof(*spec);
+        spec->header.size = spec->header.headerSize + (type->entries.size() * sizeof(uint32_t));
+        spec->id = type->typeId;
+        spec->entryCount = type->entries.size();
+
+        // Reserve space for the masks of each resource in this type. These
+        // show for which configuration axis the resource changes.
+        uint32_t* configMasks = typeBlock.nextBlock<uint32_t>(type->entries.size());
+
+        // Sort the entries by entry ID and write their configuration masks.
+        std::vector<ResourceEntry*> entries;
+        const size_t entryCount = type->entries.size();
+        for (size_t entryIndex = 0; entryIndex < entryCount; entryIndex++) {
+            const auto& entry = type->entries[entryIndex];
+
+            if (entry->entryId == ResourceEntry::kUnsetEntryId) {
+                Logger::error()
+                        << "resource '"
+                        << ResourceName{ table.getPackage(), type->type, entry->name }
+                        << "' has no ID."
+                        << std::endl;
+                return false;
+            }
+
+            auto iter = std::lower_bound(std::begin(entries), std::end(entries), entry.get(),
+                    [](const ResourceEntry* lhs, const ResourceEntry* rhs) -> bool {
+                        return lhs->entryId < rhs->entryId;
+                    });
+            entries.insert(iter, entry.get());
+
+            // Populate the config masks for this entry.
+            if (entry->publicStatus.isPublic) {
+                configMasks[entry->entryId] |= android::ResTable_typeSpec::SPEC_PUBLIC;
+            }
+
+            const size_t configCount = entry->values.size();
+            for (size_t i = 0; i < configCount; i++) {
+                const ConfigDescription& config = entry->values[i].config;
+                for (size_t j = i + 1; j < configCount; j++) {
+                    configMasks[entry->entryId] |= config.diff(entry->values[j].config);
+                }
+            }
+        }
+
+        // The binary resource table lists resource entries for each configuration.
+        // We store them inverted, where a resource entry lists the values for each
+        // configuration available. Here we reverse this to match the binary table.
+        std::map<ConfigDescription, std::vector<FlatEntry>> data;
+        for (const ResourceEntry* entry : entries) {
+            size_t keyIndex = keyPool.makeRef(entry->name).getIndex();
+
+            if (keyIndex > std::numeric_limits<uint32_t>::max()) {
+                Logger::error()
+                        << "resource key string pool exceeded max size."
+                        << std::endl;
+                return false;
+            }
+
+            for (const auto& configValue : entry->values) {
+                data[configValue.config].push_back(FlatEntry{
+                        *entry,
+                        *configValue.value,
+                        static_cast<uint32_t>(keyIndex),
+                        static_cast<uint32_t>(sourcePool.makeRef(util::utf8ToUtf16(
+                                        configValue.source.path)).getIndex()),
+                        static_cast<uint32_t>(configValue.source.line)
+                });
+            }
+        }
+
+        // Begin flattening a configuration for the current type.
+        for (const auto& entry : data) {
+            const size_t typeHeaderStart = typeBlock.size();
+            android::ResTable_type* typeHeader = typeBlock.nextBlock<android::ResTable_type>();
+            typeHeader->header.type = android::RES_TABLE_TYPE_TYPE;
+            typeHeader->header.headerSize = sizeof(*typeHeader);
+            typeHeader->id = type->typeId;
+            typeHeader->entryCount = type->entries.size();
+            typeHeader->entriesStart = typeHeader->header.headerSize
+                    + (sizeof(uint32_t) * type->entries.size());
+            typeHeader->config = entry.first;
+
+            uint32_t* indices = typeBlock.nextBlock<uint32_t>(type->entries.size());
+            memset(indices, 0xff, type->entries.size() * sizeof(uint32_t));
+
+            const size_t entryStart = typeBlock.size();
+            for (const FlatEntry& flatEntry : entry.second) {
+                assert(flatEntry.entry.entryId < type->entries.size());
+                indices[flatEntry.entry.entryId] = typeBlock.size() - entryStart;
+                if (!flattenValue(&typeBlock, flatEntry, symbolEntries)) {
+                    Logger::error()
+                            << "failed to flatten resource '"
+                            << ResourceNameRef {
+                                    table.getPackage(), type->type, flatEntry.entry.name }
+                            << "' for configuration '"
+                            << entry.first
+                            << "'."
+                            << std::endl;
+                    return false;
+                }
+            }
+
+            typeBlock.align4();
+            typeHeader->header.size = typeBlock.size() - typeHeaderStart;
+        }
+    }
+
+    const size_t beforeTable = out->size();
+    android::ResTable_header* header = out->nextBlock<android::ResTable_header>();
+    header->header.type = android::RES_TABLE_TYPE;
+    header->header.headerSize = sizeof(*header);
+    header->packageCount = 1;
+
+    SymbolTable_entry* symbolEntryData = nullptr;
+    if (!symbolEntries.empty() && mOptions.useExtendedChunks) {
+        const size_t beforeSymbolTable = out->size();
+        StringPool symbolPool;
+        SymbolTable_header* symbolHeader = out->nextBlock<SymbolTable_header>();
+        symbolHeader->header.type = RES_TABLE_SYMBOL_TABLE_TYPE;
+        symbolHeader->header.headerSize = sizeof(*symbolHeader);
+        symbolHeader->count = symbolEntries.size();
+
+        symbolEntryData = out->nextBlock<SymbolTable_entry>(symbolHeader->count);
+
+        size_t i = 0;
+        for (const auto& entry : symbolEntries) {
+            symbolEntryData[i].offset = entry.second;
+            StringPool::Ref ref = symbolPool.makeRef(
+                    entry.first.package.toString() + u":" +
+                    toString(entry.first.type).toString() + u"/" +
+                    entry.first.entry.toString());
+            symbolEntryData[i].stringIndex = ref.getIndex();
+            i++;
+        }
+
+        StringPool::flattenUtf8(out, symbolPool);
+        out->align4();
+        symbolHeader->header.size = out->size() - beforeSymbolTable;
+    }
+
+    if (sourcePool.size() > 0 && mOptions.useExtendedChunks) {
+        const size_t beforeSourcePool = out->size();
+        android::ResChunk_header* sourceHeader = out->nextBlock<android::ResChunk_header>();
+        sourceHeader->type = RES_TABLE_SOURCE_POOL_TYPE;
+        sourceHeader->headerSize = sizeof(*sourceHeader);
+        StringPool::flattenUtf8(out, sourcePool);
+        out->align4();
+        sourceHeader->size = out->size() - beforeSourcePool;
+    }
+
+    StringPool::flattenUtf8(out, table.getValueStringPool());
+
+    const size_t beforePackageIndex = out->size();
+    android::ResTable_package* package = out->nextBlock<android::ResTable_package>();
+    package->header.type = android::RES_TABLE_PACKAGE_TYPE;
+    package->header.headerSize = sizeof(*package);
+
+    if (table.getPackageId() > std::numeric_limits<uint8_t>::max()) {
+        Logger::error()
+                << "package ID 0x'"
+                << std::hex << table.getPackageId() << std::dec
+                << "' is invalid."
+                << std::endl;
+        return false;
+    }
+    package->id = table.getPackageId();
+
+    if (table.getPackage().size() >= sizeof(package->name) / sizeof(package->name[0])) {
+        Logger::error()
+                << "package name '"
+                << table.getPackage()
+                << "' is too long."
+                << std::endl;
+        return false;
+    }
+    memcpy(package->name, reinterpret_cast<const uint16_t*>(table.getPackage().data()),
+            table.getPackage().length() * sizeof(char16_t));
+    package->name[table.getPackage().length()] = 0;
+
+    package->typeStrings = package->header.headerSize;
+    StringPool::flattenUtf8(out, typePool);
+    package->keyStrings = out->size() - beforePackageIndex;
+    StringPool::flattenUtf8(out, keyPool);
+
+    if (symbolEntryData != nullptr) {
+        for (size_t i = 0; i < symbolEntries.size(); i++) {
+            symbolEntryData[i].offset += out->size() - beginning;
+        }
+    }
+
+    out->appendBuffer(std::move(typeBlock));
+
+    package->header.size = out->size() - beforePackageIndex;
+    header->header.size = out->size() - beforeTable;
+    return true;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/TableFlattener.h b/tools/aapt2/TableFlattener.h
new file mode 100644
index 0000000..0ae798c
--- /dev/null
+++ b/tools/aapt2/TableFlattener.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_TABLE_FLATTENER_H
+#define AAPT_TABLE_FLATTENER_H
+
+#include "BigBuffer.h"
+#include "ResourceTable.h"
+
+namespace aapt {
+
+struct FlatEntry;
+
+/**
+ * Flattens a ResourceTable into a binary format suitable
+ * for loading into a ResTable on the host or device.
+ */
+struct TableFlattener {
+    /**
+     * A set of options for this TableFlattener.
+     */
+    struct Options {
+        /**
+         * Specifies whether to output extended chunks, like
+         * source information and mising symbol entries. Default
+         * is true.
+         *
+         * Set this to false when emitting the final table to be used
+         * on device.
+         */
+        bool useExtendedChunks = true;
+    };
+
+    TableFlattener(Options options);
+
+    bool flatten(BigBuffer* out, const ResourceTable& table);
+
+private:
+    bool flattenValue(BigBuffer* out, const FlatEntry& flatEntry,
+                      std::vector<std::pair<ResourceNameRef, uint32_t>>& symbolEntries);
+
+    Options mOptions;
+};
+
+} // namespace aapt
+
+#endif // AAPT_TABLE_FLATTENER_H
diff --git a/tools/aapt2/Util.cpp b/tools/aapt2/Util.cpp
new file mode 100644
index 0000000..8a4c88f
--- /dev/null
+++ b/tools/aapt2/Util.cpp
@@ -0,0 +1,290 @@
+/*
+ * 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.
+ */
+
+#include "BigBuffer.h"
+#include "Maybe.h"
+#include "StringPiece.h"
+#include "Util.h"
+
+#include <algorithm>
+#include <ostream>
+#include <string>
+#include <utils/Unicode.h>
+#include <vector>
+
+namespace aapt {
+namespace util {
+
+static std::vector<std::string> splitAndTransform(const StringPiece& str, char sep,
+        const std::function<char(char)>& f) {
+    std::vector<std::string> parts;
+    const StringPiece::const_iterator end = std::end(str);
+    StringPiece::const_iterator start = std::begin(str);
+    StringPiece::const_iterator current;
+    do {
+        current = std::find(start, end, sep);
+        parts.emplace_back(str.substr(start, current).toString());
+        if (f) {
+            std::string& part = parts.back();
+            std::transform(part.begin(), part.end(), part.begin(), f);
+        }
+        start = current + 1;
+    } while (current != end);
+    return parts;
+}
+
+std::vector<std::string> split(const StringPiece& str, char sep) {
+    return splitAndTransform(str, sep, nullptr);
+}
+
+std::vector<std::string> splitAndLowercase(const StringPiece& str, char sep) {
+    return splitAndTransform(str, sep, ::tolower);
+}
+
+bool stringEndsWith(const StringPiece& str, const StringPiece& suffix) {
+    if (str.size() < suffix.size()) {
+        return false;
+    }
+    return str.substr(str.size() - suffix.size(), suffix.size()) == suffix;
+}
+
+StringPiece16 trimWhitespace(const StringPiece16& str) {
+    if (str.size() == 0 || str.data() == nullptr) {
+        return str;
+    }
+
+    const char16_t* start = str.data();
+    const char16_t* end = str.data() + str.length();
+
+    while (start != end && util::isspace16(*start)) {
+        start++;
+    }
+
+    while (end != start && util::isspace16(*(end - 1))) {
+        end--;
+    }
+
+    return StringPiece16(start, end - start);
+}
+
+StringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str,
+        const StringPiece16& allowedChars) {
+    const auto endIter = str.end();
+    for (auto iter = str.begin(); iter != endIter; ++iter) {
+        char16_t c = *iter;
+        if ((c >= u'a' && c <= u'z') ||
+                (c >= u'A' && c <= u'Z') ||
+                (c >= u'0' && c <= u'9')) {
+            continue;
+        }
+
+        bool match = false;
+        for (char16_t i : allowedChars) {
+            if (c == i) {
+                match = true;
+                break;
+            }
+        }
+
+        if (!match) {
+            return iter;
+        }
+    }
+    return endIter;
+}
+
+static Maybe<char16_t> parseUnicodeCodepoint(const char16_t** start, const char16_t* end) {
+    char16_t code = 0;
+    for (size_t i = 0; i < 4 && *start != end; i++, (*start)++) {
+        char16_t c = **start;
+        int a;
+        if (c >= '0' && c <= '9') {
+            a = c - '0';
+        } else if (c >= 'a' && c <= 'f') {
+            a = c - 'a' + 10;
+        } else if (c >= 'A' && c <= 'F') {
+            a = c - 'A' + 10;
+        } else {
+            return make_nothing<char16_t>();
+        }
+        code = (code << 4) | a;
+    }
+    return make_value(code);
+}
+
+StringBuilder& StringBuilder::append(const StringPiece16& str) {
+    if (!mError.empty()) {
+        return *this;
+    }
+
+    const char16_t* const end = str.end();
+    const char16_t* start = str.begin();
+    const char16_t* current = start;
+    while (current != end) {
+        if (*current == u'"') {
+            if (!mQuote && mTrailingSpace) {
+                // We found an opening quote, and we have
+                // trailing space, so we should append that
+                // space now.
+                if (mTrailingSpace) {
+                    // We had trailing whitespace, so
+                    // replace with a single space.
+                    if (!mStr.empty()) {
+                        mStr += u' ';
+                    }
+                    mTrailingSpace = false;
+                }
+            }
+            mQuote = !mQuote;
+            mStr.append(start, current - start);
+            start = current + 1;
+        } else if (*current == u'\'' && !mQuote) {
+            // This should be escaped.
+            mError = "unescaped apostrophe";
+            return *this;
+        } else if (*current == u'\\') {
+            // This is an escape sequence, convert to the real value.
+            if (!mQuote && mTrailingSpace) {
+                // We had trailing whitespace, so
+                // replace with a single space.
+                if (!mStr.empty()) {
+                    mStr += u' ';
+                }
+                mTrailingSpace = false;
+            }
+            mStr.append(start, current - start);
+            start = current + 1;
+
+            current++;
+            if (current != end) {
+                switch (*current) {
+                    case u't':
+                        mStr += u'\t';
+                        break;
+                    case u'n':
+                        mStr += u'\n';
+                        break;
+                    case u'#':
+                        mStr += u'#';
+                        break;
+                    case u'@':
+                        mStr += u'@';
+                        break;
+                    case u'?':
+                        mStr += u'?';
+                        break;
+                    case u'"':
+                        mStr += u'"';
+                        break;
+                    case u'\'':
+                        mStr += u'\'';
+                        break;
+                    case u'\\':
+                        mStr += u'\\';
+                        break;
+                    case u'u': {
+                        current++;
+                        Maybe<char16_t> c = parseUnicodeCodepoint(&current, end);
+                        if (!c) {
+                            mError = "invalid unicode escape sequence";
+                            return *this;
+                        }
+                        mStr += c.value();
+                        current -= 1;
+                        break;
+                    }
+
+                    default:
+                        // Ignore.
+                        break;
+                }
+                start = current + 1;
+            }
+        } else if (!mQuote) {
+            // This is not quoted text, so look for whitespace.
+            if (isspace16(*current)) {
+                // We found whitespace, see if we have seen some
+                // before.
+                if (!mTrailingSpace) {
+                    // We didn't see a previous adjacent space,
+                    // so mark that we did.
+                    mTrailingSpace = true;
+                    mStr.append(start, current - start);
+                }
+
+                // Keep skipping whitespace.
+                start = current + 1;
+            } else if (mTrailingSpace) {
+                // We saw trailing space before, so replace all
+                // that trailing space with one space.
+                if (!mStr.empty()) {
+                    mStr += u' ';
+                }
+                mTrailingSpace = false;
+            }
+        }
+        current++;
+    }
+    mStr.append(start, end - start);
+    return *this;
+}
+
+std::u16string utf8ToUtf16(const StringPiece& utf8) {
+    ssize_t utf16Length = utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(utf8.data()),
+            utf8.length());
+    if (utf16Length <= 0) {
+        return {};
+    }
+
+    std::u16string utf16;
+    utf16.resize(utf16Length);
+    utf8_to_utf16(reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length(), &*utf16.begin());
+    return utf16;
+}
+
+std::string utf16ToUtf8(const StringPiece16& utf16) {
+    ssize_t utf8Length = utf16_to_utf8_length(utf16.data(), utf16.length());
+    if (utf8Length <= 0) {
+        return {};
+    }
+
+    std::string utf8;
+    utf8.resize(utf8Length);
+    utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin());
+    return utf8;
+}
+
+bool writeAll(std::ostream& out, const BigBuffer& buffer) {
+    for (const auto& b : buffer) {
+        if (!out.write(reinterpret_cast<const char*>(b.buffer.get()), b.size)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+std::unique_ptr<uint8_t[]> copy(const BigBuffer& buffer) {
+    std::unique_ptr<uint8_t[]> data = std::unique_ptr<uint8_t[]>(new uint8_t[buffer.size()]);
+    uint8_t* p = data.get();
+    for (const auto& block : buffer) {
+        memcpy(p, block.buffer.get(), block.size);
+        p += block.size;
+    }
+    return data;
+}
+
+} // namespace util
+} // namespace aapt
diff --git a/tools/aapt2/Util.h b/tools/aapt2/Util.h
new file mode 100644
index 0000000..510ed76
--- /dev/null
+++ b/tools/aapt2/Util.h
@@ -0,0 +1,276 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_UTIL_H
+#define AAPT_UTIL_H
+
+#include "BigBuffer.h"
+#include "StringPiece.h"
+
+#include <androidfw/ResourceTypes.h>
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <vector>
+
+namespace aapt {
+namespace util {
+
+std::vector<std::string> split(const StringPiece& str, char sep);
+std::vector<std::string> splitAndLowercase(const StringPiece& str, char sep);
+
+/**
+ * Returns true if the string ends with suffix.
+ */
+bool stringEndsWith(const StringPiece& str, const StringPiece& suffix);
+
+/**
+ * Creates a new StringPiece16 that points to a substring
+ * of the original string without leading or trailing whitespace.
+ */
+StringPiece16 trimWhitespace(const StringPiece16& str);
+
+/**
+ * UTF-16 isspace(). It basically checks for lower range characters that are
+ * whitespace.
+ */
+inline bool isspace16(char16_t c) {
+    return c < 0x0080 && isspace(c);
+}
+
+/**
+ * Returns an iterator to the first character that is not alpha-numeric and that
+ * is not in the allowedChars set.
+ */
+StringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str,
+        const StringPiece16& allowedChars);
+
+/**
+ * Makes a std::unique_ptr<> with the template parameter inferred by the compiler.
+ * This will be present in C++14 and can be removed then.
+ */
+template <typename T, class... Args>
+std::unique_ptr<T> make_unique(Args&&... args) {
+    return std::unique_ptr<T>(new T{std::forward<Args>(args)...});
+}
+
+/**
+ * Writes a set of items to the std::ostream, joining the times with the provided
+ * separator.
+ */
+template <typename Iterator>
+::std::function<::std::ostream&(::std::ostream&)> joiner(Iterator begin, Iterator end,
+        const char* sep) {
+    return [begin, end, sep](::std::ostream& out) -> ::std::ostream& {
+        for (auto iter = begin; iter != end; ++iter) {
+            if (iter != begin) {
+                out << sep;
+            }
+            out << *iter;
+        }
+        return out;
+    };
+}
+
+inline ::std::function<::std::ostream&(::std::ostream&)> formatSize(size_t size) {
+    return [size](::std::ostream& out) -> ::std::ostream& {
+        constexpr size_t K = 1024u;
+        constexpr size_t M = K * K;
+        constexpr size_t G = M * K;
+        if (size < K) {
+            out << size << "B";
+        } else if (size < M) {
+            out << (double(size) / K) << " KiB";
+        } else if (size < G) {
+            out << (double(size) / M) << " MiB";
+        } else {
+            out << (double(size) / G) << " GiB";
+        }
+        return out;
+    };
+}
+
+/**
+ * Helper method to extract a string from a StringPool.
+ */
+inline StringPiece16 getString(const android::ResStringPool& pool, size_t idx) {
+    size_t len;
+    const char16_t* str = pool.stringAt(idx, &len);
+    if (str != nullptr) {
+        return StringPiece16(str, len);
+    }
+    return StringPiece16();
+}
+
+class StringBuilder {
+public:
+    StringBuilder& append(const StringPiece16& str);
+    const std::u16string& str() const;
+    const std::string& error() const;
+    operator bool() const;
+
+private:
+    std::u16string mStr;
+    bool mQuote = false;
+    bool mTrailingSpace = false;
+    std::string mError;
+};
+
+inline const std::u16string& StringBuilder::str() const {
+    return mStr;
+}
+
+inline const std::string& StringBuilder::error() const {
+    return mError;
+}
+
+inline StringBuilder::operator bool() const {
+    return mError.empty();
+}
+
+/**
+ * Converts a UTF8 string to a UTF16 string.
+ */
+std::u16string utf8ToUtf16(const StringPiece& utf8);
+std::string utf16ToUtf8(const StringPiece16& utf8);
+
+/**
+ * Writes the entire BigBuffer to the output stream.
+ */
+bool writeAll(std::ostream& out, const BigBuffer& buffer);
+
+/*
+ * Copies the entire BigBuffer into a single buffer.
+ */
+std::unique_ptr<uint8_t[]> copy(const BigBuffer& buffer);
+
+/**
+ * A Tokenizer implemented as an iterable collection. It does not allocate
+ * any memory on the heap nor use standard containers.
+ */
+template <typename Char>
+class Tokenizer {
+public:
+    class iterator {
+    public:
+        iterator(const iterator&) = default;
+        iterator& operator=(const iterator&) = default;
+
+        iterator& operator++();
+        BasicStringPiece<Char> operator*();
+        bool operator==(const iterator& rhs) const;
+        bool operator!=(const iterator& rhs) const;
+
+    private:
+        friend class Tokenizer<Char>;
+
+        iterator(BasicStringPiece<Char> s, Char sep, BasicStringPiece<Char> tok);
+
+        BasicStringPiece<Char> str;
+        Char separator;
+        BasicStringPiece<Char> token;
+    };
+
+    Tokenizer(BasicStringPiece<Char> str, Char sep);
+    iterator begin();
+    iterator end();
+
+private:
+    const iterator mBegin;
+    const iterator mEnd;
+};
+
+template <typename Char>
+inline Tokenizer<Char> tokenize(BasicStringPiece<Char> str, Char sep) {
+    return Tokenizer<Char>(str, sep);
+}
+
+template <typename Char>
+typename Tokenizer<Char>::iterator& Tokenizer<Char>::iterator::operator++() {
+    const Char* start = token.end();
+    const Char* end = str.end();
+    if (start == end) {
+        token.assign(token.end(), 0);
+        return *this;
+    }
+
+    start += 1;
+    const Char* current = start;
+    while (current != end) {
+        if (*current == separator) {
+            token.assign(start, current - start);
+            return *this;
+        }
+        ++current;
+    }
+    token.assign(start, end - start);
+    return *this;
+}
+
+template <typename Char>
+inline BasicStringPiece<Char> Tokenizer<Char>::iterator::operator*() {
+    return token;
+}
+
+template <typename Char>
+inline bool Tokenizer<Char>::iterator::operator==(const iterator& rhs) const {
+    // We check equality here a bit differently.
+    // We need to know that the addresses are the same.
+    return token.begin() == rhs.token.begin() && token.end() == rhs.token.end();
+}
+
+template <typename Char>
+inline bool Tokenizer<Char>::iterator::operator!=(const iterator& rhs) const {
+    return !(*this == rhs);
+}
+
+template <typename Char>
+inline Tokenizer<Char>::iterator::iterator(BasicStringPiece<Char> s, Char sep,
+                                           BasicStringPiece<Char> tok) :
+        str(s), separator(sep), token(tok) {
+}
+
+template <typename Char>
+inline typename Tokenizer<Char>::iterator Tokenizer<Char>::begin() {
+    return mBegin;
+}
+
+template <typename Char>
+inline typename Tokenizer<Char>::iterator Tokenizer<Char>::end() {
+    return mEnd;
+}
+
+template <typename Char>
+inline Tokenizer<Char>::Tokenizer(BasicStringPiece<Char> str, Char sep) :
+        mBegin(++iterator(str, sep, BasicStringPiece<Char>(str.begin() - 1, 0))),
+        mEnd(str, sep, BasicStringPiece<Char>(str.end(), 0)) {
+}
+
+} // namespace util
+
+/**
+ * Stream operator for functions. Calls the function with the stream as an argument.
+ * In the aapt namespace for lookup.
+ */
+inline ::std::ostream& operator<<(::std::ostream& out,
+                                  ::std::function<::std::ostream&(::std::ostream&)> f) {
+    return f(out);
+}
+
+} // namespace aapt
+
+#endif // AAPT_UTIL_H
diff --git a/tools/aapt2/Util_test.cpp b/tools/aapt2/Util_test.cpp
new file mode 100644
index 0000000..7dbe7e0
--- /dev/null
+++ b/tools/aapt2/Util_test.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <string>
+
+#include "StringPiece.h"
+#include "Util.h"
+
+namespace aapt {
+
+TEST(UtilTest, TrimOnlyWhitespace) {
+    const std::u16string full = u"\n        ";
+
+    StringPiece16 trimmed = util::trimWhitespace(full);
+    EXPECT_TRUE(trimmed.empty());
+    EXPECT_EQ(0u, trimmed.size());
+}
+
+TEST(UtilTest, StringEndsWith) {
+    EXPECT_TRUE(util::stringEndsWith("hello.xml", ".xml"));
+}
+
+TEST(UtilTest, StringBuilderWhitespaceRemoval) {
+    EXPECT_EQ(StringPiece16(u"hey guys this is so cool"),
+            util::StringBuilder().append(u"    hey guys ")
+                                 .append(u" this is so cool ")
+                                 .str());
+
+    EXPECT_EQ(StringPiece16(u" wow,  so many \t spaces. what?"),
+            util::StringBuilder().append(u" \" wow,  so many \t ")
+                                 .append(u"spaces. \"what? ")
+                                 .str());
+
+    EXPECT_EQ(StringPiece16(u"where is the pie?"),
+            util::StringBuilder().append(u"  where \t ")
+                                 .append(u" \nis the "" pie?")
+                                 .str());
+}
+
+TEST(UtilTest, StringBuilderEscaping) {
+    EXPECT_EQ(StringPiece16(u"hey guys\n this \t is so\\ cool"),
+            util::StringBuilder().append(u"    hey guys\\n ")
+                                 .append(u" this \\t is so\\\\ cool ")
+                                 .str());
+
+    EXPECT_EQ(StringPiece16(u"@?#\\\'"),
+            util::StringBuilder().append(u"\\@\\?\\#\\\\\\'")
+                                 .str());
+}
+
+TEST(UtilTest, StringBuilderMisplacedQuote) {
+    util::StringBuilder builder{};
+    EXPECT_FALSE(builder.append(u"they're coming!"));
+}
+
+TEST(UtilTest, StringBuilderUnicodeCodes) {
+    EXPECT_EQ(StringPiece16(u"\u00AF\u0AF0 woah"),
+            util::StringBuilder().append(u"\\u00AF\\u0AF0 woah")
+                                 .str());
+
+    EXPECT_FALSE(util::StringBuilder().append(u"\\u00 yo"));
+}
+
+TEST(UtilTest, TokenizeInput) {
+    auto tokenizer = util::tokenize(StringPiece16(u"this| is|the|end"), u'|');
+    auto iter = tokenizer.begin();
+    ASSERT_EQ(*iter, StringPiece16(u"this"));
+    ++iter;
+    ASSERT_EQ(*iter, StringPiece16(u" is"));
+    ++iter;
+    ASSERT_EQ(*iter, StringPiece16(u"the"));
+    ++iter;
+    ASSERT_EQ(*iter, StringPiece16(u"end"));
+    ++iter;
+    ASSERT_EQ(tokenizer.end(), iter);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/XliffXmlPullParser.cpp b/tools/aapt2/XliffXmlPullParser.cpp
new file mode 100644
index 0000000..f0950a3
--- /dev/null
+++ b/tools/aapt2/XliffXmlPullParser.cpp
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+#include "XliffXmlPullParser.h"
+
+#include <string>
+
+namespace aapt {
+
+XliffXmlPullParser::XliffXmlPullParser(const std::shared_ptr<XmlPullParser>& parser) :
+        mParser(parser) {
+}
+
+XmlPullParser::Event XliffXmlPullParser::next() {
+    while (XmlPullParser::isGoodEvent(mParser->next())) {
+        Event event = mParser->getEvent();
+        if (event != Event::kStartElement && event != Event::kEndElement) {
+            break;
+        }
+
+        if (mParser->getElementNamespace() !=
+                u"urn:oasis:names:tc:xliff:document:1.2") {
+            break;
+        }
+
+        const std::u16string& name = mParser->getElementName();
+        if (name != u"bpt"
+                && name != u"ept"
+                && name != u"it"
+                && name != u"ph"
+                && name != u"g"
+                && name != u"bx"
+                && name != u"ex"
+                && name != u"x") {
+            break;
+        }
+
+        // We hit a tag that was ignored, so get the next event.
+    }
+    return mParser->getEvent();
+}
+
+XmlPullParser::Event XliffXmlPullParser::getEvent() const {
+    return mParser->getEvent();
+}
+
+const std::string& XliffXmlPullParser::getLastError() const {
+    return mParser->getLastError();
+}
+
+const std::u16string& XliffXmlPullParser::getComment() const {
+    return mParser->getComment();
+}
+
+size_t XliffXmlPullParser::getLineNumber() const {
+    return mParser->getLineNumber();
+}
+
+size_t XliffXmlPullParser::getDepth() const {
+    return mParser->getDepth();
+}
+
+const std::u16string& XliffXmlPullParser::getText() const {
+    return mParser->getText();
+}
+
+const std::u16string& XliffXmlPullParser::getNamespacePrefix() const {
+    return mParser->getNamespacePrefix();
+}
+
+const std::u16string& XliffXmlPullParser::getNamespaceUri() const {
+    return mParser->getNamespaceUri();
+}
+
+const std::u16string& XliffXmlPullParser::getElementNamespace() const {
+    return mParser->getElementNamespace();
+}
+
+const std::u16string& XliffXmlPullParser::getElementName() const {
+    return mParser->getElementName();
+}
+
+size_t XliffXmlPullParser::getAttributeCount() const {
+    return mParser->getAttributeCount();
+}
+
+XmlPullParser::const_iterator XliffXmlPullParser::beginAttributes() const {
+    return mParser->beginAttributes();
+}
+
+XmlPullParser::const_iterator XliffXmlPullParser::endAttributes() const {
+    return mParser->endAttributes();
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/XliffXmlPullParser.h b/tools/aapt2/XliffXmlPullParser.h
new file mode 100644
index 0000000..d4aa222
--- /dev/null
+++ b/tools/aapt2/XliffXmlPullParser.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_XLIFF_XML_PULL_PARSER_H
+#define AAPT_XLIFF_XML_PULL_PARSER_H
+
+#include "XmlPullParser.h"
+
+#include <memory>
+#include <string>
+
+namespace aapt {
+
+/**
+ * Strips xliff elements and provides the caller with a view of the
+ * underlying XML without xliff.
+ */
+class XliffXmlPullParser : public XmlPullParser {
+public:
+    XliffXmlPullParser(const std::shared_ptr<XmlPullParser>& parser);
+    XliffXmlPullParser(const XliffXmlPullParser& rhs) = delete;
+
+    Event getEvent() const;
+    const std::string& getLastError() const;
+    Event next();
+
+    const std::u16string& getComment() const;
+    size_t getLineNumber() const;
+    size_t getDepth() const;
+
+    const std::u16string& getText() const;
+
+    const std::u16string& getNamespacePrefix() const;
+    const std::u16string& getNamespaceUri() const;
+
+    const std::u16string& getElementNamespace() const;
+    const std::u16string& getElementName() const;
+
+    const_iterator beginAttributes() const;
+    const_iterator endAttributes() const;
+    size_t getAttributeCount() const;
+
+private:
+    std::shared_ptr<XmlPullParser> mParser;
+};
+
+} // namespace aapt
+
+#endif // AAPT_XLIFF_XML_PULL_PARSER_H
diff --git a/tools/aapt2/XliffXmlPullParser_test.cpp b/tools/aapt2/XliffXmlPullParser_test.cpp
new file mode 100644
index 0000000..f9030724
--- /dev/null
+++ b/tools/aapt2/XliffXmlPullParser_test.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#include "SourceXmlPullParser.h"
+#include "XliffXmlPullParser.h"
+
+#include <gtest/gtest.h>
+#include <sstream>
+#include <string>
+
+namespace aapt {
+
+TEST(XliffXmlPullParserTest, IgnoreXliffTags) {
+    std::stringstream input;
+    input << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl
+          << "<resources xmlns:xliff=\"urn:oasis:names:tc:xliff:document:1.2\">" << std::endl
+          << "<string name=\"foo\">"
+          << "Hey <xliff:g><xliff:it>there</xliff:it></xliff:g> world</string>" << std::endl
+          << "</resources>" << std::endl;
+    std::shared_ptr<XmlPullParser> sourceParser = std::make_shared<SourceXmlPullParser>(input);
+    XliffXmlPullParser parser(sourceParser);
+    EXPECT_EQ(XmlPullParser::Event::kStartDocument, parser.getEvent());
+
+    EXPECT_EQ(XmlPullParser::Event::kStartNamespace, parser.next());
+    EXPECT_EQ(parser.getNamespaceUri(), u"urn:oasis:names:tc:xliff:document:1.2");
+    EXPECT_EQ(parser.getNamespacePrefix(), u"xliff");
+
+    EXPECT_EQ(XmlPullParser::Event::kStartElement, parser.next());
+    EXPECT_EQ(parser.getElementNamespace(), u"");
+    EXPECT_EQ(parser.getElementName(), u"resources");
+    EXPECT_EQ(XmlPullParser::Event::kText, parser.next()); // Account for newline/whitespace.
+
+    EXPECT_EQ(XmlPullParser::Event::kStartElement, parser.next());
+    EXPECT_EQ(parser.getElementNamespace(), u"");
+    EXPECT_EQ(parser.getElementName(), u"string");
+
+    EXPECT_EQ(XmlPullParser::Event::kText, parser.next());
+    EXPECT_EQ(parser.getText(), u"Hey ");
+
+    EXPECT_EQ(XmlPullParser::Event::kText, parser.next());
+    EXPECT_EQ(parser.getText(), u"there");
+
+    EXPECT_EQ(XmlPullParser::Event::kText, parser.next());
+    EXPECT_EQ(parser.getText(), u" world");
+
+    EXPECT_EQ(XmlPullParser::Event::kEndElement, parser.next());
+    EXPECT_EQ(parser.getElementNamespace(), u"");
+    EXPECT_EQ(parser.getElementName(), u"string");
+    EXPECT_EQ(XmlPullParser::Event::kText, parser.next()); // Account for newline/whitespace.
+
+    EXPECT_EQ(XmlPullParser::Event::kEndElement, parser.next());
+    EXPECT_EQ(parser.getElementNamespace(), u"");
+    EXPECT_EQ(parser.getElementName(), u"resources");
+
+    EXPECT_EQ(XmlPullParser::Event::kEndNamespace, parser.next());
+    EXPECT_EQ(parser.getNamespacePrefix(), u"xliff");
+    EXPECT_EQ(parser.getNamespaceUri(), u"urn:oasis:names:tc:xliff:document:1.2");
+
+    EXPECT_EQ(XmlPullParser::Event::kEndDocument, parser.next());
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/XmlFlattener.cpp b/tools/aapt2/XmlFlattener.cpp
new file mode 100644
index 0000000..b6ca6d5
--- /dev/null
+++ b/tools/aapt2/XmlFlattener.cpp
@@ -0,0 +1,437 @@
+/*
+ * 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.
+ */
+
+#include "BigBuffer.h"
+#include "Logger.h"
+#include "Maybe.h"
+#include "Resolver.h"
+#include "Resource.h"
+#include "ResourceParser.h"
+#include "ResourceValues.h"
+#include "SdkConstants.h"
+#include "Source.h"
+#include "StringPool.h"
+#include "Util.h"
+#include "XmlFlattener.h"
+
+#include <androidfw/ResourceTypes.h>
+#include <limits>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace aapt {
+
+struct AttributeValueFlattener : ValueVisitor {
+    struct Args : ValueVisitorArgs {
+        Args(std::shared_ptr<Resolver> r, SourceLogger& s, android::Res_value& oV,
+                std::shared_ptr<XmlPullParser> p, bool& e, StringPool::Ref& rV,
+                std::vector<std::pair<StringPool::Ref, android::ResStringPool_ref*>>& sR) :
+                resolver(r), logger(s), outValue(oV), parser(p), error(e), rawValue(rV),
+                stringRefs(sR) {
+        }
+
+        std::shared_ptr<Resolver> resolver;
+        SourceLogger& logger;
+        android::Res_value& outValue;
+        std::shared_ptr<XmlPullParser> parser;
+        bool& error;
+        StringPool::Ref& rawValue;
+        std::vector<std::pair<StringPool::Ref, android::ResStringPool_ref*>>& stringRefs;
+    };
+
+    void visit(Reference& reference, ValueVisitorArgs& a) override {
+        Args& args = static_cast<Args&>(a);
+
+        Maybe<ResourceId> result = args.resolver->findId(reference.name);
+        if (!result || !result.value().isValid()) {
+            args.logger.error(args.parser->getLineNumber())
+                    << "unresolved reference '"
+                    << reference.name
+                    << "'."
+                    << std::endl;
+            args.error = true;
+        } else {
+            reference.id = result.value();
+            reference.flatten(args.outValue);
+        }
+    }
+
+    void visit(String& string, ValueVisitorArgs& a) override {
+        Args& args = static_cast<Args&>(a);
+
+        args.outValue.dataType = android::Res_value::TYPE_STRING;
+        args.stringRefs.emplace_back(args.rawValue,
+                reinterpret_cast<android::ResStringPool_ref*>(&args.outValue.data));
+    }
+
+    void visitItem(Item& item, ValueVisitorArgs& a) override {
+        Args& args = static_cast<Args&>(a);
+        item.flatten(args.outValue);
+    }
+};
+
+struct XmlAttribute {
+    uint32_t resourceId;
+    const XmlPullParser::Attribute* xmlAttr;
+    const Attribute* attr;
+    StringPool::Ref nameRef;
+};
+
+static bool lessAttributeId(const XmlAttribute& a, uint32_t id) {
+    return a.resourceId < id;
+}
+
+XmlFlattener::XmlFlattener(const std::shared_ptr<Resolver>& resolver) : mResolver(resolver) {
+}
+
+/**
+ * Reads events from the parser and writes to a BigBuffer. The binary XML file
+ * expects the StringPool to appear first, but we haven't collected the strings yet. We
+ * write to a temporary BigBuffer while parsing the input, adding strings we encounter
+ * to the StringPool. At the end, we write the StringPool to the given BigBuffer and
+ * then move the data from the temporary BigBuffer into the given one. This incurs no
+ * copies as the given BigBuffer simply takes ownership of the data.
+ */
+Maybe<size_t> XmlFlattener::flatten(const Source& source,
+                                    const std::shared_ptr<XmlPullParser>& parser,
+                                    BigBuffer* outBuffer, Options options) {
+    SourceLogger logger(source);
+    StringPool pool;
+    bool error = false;
+
+    size_t smallestStrippedAttributeSdk = std::numeric_limits<size_t>::max();
+
+    // Attribute names are stored without packages, but we use
+    // their StringPool index to lookup their resource IDs.
+    // This will cause collisions, so we can't dedupe
+    // attribute names from different packages. We use separate
+    // pools that we later combine.
+    std::map<std::u16string, StringPool> packagePools;
+
+    // Attribute resource IDs are stored in the same order
+    // as the attribute names appear in the StringPool.
+    // Since the StringPool contains more than just attribute
+    // names, to maintain a tight packing of resource IDs,
+    // we must ensure that attribute names appear first
+    // in our StringPool. For this, we assign a low priority
+    // (0xffffffff) to non-attribute strings. Attribute
+    // names will be stored along with a priority equal
+    // to their resource ID so that they are ordered.
+    StringPool::Context lowPriority { 0xffffffffu };
+
+    // Once we sort the StringPool, we can assign the updated indices
+    // to the correct data locations.
+    std::vector<std::pair<StringPool::Ref, android::ResStringPool_ref*>> stringRefs;
+
+    // Since we don't know the size of the final StringPool, we write to this
+    // temporary BigBuffer, which we will append to outBuffer later.
+    BigBuffer out(1024);
+    while (XmlPullParser::isGoodEvent(parser->next())) {
+        XmlPullParser::Event event = parser->getEvent();
+        switch (event) {
+            case XmlPullParser::Event::kStartNamespace:
+            case XmlPullParser::Event::kEndNamespace: {
+                const size_t startIndex = out.size();
+                android::ResXMLTree_node* node = out.nextBlock<android::ResXMLTree_node>();
+                if (event == XmlPullParser::Event::kStartNamespace) {
+                    node->header.type = android::RES_XML_START_NAMESPACE_TYPE;
+                } else {
+                    node->header.type = android::RES_XML_END_NAMESPACE_TYPE;
+                }
+
+                node->header.headerSize = sizeof(*node);
+                node->lineNumber = parser->getLineNumber();
+                node->comment.index = -1;
+
+                android::ResXMLTree_namespaceExt* ns =
+                        out.nextBlock<android::ResXMLTree_namespaceExt>();
+                stringRefs.emplace_back(
+                        pool.makeRef(parser->getNamespacePrefix(), lowPriority), &ns->prefix);
+                stringRefs.emplace_back(
+                        pool.makeRef(parser->getNamespaceUri(), lowPriority), &ns->uri);
+
+                out.align4();
+                node->header.size = out.size() - startIndex;
+                break;
+            }
+
+            case XmlPullParser::Event::kStartElement: {
+                const size_t startIndex = out.size();
+                android::ResXMLTree_node* node = out.nextBlock<android::ResXMLTree_node>();
+                node->header.type = android::RES_XML_START_ELEMENT_TYPE;
+                node->header.headerSize = sizeof(*node);
+                node->lineNumber = parser->getLineNumber();
+                node->comment.index = -1;
+
+                android::ResXMLTree_attrExt* elem = out.nextBlock<android::ResXMLTree_attrExt>();
+                stringRefs.emplace_back(
+                        pool.makeRef(parser->getElementNamespace(), lowPriority), &elem->ns);
+                stringRefs.emplace_back(
+                        pool.makeRef(parser->getElementName(), lowPriority), &elem->name);
+                elem->attributeStart = sizeof(*elem);
+                elem->attributeSize = sizeof(android::ResXMLTree_attribute);
+
+                // The resource system expects attributes to be sorted by resource ID.
+                std::vector<XmlAttribute> sortedAttributes;
+                uint32_t nextAttributeId = 0;
+                const auto endAttrIter = parser->endAttributes();
+                for (auto attrIter = parser->beginAttributes();
+                     attrIter != endAttrIter;
+                     ++attrIter) {
+                    uint32_t id;
+                    StringPool::Ref nameRef;
+                    const Attribute* attr = nullptr;
+                    if (attrIter->namespaceUri.empty()) {
+                        // Attributes that have no resource ID (because they don't belong to a
+                        // package) should appear after those that do have resource IDs. Assign
+                        // them some/ integer value that will appear after.
+                        id = 0x80000000u | nextAttributeId++;
+                        nameRef = pool.makeRef(attrIter->name, StringPool::Context{ id });
+                    } else {
+                        StringPiece16 package;
+                        if (attrIter->namespaceUri == u"http://schemas.android.com/apk/res-auto") {
+                            package = mResolver->getDefaultPackage();
+                        } else {
+                            // TODO(adamlesinski): Extract package from namespace.
+                            // The package name appears like so:
+                            // http://schemas.android.com/apk/res/<package name>
+                            package = u"android";
+                        }
+
+                        // Find the Attribute object via our Resolver.
+                        ResourceName attrName = {
+                                package.toString(), ResourceType::kAttr, attrIter->name };
+                        Maybe<Resolver::Entry> result = mResolver->findAttribute(attrName);
+                        if (!result || !result.value().id.isValid()) {
+                            logger.error(parser->getLineNumber())
+                                    << "unresolved attribute '"
+                                    << attrName
+                                    << "'."
+                                    << std::endl;
+                            error = true;
+                            continue;
+                        }
+
+                        if (!result.value().attr) {
+                            logger.error(parser->getLineNumber())
+                                    << "not a valid attribute '"
+                                    << attrName
+                                    << "'."
+                                    << std::endl;
+                            error = true;
+                            continue;
+                        }
+
+                        if (options.maxSdkAttribute && package == u"android") {
+                            size_t sdkVersion = findAttributeSdkLevel(attrIter->name);
+                            if (sdkVersion > options.maxSdkAttribute.value()) {
+                                // We will silently omit this attribute
+                                smallestStrippedAttributeSdk =
+                                        std::min(smallestStrippedAttributeSdk, sdkVersion);
+                                continue;
+                            }
+                        }
+
+                        id = result.value().id.id;
+                        attr = result.value().attr;
+
+                        // Put the attribute name into a package specific pool, since we don't
+                        // want to collapse names from different packages.
+                        nameRef = packagePools[package.toString()].makeRef(
+                                attrIter->name, StringPool::Context{ id });
+                    }
+
+                    // Insert the attribute into the sorted vector.
+                    auto iter = std::lower_bound(sortedAttributes.begin(), sortedAttributes.end(),
+                                                 id, lessAttributeId);
+                    sortedAttributes.insert(iter, XmlAttribute{ id, &*attrIter, attr, nameRef });
+                }
+
+                if (error) {
+                    break;
+                }
+
+                // Now that we have filtered out some attributes, get the final count.
+                elem->attributeCount = sortedAttributes.size();
+
+                // Flatten the sorted attributes.
+                for (auto entry : sortedAttributes) {
+                    android::ResXMLTree_attribute* attr =
+                            out.nextBlock<android::ResXMLTree_attribute>();
+                    stringRefs.emplace_back(
+                            pool.makeRef(entry.xmlAttr->namespaceUri, lowPriority), &attr->ns);
+                    StringPool::Ref rawValueRef = pool.makeRef(entry.xmlAttr->value, lowPriority);
+                    stringRefs.emplace_back(rawValueRef, &attr->rawValue);
+                    stringRefs.emplace_back(entry.nameRef, &attr->name);
+
+                    if (entry.attr) {
+                        std::unique_ptr<Item> value = ResourceParser::parseItemForAttribute(
+                                entry.xmlAttr->value, *entry.attr, mResolver->getDefaultPackage());
+                        if (value) {
+                            AttributeValueFlattener flattener;
+                            value->accept(flattener, AttributeValueFlattener::Args{
+                                    mResolver,
+                                    logger,
+                                    attr->typedValue,
+                                    parser,
+                                    error,
+                                    rawValueRef,
+                                    stringRefs
+                            });
+                        } else if (!(entry.attr->typeMask & android::ResTable_map::TYPE_STRING)) {
+                            logger.error(parser->getLineNumber())
+                                    << "'"
+                                    << *rawValueRef
+                                    << "' is not compatible with attribute "
+                                    << *entry.attr
+                                    << "."
+                                    << std::endl;
+                            error = true;
+                        } else {
+                            attr->typedValue.dataType = android::Res_value::TYPE_STRING;
+                            stringRefs.emplace_back(rawValueRef,
+                                    reinterpret_cast<android::ResStringPool_ref*>(
+                                            &attr->typedValue.data));
+                        }
+                    } else {
+                        attr->typedValue.dataType = android::Res_value::TYPE_STRING;
+                        stringRefs.emplace_back(rawValueRef,
+                                reinterpret_cast<android::ResStringPool_ref*>(
+                                        &attr->typedValue.data));
+                    }
+                    attr->typedValue.size = sizeof(attr->typedValue);
+                }
+
+                out.align4();
+                node->header.size = out.size() - startIndex;
+                break;
+            }
+
+            case XmlPullParser::Event::kEndElement: {
+                const size_t startIndex = out.size();
+                android::ResXMLTree_node* node = out.nextBlock<android::ResXMLTree_node>();
+                node->header.type = android::RES_XML_END_ELEMENT_TYPE;
+                node->header.headerSize = sizeof(*node);
+                node->lineNumber = parser->getLineNumber();
+                node->comment.index = -1;
+
+                android::ResXMLTree_endElementExt* elem =
+                        out.nextBlock<android::ResXMLTree_endElementExt>();
+                stringRefs.emplace_back(
+                        pool.makeRef(parser->getElementNamespace(), lowPriority), &elem->ns);
+                stringRefs.emplace_back(
+                        pool.makeRef(parser->getElementName(), lowPriority), &elem->name);
+
+                out.align4();
+                node->header.size = out.size() - startIndex;
+                break;
+            }
+
+            case XmlPullParser::Event::kText: {
+                StringPiece16 text = util::trimWhitespace(parser->getText());
+                if (text.empty()) {
+                    break;
+                }
+
+                const size_t startIndex = out.size();
+                android::ResXMLTree_node* node = out.nextBlock<android::ResXMLTree_node>();
+                node->header.type = android::RES_XML_CDATA_TYPE;
+                node->header.headerSize = sizeof(*node);
+                node->lineNumber = parser->getLineNumber();
+                node->comment.index = -1;
+
+                android::ResXMLTree_cdataExt* elem = out.nextBlock<android::ResXMLTree_cdataExt>();
+                stringRefs.emplace_back(pool.makeRef(text, lowPriority), &elem->data);
+
+                out.align4();
+                node->header.size = out.size() - startIndex;
+                break;
+            }
+
+            default:
+                break;
+        }
+
+    }
+    out.align4();
+
+    if (error) {
+        return {};
+    }
+
+    if (parser->getEvent() == XmlPullParser::Event::kBadDocument) {
+        logger.error(parser->getLineNumber())
+                << parser->getLastError()
+                << std::endl;
+        return {};
+    }
+
+    // Merge the package pools into the main pool.
+    for (auto& packagePoolEntry : packagePools) {
+        pool.merge(std::move(packagePoolEntry.second));
+    }
+
+    // Sort so that attribute resource IDs show up first.
+    pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
+        return a.context.priority < b.context.priority;
+    });
+
+    // Now we flatten the string pool references into the correct places.
+    for (const auto& refEntry : stringRefs) {
+        refEntry.second->index = refEntry.first.getIndex();
+    }
+
+    // Write the XML header.
+    const size_t beforeXmlTreeIndex = outBuffer->size();
+    android::ResXMLTree_header* header = outBuffer->nextBlock<android::ResXMLTree_header>();
+    header->header.type = android::RES_XML_TYPE;
+    header->header.headerSize = sizeof(*header);
+
+    // Write the array of resource IDs, indexed by StringPool order.
+    const size_t beforeResIdMapIndex = outBuffer->size();
+    android::ResChunk_header* resIdMapChunk = outBuffer->nextBlock<android::ResChunk_header>();
+    resIdMapChunk->type = android::RES_XML_RESOURCE_MAP_TYPE;
+    resIdMapChunk->headerSize = sizeof(*resIdMapChunk);
+    for (const auto& str : pool) {
+        ResourceId id { str->context.priority };
+        if (!id.isValid()) {
+            // When we see the first non-resource ID,
+            // we're done.
+            break;
+        }
+
+        uint32_t* flatId = outBuffer->nextBlock<uint32_t>();
+        *flatId = id.id;
+    }
+    resIdMapChunk->size = outBuffer->size() - beforeResIdMapIndex;
+
+    // Flatten the StringPool.
+    StringPool::flattenUtf8(outBuffer, pool);
+
+    // Move the temporary BigBuffer into outBuffer->
+    outBuffer->appendBuffer(std::move(out));
+
+    header->header.size = outBuffer->size() - beforeXmlTreeIndex;
+
+    if (smallestStrippedAttributeSdk == std::numeric_limits<size_t>::max()) {
+        // Nothing was stripped
+        return 0u;
+    }
+    return smallestStrippedAttributeSdk;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/XmlFlattener.h b/tools/aapt2/XmlFlattener.h
new file mode 100644
index 0000000..abf64ab
--- /dev/null
+++ b/tools/aapt2/XmlFlattener.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_XML_FLATTENER_H
+#define AAPT_XML_FLATTENER_H
+
+#include "BigBuffer.h"
+#include "Maybe.h"
+#include "Resolver.h"
+#include "Source.h"
+#include "XmlPullParser.h"
+
+namespace aapt {
+
+/**
+ * Flattens an XML file into a binary representation parseable by
+ * the Android resource system. References to resources are checked
+ * and string values are transformed to typed data where possible.
+ */
+class XmlFlattener {
+public:
+    struct Options {
+        /**
+         * If set, tells the XmlFlattener to strip out
+         * attributes that have been introduced after
+         * max SDK.
+         */
+        Maybe<size_t> maxSdkAttribute;
+    };
+
+    /**
+     * Creates a flattener with a Resolver to resolve references
+     * and attributes.
+     */
+    XmlFlattener(const std::shared_ptr<Resolver>& resolver);
+
+    XmlFlattener(const XmlFlattener&) = delete; // Not copyable.
+
+    /**
+     * Flatten an XML file, reading from the XML parser and writing to the
+     * BigBuffer. The source object is mainly for logging errors. If the
+     * function succeeds, returns the smallest SDK version of an attribute that
+     * was stripped out. If no attributes were stripped out, the return value
+     * is 0.
+     */
+    Maybe<size_t> flatten(const Source& source, const std::shared_ptr<XmlPullParser>& parser,
+                          BigBuffer* outBuffer, Options options);
+
+private:
+    std::shared_ptr<Resolver> mResolver;
+};
+
+} // namespace aapt
+
+#endif // AAPT_XML_FLATTENER_H
diff --git a/tools/aapt2/XmlFlattener_test.cpp b/tools/aapt2/XmlFlattener_test.cpp
new file mode 100644
index 0000000..6e24847
--- /dev/null
+++ b/tools/aapt2/XmlFlattener_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#include "Resolver.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "SourceXmlPullParser.h"
+#include "Util.h"
+#include "XmlFlattener.h"
+
+#include <androidfw/AssetManager.h>
+#include <androidfw/ResourceTypes.h>
+#include <gtest/gtest.h>
+#include <sstream>
+#include <string>
+
+using namespace android;
+
+namespace aapt {
+
+constexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+
+class XmlFlattenerTest : public ::testing::Test {
+public:
+    virtual void SetUp() override {
+        std::shared_ptr<ResourceTable> table = std::make_shared<ResourceTable>();
+        table->setPackage(u"android");
+        table->setPackageId(0x01);
+
+        table->addResource(ResourceName{ {}, ResourceType::kAttr, u"id" },
+                           ResourceId{ 0x01010000 }, {}, {},
+                           util::make_unique<Attribute>(false, ResTable_map::TYPE_ANY));
+
+        table->addResource(ResourceName{ {}, ResourceType::kId, u"test" },
+                           ResourceId{ 0x01020000 }, {}, {}, util::make_unique<Id>());
+
+        mFlattener = std::make_shared<XmlFlattener>(
+                std::make_shared<Resolver>(table, std::make_shared<AssetManager>()));
+    }
+
+    ::testing::AssertionResult testFlatten(std::istream& in, ResXMLTree* outTree) {
+        std::stringstream input(kXmlPreamble);
+        input << in.rdbuf() << std::endl;
+        std::shared_ptr<XmlPullParser> xmlParser = std::make_shared<SourceXmlPullParser>(input);
+        BigBuffer outBuffer(1024);
+        if (!mFlattener->flatten(Source{ "test" }, xmlParser, &outBuffer, {})) {
+            return ::testing::AssertionFailure();
+        }
+
+        std::unique_ptr<uint8_t[]> data = util::copy(outBuffer);
+        if (outTree->setTo(data.get(), outBuffer.size(), true) != NO_ERROR) {
+            return ::testing::AssertionFailure();
+        }
+        return ::testing::AssertionSuccess();
+    }
+
+    std::shared_ptr<XmlFlattener> mFlattener;
+};
+
+TEST_F(XmlFlattenerTest, ParseSimpleView) {
+    std::stringstream input;
+    input << "<View xmlns:android=\"http://schemas.android.com/apk/res/android\"" << std::endl
+          << "      android:id=\"@id/test\">" << std::endl
+          << "</View>" << std::endl;
+
+    ResXMLTree tree;
+    ASSERT_TRUE(testFlatten(input, &tree));
+
+    while (tree.next() != ResXMLTree::END_DOCUMENT) {
+        ASSERT_NE(tree.getEventType(), ResXMLTree::BAD_DOCUMENT);
+    }
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/XmlPullParser.h b/tools/aapt2/XmlPullParser.h
new file mode 100644
index 0000000..753405c
--- /dev/null
+++ b/tools/aapt2/XmlPullParser.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_XML_PULL_PARSER_H
+#define AAPT_XML_PULL_PARSER_H
+
+#include <algorithm>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "StringPiece.h"
+
+namespace aapt {
+
+class XmlPullParser {
+public:
+    enum class Event {
+        kBadDocument,
+        kStartDocument,
+        kEndDocument,
+
+        kStartNamespace,
+        kEndNamespace,
+        kStartElement,
+        kEndElement,
+        kText,
+        kComment,
+    };
+
+    static void skipCurrentElement(XmlPullParser* parser);
+    static bool isGoodEvent(Event event);
+
+    virtual ~XmlPullParser() {}
+
+    /**
+     * Returns the current event that is being processed.
+     */
+    virtual Event getEvent() const = 0;
+
+    virtual const std::string& getLastError() const = 0;
+
+    /**
+     * Note, unlike XmlPullParser, the first call to next() will return
+     * StartElement of the first element.
+     */
+    virtual Event next() = 0;
+
+    //
+    // These are available for all nodes.
+    //
+
+    virtual const std::u16string& getComment() const = 0;
+    virtual size_t getLineNumber() const = 0;
+    virtual size_t getDepth() const = 0;
+
+    /**
+     * Returns the character data for a Text event.
+     */
+    virtual const std::u16string& getText() const = 0;
+
+    /**
+     * Namespace prefix is available for StartNamespace and EndNamespace.
+     */
+    virtual const std::u16string& getNamespacePrefix() const = 0;
+
+    /**
+     * Namespace URI is available for StartNamespace.
+     */
+    virtual const std::u16string& getNamespaceUri() const = 0;
+
+    //
+    // These are available for StartElement and EndElement.
+    //
+
+    virtual const std::u16string& getElementNamespace() const = 0;
+    virtual const std::u16string& getElementName() const = 0;
+
+    //
+    // Remaining methods are for retrieving information about attributes
+    // associated with a StartElement.
+    //
+    // Attributes must be in sorted order (according to the less than operator
+    // of struct Attribute).
+    //
+
+    struct Attribute {
+        std::u16string namespaceUri;
+        std::u16string name;
+        std::u16string value;
+
+        int compare(const Attribute& rhs) const;
+        bool operator<(const Attribute& rhs) const;
+        bool operator==(const Attribute& rhs) const;
+        bool operator!=(const Attribute& rhs) const;
+    };
+
+    using const_iterator = std::vector<Attribute>::const_iterator;
+
+    virtual const_iterator beginAttributes() const = 0;
+    virtual const_iterator endAttributes() const = 0;
+    virtual size_t getAttributeCount() const = 0;
+    const_iterator findAttribute(StringPiece16 namespaceUri, StringPiece16 name) const;
+};
+
+//
+// Implementation
+//
+
+inline ::std::ostream& operator<<(::std::ostream& out, XmlPullParser::Event event) {
+    switch (event) {
+        case XmlPullParser::Event::kBadDocument: return out << "BadDocument";
+        case XmlPullParser::Event::kStartDocument: return out << "StartDocument";
+        case XmlPullParser::Event::kEndDocument: return out << "EndDocument";
+        case XmlPullParser::Event::kStartNamespace: return out << "StartNamespace";
+        case XmlPullParser::Event::kEndNamespace: return out << "EndNamespace";
+        case XmlPullParser::Event::kStartElement: return out << "StartElement";
+        case XmlPullParser::Event::kEndElement: return out << "EndElement";
+        case XmlPullParser::Event::kText: return out << "Text";
+        case XmlPullParser::Event::kComment: return out << "Comment";
+    }
+    return out;
+}
+
+inline void XmlPullParser::skipCurrentElement(XmlPullParser* parser) {
+    int depth = 1;
+    while (depth > 0) {
+        switch (parser->next()) {
+            case Event::kEndDocument:
+            case Event::kBadDocument:
+                return;
+            case Event::kStartElement:
+                depth++;
+                break;
+            case Event::kEndElement:
+                depth--;
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+inline bool XmlPullParser::isGoodEvent(XmlPullParser::Event event) {
+    return event != Event::kBadDocument && event != Event::kEndDocument;
+}
+
+inline int XmlPullParser::Attribute::compare(const Attribute& rhs) const {
+    int cmp = namespaceUri.compare(rhs.namespaceUri);
+    if (cmp != 0) return cmp;
+    return name.compare(rhs.name);
+}
+
+inline bool XmlPullParser::Attribute::operator<(const Attribute& rhs) const {
+    return compare(rhs) < 0;
+}
+
+inline bool XmlPullParser::Attribute::operator==(const Attribute& rhs) const {
+    return compare(rhs) == 0;
+}
+
+inline bool XmlPullParser::Attribute::operator!=(const Attribute& rhs) const {
+    return compare(rhs) != 0;
+}
+
+inline XmlPullParser::const_iterator XmlPullParser::findAttribute(StringPiece16 namespaceUri,
+                                                                  StringPiece16 name) const {
+    const auto endIter = endAttributes();
+    const auto iter = std::lower_bound(beginAttributes(), endIter,
+            std::pair<StringPiece16, StringPiece16>(namespaceUri, name),
+            [](const Attribute& attr, const std::pair<StringPiece16, StringPiece16>& rhs) -> bool {
+                int cmp = attr.namespaceUri.compare(0, attr.namespaceUri.size(),
+                        rhs.first.data(), rhs.first.size());
+                if (cmp < 0) return true;
+                if (cmp > 0) return false;
+                cmp = attr.name.compare(0, attr.name.size(), rhs.second.data(), rhs.second.size());
+                if (cmp < 0) return true;
+                return false;
+            }
+    );
+
+    if (iter != endIter && namespaceUri == iter->namespaceUri && name == iter->name) {
+        return iter;
+    }
+    return endIter;
+}
+
+} // namespace aapt
+
+#endif // AAPT_XML_PULL_PARSER_H
diff --git a/tools/aapt2/data/AndroidManifest.xml b/tools/aapt2/data/AndroidManifest.xml
new file mode 100644
index 0000000..c017a0d
--- /dev/null
+++ b/tools/aapt2/data/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.app">
+    <application>
+    </application>
+</manifest>
diff --git a/tools/aapt2/data/res/drawable/image.xml b/tools/aapt2/data/res/drawable/image.xml
new file mode 100644
index 0000000..9b38739
--- /dev/null
+++ b/tools/aapt2/data/res/drawable/image.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector />
diff --git a/tools/aapt2/data/res/layout/main.xml b/tools/aapt2/data/res/layout/main.xml
new file mode 100644
index 0000000..e0b55c0
--- /dev/null
+++ b/tools/aapt2/data/res/layout/main.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/view"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+    <View xmlns:app="http://schemas.android.com/apk/res-auto"
+        android:id="@+id/me"
+        android:layout_width="1dp"
+        android:layout_height="match_parent"
+        app:layout_width="false"
+        app:flags="complex|weak"
+        android:colorAccent="#ffffff"/>
+</LinearLayout>
diff --git a/tools/aapt2/data/res/values-v4/styles.xml b/tools/aapt2/data/res/values-v4/styles.xml
new file mode 100644
index 0000000..979a82a
--- /dev/null
+++ b/tools/aapt2/data/res/values-v4/styles.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="App" parent="android:Theme.Material">
+        <item name="android:colorAccent">@color/accent</item>
+        <item name="android:text">Hey</item>
+    </style>
+</resources>
diff --git a/tools/aapt2/data/res/values/colors.xml b/tools/aapt2/data/res/values/colors.xml
new file mode 100644
index 0000000..89db5fb
--- /dev/null
+++ b/tools/aapt2/data/res/values/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="primary">#f44336</color>
+    <color name="primary_dark">#b71c1c</color>
+    <color name="accent">#fdd835</color>
+</resources>
diff --git a/tools/aapt2/data/res/values/styles.xml b/tools/aapt2/data/res/values/styles.xml
new file mode 100644
index 0000000..71ce388
--- /dev/null
+++ b/tools/aapt2/data/res/values/styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="App" parent="android:Theme.Material">
+        <item name="android:background">@color/primary</item>
+        <item name="android:colorPrimary">@color/primary</item>
+        <item name="android:colorPrimaryDark">@color/primary_dark</item>
+        <item name="android:colorAccent">@color/accent</item>
+    </style>
+    <attr name="custom" format="reference" />
+    <style name="Pop">
+        <item name="custom">@drawable/image</item>
+    </style>
+    <string name="yo">@string/wow</string>
+
+    <declare-styleable name="View">
+        <attr name="custom" />
+        <attr name="decor">
+            <enum name="no-border" value="0"/>
+            <enum name="border" value="1"/>
+            <enum name="shadow" value="2"/>
+        </attr>
+    </declare-styleable>
+
+</resources>
diff --git a/tools/aapt2/data/res/values/test.xml b/tools/aapt2/data/res/values/test.xml
new file mode 100644
index 0000000..d3ead34
--- /dev/null
+++ b/tools/aapt2/data/res/values/test.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="hooha"><font bgcolor="#ffffff">Hey guys!</font> <xliff:g>My</xliff:g> name is <b>Adam</b>. How <b><i>are</i></b> you?</string>
+    <public name="hooha" type="string" id="0x7f020001"/>
+    <string name="wow">@android:string/ok</string>
+    <public name="image" type="drawable" id="0x7f060000" />
+    <attr name="layout_width" format="boolean" />
+    <attr name="flags">
+        <flag name="complex" value="1" />
+        <flag name="pub" value="2" />
+        <flag name="weak" value="4" />
+    </attr>
+</resources>
diff --git a/tools/aapt2/data/resources.arsc b/tools/aapt2/data/resources.arsc
new file mode 100644
index 0000000..6a416df
--- /dev/null
+++ b/tools/aapt2/data/resources.arsc
Binary files differ
diff --git a/tools/aapt2/data/resources_base.arsc b/tools/aapt2/data/resources_base.arsc
new file mode 100644
index 0000000..f9d0610
--- /dev/null
+++ b/tools/aapt2/data/resources_base.arsc
Binary files differ
diff --git a/tools/aapt2/data/resources_hdpi.arsc b/tools/aapt2/data/resources_hdpi.arsc
new file mode 100644
index 0000000..97232a3
--- /dev/null
+++ b/tools/aapt2/data/resources_hdpi.arsc
Binary files differ
diff --git a/tools/aapt2/process.dot b/tools/aapt2/process.dot
new file mode 100644
index 0000000..a92405d
--- /dev/null
+++ b/tools/aapt2/process.dot
@@ -0,0 +1,92 @@
+digraph aapt {
+    out_package [label="out/default/package.apk"];
+    out_fr_package [label="out/fr/package.apk"];
+    out_table_aligned [label="out/default/resources-aligned.arsc"];
+    out_table_fr_aligned [label="out/fr/resources-aligned.arsc"];
+    out_res_layout_main_xml [label="out/res/layout/main.xml"];
+    out_res_layout_v21_main_xml [color=red,label="out/res/layout-v21/main.xml"];
+    out_res_layout_fr_main_xml [label="out/res/layout-fr/main.xml"];
+    out_res_layout_fr_v21_main_xml [color=red,label="out/res/layout-fr-v21/main.xml"];
+    out_table [label="out/default/resources.arsc"];
+    out_fr_table [label="out/fr/resources.arsc"];
+    out_values_table [label="out/values/resources.arsc"];
+    out_layout_table [label="out/layout/resources.arsc"];
+    out_values_fr_table [label="out/values-fr/resources.arsc"];
+    out_layout_fr_table [label="out/layout-fr/resources.arsc"];
+    res_values_strings_xml [label="res/values/strings.xml"];
+    res_values_attrs_xml [label="res/values/attrs.xml"];
+    res_layout_main_xml [label="res/layout/main.xml"];
+    res_layout_fr_main_xml [label="res/layout-fr/main.xml"];
+    res_values_fr_strings_xml [label="res/values-fr/strings.xml"];
+
+    out_package -> package_default;
+    out_fr_package -> package_fr;
+
+    package_default [shape=box,label="Assemble",color=blue];
+    package_default -> out_table_aligned;
+    package_default -> out_res_layout_main_xml;
+    package_default -> out_res_layout_v21_main_xml [color=red];
+
+    package_fr [shape=box,label="Assemble",color=blue];
+    package_fr -> out_table_fr_aligned;
+    package_fr -> out_res_layout_fr_main_xml;
+    package_fr -> out_res_layout_fr_v21_main_xml [color=red];
+
+    out_table_aligned -> align_tables;
+    out_table_fr_aligned -> align_tables;
+
+    align_tables [shape=box,label="Align",color=blue];
+    align_tables -> out_table;
+    align_tables -> out_fr_table;
+
+    out_table -> link_tables;
+
+    link_tables [shape=box,label="Link",color=blue];
+    link_tables -> out_values_table;
+    link_tables -> out_layout_table;
+
+    out_values_table -> compile_values;
+
+    compile_values [shape=box,label="Collect",color=blue];
+    compile_values -> res_values_strings_xml;
+    compile_values -> res_values_attrs_xml;
+
+    out_layout_table -> collect_xml;
+
+    collect_xml [shape=box,label="Collect",color=blue];
+    collect_xml -> res_layout_main_xml;
+
+    out_fr_table -> link_fr_tables;
+
+    link_fr_tables [shape=box,label="Link",color=blue];
+    link_fr_tables -> out_values_fr_table;
+    link_fr_tables -> out_layout_fr_table;
+
+    out_values_fr_table -> compile_values_fr;
+
+    compile_values_fr [shape=box,label="Compile",color=blue];
+    compile_values_fr -> res_values_fr_strings_xml;
+
+    out_layout_fr_table -> collect_xml_fr;
+
+    collect_xml_fr [shape=box,label="Collect",color=blue];
+    collect_xml_fr -> res_layout_fr_main_xml;
+
+    compile_res_layout_main_xml [shape=box,label="Compile",color=blue];
+
+    out_res_layout_main_xml -> compile_res_layout_main_xml;
+
+    out_res_layout_v21_main_xml -> compile_res_layout_main_xml [color=red];
+
+    compile_res_layout_main_xml -> res_layout_main_xml;
+    compile_res_layout_main_xml -> out_table_aligned;
+
+    compile_res_layout_fr_main_xml [shape=box,label="Compile",color=blue];
+
+    out_res_layout_fr_main_xml -> compile_res_layout_fr_main_xml;
+
+    out_res_layout_fr_v21_main_xml -> compile_res_layout_fr_main_xml [color=red];
+
+    compile_res_layout_fr_main_xml -> res_layout_fr_main_xml;
+    compile_res_layout_fr_main_xml -> out_table_fr_aligned;
+}
diff --git a/tools/aapt2/public_attr_map.py b/tools/aapt2/public_attr_map.py
new file mode 100644
index 0000000..92136a8
--- /dev/null
+++ b/tools/aapt2/public_attr_map.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+
+import sys
+import xml.etree.ElementTree as ET
+
+def findSdkLevelForAttribute(id):
+    intId = int(id, 16)
+    packageId = 0x000000ff & (intId >> 24)
+    typeId = 0x000000ff & (intId >> 16)
+    entryId = 0x0000ffff & intId
+
+    if packageId != 0x01 or typeId != 0x01:
+        return 0
+
+    levels = [(1, 0x021c), (2, 0x021d), (3, 0x0269), (4, 0x028d),
+              (5, 0x02ad), (6, 0x02b3), (7, 0x02b5), (8, 0x02bd),
+              (9, 0x02cb), (11, 0x0361), (12, 0x0366), (13, 0x03a6),
+              (16, 0x03ae), (17, 0x03cc), (18, 0x03da), (19, 0x03f1),
+              (20, 0x03f6), (21, 0x04ce)]
+    for level, attrEntryId in levels:
+        if entryId <= attrEntryId:
+            return level
+    return 22
+
+
+tree = None
+with open(sys.argv[1], 'rt') as f:
+    tree = ET.parse(f)
+
+attrs = []
+for node in tree.iter('public'):
+    if node.get('type') == 'attr':
+        sdkLevel = findSdkLevelForAttribute(node.get('id', '0'))
+        if sdkLevel > 1 and sdkLevel < 22:
+            attrs.append("{{ u\"{}\", {} }}".format(node.get('name'), sdkLevel))
+
+print "#include <string>"
+print "#include <unordered_map>"
+print
+print "namespace aapt {"
+print
+print "static std::unordered_map<std::u16string, size_t> sAttrMap = {"
+print ",\n    ".join(attrs)
+print "};"
+print
+print "size_t findAttributeSdkLevel(const std::u16string& name) {"
+print "    auto iter = sAttrMap.find(name);"
+print "    if (iter != sAttrMap.end()) {"
+print "        return iter->second;"
+print "    }"
+print "    return 0;"
+print "}"
+print
+print "} // namespace aapt"
+print
diff --git a/tools/aapt2/todo.txt b/tools/aapt2/todo.txt
new file mode 100644
index 0000000..acc8bfb
--- /dev/null
+++ b/tools/aapt2/todo.txt
@@ -0,0 +1,29 @@
+XML Files
+X Collect declared IDs
+X Build StringPool
+X Flatten
+
+Resource Table Operations
+X Build Resource Table (with StringPool) from XML.
+X Modify Resource Table.
+X - Copy and transform resources.
+X   - Pre-17/21 attr correction.
+X Perform analysis of types.
+X Flatten.
+X Assign resource IDs.
+X Assign public resource IDs.
+X Merge resource tables
+- Assign private attributes to different typespace.
+- Align resource tables
+
+Splits
+- Collect all resources (ids from layouts).
+- Generate resource table from base resources.
+- Generate resource table from individual resources of the required type.
+- Align resource tables (same type/name = same ID).
+
+Fat Apk
+X Collect all resources (ids from layouts).
+X Generate resource tables for all configurations.
+- Align individual resource tables.
+- Merge resource tables.
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 5c6d870..72ee343 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -26,14 +26,17 @@
 $ apilint.py /tmp/currentblame.txt previous.txt --no-color
 """
 
-import re, sys, collections, traceback
+import re, sys, collections, traceback, argparse
 
 
 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
 
+ALLOW_GOOGLE = False
+USE_COLOR = True
+
 def format(fg=None, bg=None, bright=False, bold=False, dim=False, reset=False):
     # manually derived from http://en.wikipedia.org/wiki/ANSI_escape_code#Codes
-    if "--no-color" in sys.argv: return ""
+    if not USE_COLOR: return ""
     codes = []
     if reset: codes.append("0")
     else:
@@ -976,7 +979,7 @@
     verify_collections(clazz)
     verify_flags(clazz)
     verify_exception(clazz)
-    verify_google(clazz)
+    if not ALLOW_GOOGLE: verify_google(clazz)
     verify_bitset(clazz)
     verify_manager(clazz)
     verify_boxed(clazz)
@@ -1061,11 +1064,30 @@
 
 
 if __name__ == "__main__":
-    with open(sys.argv[1]) as f:
-        cur_fail = examine_stream(f)
+    parser = argparse.ArgumentParser(description="Enforces common Android public API design \
+            patterns. It ignores lint messages from a previous API level, if provided.")
+    parser.add_argument("current.txt", type=argparse.FileType('r'), help="current.txt")
+    parser.add_argument("previous.txt", nargs='?', type=argparse.FileType('r'), default=None,
+            help="previous.txt")
+    parser.add_argument("--no-color", action='store_const', const=True,
+            help="Disable terminal colors")
+    parser.add_argument("--allow-google", action='store_const', const=True,
+            help="Allow references to Google")
+    args = vars(parser.parse_args())
 
-    if len(sys.argv) > 2:
-        with open(sys.argv[2]) as f:
+    if args['no_color']:
+        USE_COLOR = False
+
+    if args['allow_google']:
+        ALLOW_GOOGLE = True
+
+    current_file = args['current.txt']
+    previous_file = args['previous.txt']
+
+    with current_file as f:
+        cur_fail = examine_stream(f)
+    if not previous_file is None:
+        with previous_file as f:
             prev_fail = examine_stream(f)
 
         # ignore errors from previous API level
diff --git a/tools/layoutlib/.idea/libraries/guava.xml b/tools/layoutlib/.idea/libraries/guava.xml
index d47fc06..eb60719 100644
--- a/tools/layoutlib/.idea/libraries/guava.xml
+++ b/tools/layoutlib/.idea/libraries/guava.xml
@@ -1,11 +1,11 @@
 <component name="libraryTable">
   <library name="guava">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/guavalib_intermediates/javalib.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../../../prebuilts/tools/common/m2/repository/com/google/guava/guava/15.0/guava-15.0.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="file://$PROJECT_DIR$/../../../../external/guava/guava/src" />
+      <root url="jar://$PROJECT_DIR$/../../../../prebuilts/tools/common/m2/repository/com/google/guava/guava/15.0/guava-15.0-sources.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml b/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml
index f965ba7..0b22717 100644
--- a/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml
+++ b/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml
@@ -1,5 +1,5 @@
 <component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="All in bridge" type="JUnit" factoryName="JUnit" singleton="true" nameIsGenerated="true">
+  <configuration default="false" name="All in bridge" type="JUnit" factoryName="JUnit" singleton="true">
     <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
     <module name="bridge" />
     <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@@ -8,7 +8,7 @@
     <option name="MAIN_CLASS_NAME" value="" />
     <option name="METHOD_NAME" value="" />
     <option name="TEST_OBJECT" value="package" />
-    <option name="VM_PARAMETERS" value="-ea -Dtest_res.dir=&quot;$PROJECT_DIR$/bridge/tests/res&quot;" />
+    <option name="VM_PARAMETERS" value="-ea" />
     <option name="PARAMETERS" value="" />
     <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
     <option name="ENV_VARIABLES" />
@@ -18,13 +18,7 @@
     </option>
     <envs />
     <patterns />
-    <RunnerSettings RunnerId="Debug">
-      <option name="DEBUG_PORT" value="" />
-      <option name="TRANSPORT" value="0" />
-      <option name="LOCAL" value="true" />
-    </RunnerSettings>
     <RunnerSettings RunnerId="Run" />
-    <ConfigurationWrapper RunnerId="Debug" />
     <ConfigurationWrapper RunnerId="Run" />
     <method />
   </configuration>
diff --git a/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml b/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml
new file mode 100644
index 0000000..4f0eb8d
--- /dev/null
+++ b/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml
@@ -0,0 +1,29 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="Bridge quick" type="JUnit" factoryName="JUnit">
+    <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+    <module name="bridge" />
+    <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+    <option name="ALTERNATIVE_JRE_PATH" value="" />
+    <option name="PACKAGE_NAME" />
+    <option name="MAIN_CLASS_NAME" value="" />
+    <option name="METHOD_NAME" value="" />
+    <option name="TEST_OBJECT" value="pattern" />
+    <option name="VM_PARAMETERS" value="-ea" />
+    <option name="PARAMETERS" value="" />
+    <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+    <option name="ENV_VARIABLES" />
+    <option name="PASS_PARENT_ENVS" value="true" />
+    <option name="TEST_SEARCH_SCOPE">
+      <value defaultName="singleModule" />
+    </option>
+    <envs />
+    <patterns>
+      <pattern testClass="com.android.layoutlib.bridge.TestDelegates" />
+      <pattern testClass="android.graphics.Matrix_DelegateTest" />
+      <pattern testClass="com.android.layoutlib.bridge.android.BridgeXmlBlockParserTest" />
+    </patterns>
+    <RunnerSettings RunnerId="Run" />
+    <ConfigurationWrapper RunnerId="Run" />
+    <method />
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/runConfigurations/Create.xml b/tools/layoutlib/.idea/runConfigurations/Create.xml
index fb0b866..ff173e5 100644
--- a/tools/layoutlib/.idea/runConfigurations/Create.xml
+++ b/tools/layoutlib/.idea/runConfigurations/Create.xml
@@ -5,8 +5,8 @@
     <option name="VM_PARAMETERS" value="" />
     <option name="PROGRAM_PARAMETERS" value="out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/javalib.jar" />
     <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/../../../../" />
-    <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
-    <option name="ALTERNATIVE_JRE_PATH" value="1.6" />
+    <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+    <option name="ALTERNATIVE_JRE_PATH" value="" />
     <option name="ENABLE_SWING_INSPECTOR" value="false" />
     <option name="ENV_VARIABLES" />
     <option name="PASS_PARENT_ENVS" value="true" />
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index be75dde..4d2d100 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -675,7 +675,7 @@
                             graphics.fillRoundRect(
                                     (int)left, (int)top,
                                     (int)(right - left), (int)(bottom - top),
-                                    (int)rx, (int)ry);
+                                    2 * (int)rx, 2 * (int)ry);
                         }
 
                         if (style == Paint.Style.STROKE.nativeInt ||
@@ -683,7 +683,7 @@
                             graphics.drawRoundRect(
                                     (int)left, (int)top,
                                     (int)(right - left), (int)(bottom - top),
-                                    (int)rx, (int)ry);
+                                    2 * (int)rx, 2 * (int)ry);
                         }
                     }
         });
diff --git a/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java b/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java
index 24e4b54..c72efc2 100644
--- a/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java
+++ b/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java
@@ -166,7 +166,7 @@
             if (lineBreaks.breaks.length != mBreaksList.size()) {
                 lineBreaks.breaks = new int[mBreaksList.size()];
                 lineBreaks.widths = new float[mWidthsList.size()];
-                lineBreaks.flags = new boolean[mFlagsList.size()];
+                lineBreaks.flags = new int[mFlagsList.size()];
             }
 
             int i = 0;
@@ -181,7 +181,7 @@
             }
             i = 0;
             for (boolean b : mFlagsList) {
-                lineBreaks.flags[i] = b;
+                lineBreaks.flags[i] = b ? TAB_MASK : 0;
                 i++;
             }
 
diff --git a/tools/layoutlib/bridge/src/android/text/LineBreaker.java b/tools/layoutlib/bridge/src/android/text/LineBreaker.java
index 8be3635..54445a4 100644
--- a/tools/layoutlib/bridge/src/android/text/LineBreaker.java
+++ b/tools/layoutlib/bridge/src/android/text/LineBreaker.java
@@ -26,6 +26,8 @@
 // frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260
 public abstract class LineBreaker {
 
+    protected static final int TAB_MASK   = 0x20000000;  // keep in sync with StaticLayout
+
     protected final @NonNull List<Primitive> mPrimitives;
     protected final @NonNull LineWidth mLineWidth;
     protected final @NonNull TabStops mTabStops;
diff --git a/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java b/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java
index d5d7798..cd92581 100644
--- a/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java
+++ b/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java
@@ -51,7 +51,7 @@
             assert p.type == PrimitiveType.PENALTY;
             breakInfo.breaks = new int[]{0};
             breakInfo.widths = new float[]{p.width};
-            breakInfo.flags = new boolean[]{false};
+            breakInfo.flags = new int[]{0};
             return;
         }
         Node[] opt = new Node[numBreaks];
@@ -129,7 +129,7 @@
 
             breakInfo.breaks[count] = mPrimitives.get(idx).location;
             breakInfo.widths[count] = opt[idx].mWidth;
-            breakInfo.flags [count] = opt[idx].mHasTabs;
+            breakInfo.flags [count] = opt[idx].mHasTabs ? TAB_MASK : 0;
             idx = opt[idx].mPrev;
         }
     }
@@ -140,7 +140,7 @@
         }
         int[] breaks = new int[size];
         float[] widths = new float[size];
-        boolean[] flags = new boolean[size];
+        int[] flags = new int[size];
 
         int toCopy = Math.min(size, lineBreaks.breaks.length);
         System.arraycopy(lineBreaks.breaks, 0, breaks, 0, toCopy);
diff --git a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
index e24b3d5..86d8da3 100644
--- a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
@@ -4,10 +4,15 @@
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
+import android.graphics.BidiRenderer;
+import android.graphics.Paint;
+import android.graphics.Paint_Delegate;
+import android.graphics.RectF;
 import android.text.StaticLayout.LineBreaks;
 import android.text.Primitive.PrimitiveType;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import com.ibm.icu.text.BreakIterator;
@@ -33,7 +38,7 @@
         new DelegateManager<Builder>(Builder.class);
 
     @LayoutlibDelegate
-    /*package*/ static int nComputeLineBreaks(long nativeBuilder, char[] inputText, float[] widths,
+    /*package*/ static int nComputeLineBreaks(long nativeBuilder,
             int length, float firstWidth, int firstWidthLineCount, float restWidth,
             int[] variableTabStops, int defaultTabStop, boolean optimize, LineBreaks recycle,
             int[] recycleBreaks, float[] recycleWidths, boolean[] recycleFlags, int recycleLength) {
@@ -41,7 +46,7 @@
         Builder builder = sBuilderManager.getDelegate(nativeBuilder);
         // compute all possible breakpoints.
         BreakIterator it = BreakIterator.getLineInstance(new ULocale(builder.mLocale));
-        it.setText(new Segment(inputText, 0, length));
+        it.setText(new Segment(builder.mText, 0, length));
         // average word length in english is 5. So, initialize the possible breaks with a guess.
         List<Integer> breaks = new ArrayList<Integer>((int) Math.ceil(length / 5d));
         int loc;
@@ -52,7 +57,7 @@
 
         LineWidth lineWidth = new LineWidth(firstWidth, firstWidthLineCount, restWidth);
         TabStops tabStopCalculator = new TabStops(variableTabStops, defaultTabStop);
-        List<Primitive> primitives = computePrimitives(inputText, widths, length, breaks);
+        List<Primitive> primitives = computePrimitives(builder.mText, builder.mWidths, length, breaks);
         LineBreaker lineBreaker;
         if (optimize) {
             lineBreaker = new OptimizingLineBreaker(primitives, lineWidth, tabStopCalculator);
@@ -119,16 +124,62 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nBuilderSetLocale(long nativeBuilder, String locale) {
+    /*package*/ static void nSetLocale(long nativeBuilder, String locale) {
         Builder builder = sBuilderManager.getDelegate(nativeBuilder);
         builder.mLocale = locale;
     }
 
+    @LayoutlibDelegate
+    /*package*/ static void nSetText(long nativeBuilder, char[] text, int length) {
+        Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+        builder.mText = text;
+        builder.mWidths = new float[length];
+    }
+
+
+    @LayoutlibDelegate
+    /*package*/ static float nAddStyleRun(long nativeBuilder, long nativePaint, long nativeTypeface,
+            int start, int end, boolean isRtl) {
+        Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+
+        int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
+        return measureText(nativePaint, builder.mText, start, end - start, builder.mWidths, bidiFlags);
+    }
+
+
+    @LayoutlibDelegate
+    /*package*/ static void nAddMeasuredRun(long nativeBuilder, int start, int end, float[] widths) {
+        Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+        System.arraycopy(widths, start, builder.mWidths, start, end - start);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nAddReplacementRun(long nativeBuilder, int start, int end, float width) {
+        Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+        builder.mWidths[start] = width;
+        Arrays.fill(builder.mWidths, start + 1, end, 0.0f);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void nGetWidths(long nativeBuilder, float[] floatsArray) {
+        Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+        System.arraycopy(builder.mWidths, 0, floatsArray, 0, builder.mWidths.length);
+    }
+
+    private static float measureText(long nativePaint, char []text, int index, int count,
+            float[] widths, int bidiFlags) {
+        Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint);
+        RectF bounds = new BidiRenderer(null, paint, text)
+            .renderText(index, index + count, bidiFlags, widths, 0, false);
+        return bounds.right - bounds.left;
+    }
+
     /**
-     * Java representation of the native Builder class. It currently only stores the locale
-     * set by nBuilderSetLocale.
+     * Java representation of the native Builder class.
      */
     static class Builder {
         String mLocale;
+        char[] mText;
+        float[] mWidths;
     }
 }
diff --git a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
new file mode 100644
index 0000000..ec3a8d6
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
@@ -0,0 +1,156 @@
+/*
+ * 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.view;
+
+import com.android.layoutlib.bridge.impl.ResourceHelper;
+
+import android.graphics.Canvas;
+import android.graphics.LinearGradient;
+import android.graphics.Outline;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Path;
+import android.graphics.Path.FillType;
+import android.graphics.RadialGradient;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region.Op;
+import android.graphics.Shader.TileMode;
+
+/**
+ * Paints shadow for rounded rectangles. Inspiration from CardView. Couldn't use that directly,
+ * since it modifies the size of the content, that we can't do.
+ */
+public class RectShadowPainter {
+
+
+    private static final int START_COLOR = ResourceHelper.getColor("#37000000");
+    private static final int END_COLOR = ResourceHelper.getColor("#03000000");
+    private static final float PERPENDICULAR_ANGLE = 90f;
+
+    public static void paintShadow(Outline viewOutline, float elevation, Canvas canvas) {
+        float shadowSize = elevationToShadow(elevation);
+        int saved = modifyCanvas(canvas, shadowSize);
+        if (saved == -1) {
+            return;
+        }
+        try {
+            Paint cornerPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
+            cornerPaint.setStyle(Style.FILL);
+            Paint edgePaint = new Paint(cornerPaint);
+            edgePaint.setAntiAlias(false);
+            Rect outline = viewOutline.mRect;
+            float radius = viewOutline.mRadius;
+            float outerArcRadius = radius + shadowSize;
+            int[] colors = {START_COLOR, START_COLOR, END_COLOR};
+            cornerPaint.setShader(new RadialGradient(0, 0, outerArcRadius, colors,
+                    new float[]{0f, radius / outerArcRadius, 1f}, TileMode.CLAMP));
+            edgePaint.setShader(new LinearGradient(0, 0, -shadowSize, 0, START_COLOR, END_COLOR,
+                    TileMode.CLAMP));
+            Path path = new Path();
+            path.setFillType(FillType.EVEN_ODD);
+            // A rectangle bounding the complete shadow.
+            RectF shadowRect = new RectF(outline);
+            shadowRect.inset(-shadowSize, -shadowSize);
+            // A rectangle with edges corresponding to the straight edges of the outline.
+            RectF inset = new RectF(outline);
+            inset.inset(radius, radius);
+            // A rectangle used to represent the edge shadow.
+            RectF edgeShadowRect = new RectF();
+
+
+            // left and right sides.
+            edgeShadowRect.set(-shadowSize, 0f, 0f, inset.height());
+            // Left shadow
+            sideShadow(canvas, edgePaint, edgeShadowRect, outline.left, inset.top, 0);
+            // Right shadow
+            sideShadow(canvas, edgePaint, edgeShadowRect, outline.right, inset.bottom, 2);
+            // Top shadow
+            edgeShadowRect.set(-shadowSize, 0, 0, inset.width());
+            sideShadow(canvas, edgePaint, edgeShadowRect, inset.right, outline.top, 1);
+            // bottom shadow. This needs an inset so that blank doesn't appear when the content is
+            // moved up.
+            edgeShadowRect.set(-shadowSize, 0, shadowSize / 2f, inset.width());
+            edgePaint.setShader(new LinearGradient(edgeShadowRect.right, 0, edgeShadowRect.left, 0,
+                    colors, new float[]{0f, 1 / 3f, 1f}, TileMode.CLAMP));
+            sideShadow(canvas, edgePaint, edgeShadowRect, inset.left, outline.bottom, 3);
+
+            // Draw corners.
+            drawCorner(canvas, cornerPaint, path, inset.right, inset.bottom, outerArcRadius, 0);
+            drawCorner(canvas, cornerPaint, path, inset.left, inset.bottom, outerArcRadius, 1);
+            drawCorner(canvas, cornerPaint, path, inset.left, inset.top, outerArcRadius, 2);
+            drawCorner(canvas, cornerPaint, path, inset.right, inset.top, outerArcRadius, 3);
+        } finally {
+            canvas.restoreToCount(saved);
+        }
+    }
+
+    private static float elevationToShadow(float elevation) {
+        // The factor is chosen by eyeballing the shadow size on device and preview.
+        return elevation * 0.5f;
+    }
+
+    /**
+     * Translate canvas by half of shadow size up, so that it appears that light is coming
+     * slightly from above. Also, remove clipping, so that shadow is not clipped.
+     */
+    private static int modifyCanvas(Canvas canvas, float shadowSize) {
+        Rect clipBounds = canvas.getClipBounds();
+        if (clipBounds.isEmpty()) {
+            return -1;
+        }
+        int saved = canvas.save();
+        // Usually canvas has been translated to the top left corner of the view when this is
+        // called. So, setting a clip rect at 0,0 will clip the top left part of the shadow.
+        // Thus, we just expand in each direction by width and height of the canvas.
+        canvas.clipRect(-canvas.getWidth(), -canvas.getHeight(), canvas.getWidth(),
+                canvas.getHeight(), Op.REPLACE);
+        canvas.translate(0, shadowSize / 2f);
+        return saved;
+    }
+
+    private static void sideShadow(Canvas canvas, Paint edgePaint,
+            RectF edgeShadowRect, float dx, float dy, int rotations) {
+        int saved = canvas.save();
+        canvas.translate(dx, dy);
+        canvas.rotate(rotations * PERPENDICULAR_ANGLE);
+        canvas.drawRect(edgeShadowRect, edgePaint);
+        canvas.restoreToCount(saved);
+    }
+
+    /**
+     * @param canvas Canvas to draw the rectangle on.
+     * @param paint Paint to use when drawing the corner.
+     * @param path A path to reuse. Prevents allocating memory for each path.
+     * @param x Center of circle, which this corner is a part of.
+     * @param y Center of circle, which this corner is a part of.
+     * @param radius radius of the arc
+     * @param rotations number of quarter rotations before starting to paint the arc.
+     */
+    private static void drawCorner(Canvas canvas, Paint paint, Path path, float x, float y,
+            float radius, int rotations) {
+        int saved = canvas.save();
+        canvas.translate(x, y);
+        path.reset();
+        path.arcTo(-radius, -radius, radius, radius, rotations * PERPENDICULAR_ANGLE,
+                PERPENDICULAR_ANGLE, false);
+        path.lineTo(0, 0);
+        path.close();
+        canvas.drawPath(path, paint);
+        canvas.restoreToCount(saved);
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
index 82ae1df..e72a0db 100644
--- a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
@@ -16,12 +16,9 @@
 
 package android.view;
 
-import com.android.annotations.NonNull;
-import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.resources.Density;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
-import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
 import android.graphics.Canvas;
@@ -29,8 +26,6 @@
 import android.graphics.Path_Delegate;
 import android.graphics.Rect;
 import android.graphics.Region.Op;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
 import android.view.animation.Transformation;
 
 import java.awt.Graphics2D;
@@ -50,33 +45,36 @@
     @LayoutlibDelegate
     /*package*/ static boolean drawChild(ViewGroup thisVG, Canvas canvas, View child,
             long drawingTime) {
-        boolean retVal = thisVG.drawChild_Original(canvas, child, drawingTime);
         if (child.getZ() > thisVG.getZ()) {
             ViewOutlineProvider outlineProvider = child.getOutlineProvider();
             Outline outline = new Outline();
             outlineProvider.getOutline(child, outline);
-
+            if (outline.mPath == null && outline.mRect == null) {
+                // Sometimes, the bounds of the background drawable are not set until View.draw()
+                // is called. So, we set the bounds manually and try to get the outline again.
+                child.getBackground().setBounds(0, 0, child.mRight - child.mLeft,
+                        child.mBottom - child.mTop);
+                outlineProvider.getOutline(child, outline);
+            }
             if (outline.mPath != null || (outline.mRect != null && !outline.mRect.isEmpty())) {
                 int restoreTo = transformCanvas(thisVG, canvas, child);
                 drawShadow(thisVG, canvas, child, outline);
                 canvas.restoreToCount(restoreTo);
             }
         }
-        return retVal;
+        return thisVG.drawChild_Original(canvas, child, drawingTime);
     }
 
     private static void drawShadow(ViewGroup parent, Canvas canvas, View child,
             Outline outline) {
+        float elevation = getElevation(child, parent);
+        if(outline.mRect != null) {
+            RectShadowPainter.paintShadow(outline, elevation, canvas);
+            return;
+        }
         BufferedImage shadow = null;
-        int x = 0;
-        if (outline.mRect != null) {
-            Shadow s = getRectShadow(parent, canvas, child, outline);
-            if (s != null) {
-              shadow = s.mShadow;
-              x = -s.mShadowWidth;
-            }
-        } else if (outline.mPath != null) {
-            shadow = getPathShadow(child, outline, canvas);
+        if (outline.mPath != null) {
+            shadow = getPathShadow(outline, canvas, elevation);
         }
         if (shadow == null) {
             return;
@@ -85,52 +83,17 @@
                 Density.getEnum(canvas.getDensity()));
         Rect clipBounds = canvas.getClipBounds();
         Rect newBounds = new Rect(clipBounds);
-        newBounds.left = newBounds.left + x;
+        newBounds.inset((int)-elevation, (int)-elevation);
         canvas.clipRect(newBounds, Op.REPLACE);
-        canvas.drawBitmap(bitmap, x, 0, null);
+        canvas.drawBitmap(bitmap, 0, 0, null);
         canvas.clipRect(clipBounds, Op.REPLACE);
     }
 
-    private static Shadow getRectShadow(ViewGroup parent, Canvas canvas, View child,
-            Outline outline) {
-        BufferedImage shadow;
-        Rect clipBounds = canvas.getClipBounds();
-        if (clipBounds.isEmpty()) {
-            return null;
-        }
-        float height = child.getZ() - parent.getZ();
-        // Draw large shadow if difference in z index is more than 10dp
-        float largeShadowThreshold = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f,
-                getMetrics(child));
-        boolean largeShadow = height > largeShadowThreshold;
-        int shadowSize = largeShadow ? ShadowPainter.SHADOW_SIZE : ShadowPainter.SMALL_SHADOW_SIZE;
-        shadow = new BufferedImage(clipBounds.width() + shadowSize, clipBounds.height(),
-                BufferedImage.TYPE_INT_ARGB);
-        Graphics2D graphics = shadow.createGraphics();
-        Rect rect = outline.mRect;
-        if (largeShadow) {
-            ShadowPainter.drawRectangleShadow(graphics,
-                    rect.left + shadowSize, rect.top, rect.width(), rect.height());
-        } else {
-            ShadowPainter.drawSmallRectangleShadow(graphics,
-                    rect.left + shadowSize, rect.top, rect.width(), rect.height());
-        }
-        graphics.dispose();
-        return new Shadow(shadow, shadowSize);
+    private static float getElevation(View child, ViewGroup parent) {
+        return child.getZ() - parent.getZ();
     }
 
-    @NonNull
-    private static DisplayMetrics getMetrics(View view) {
-        Context context = view.getContext();
-        context = BridgeContext.getBaseContext(context);
-        if (context instanceof BridgeContext) {
-            return ((BridgeContext) context).getMetrics();
-        }
-        throw new RuntimeException("View " + view.getClass().getName() + " not created with the " +
-                "right context");
-    }
-
-    private static BufferedImage getPathShadow(View child, Outline outline, Canvas canvas) {
+    private static BufferedImage getPathShadow(Outline outline, Canvas canvas, float elevation) {
         Rect clipBounds = canvas.getClipBounds();
         if (clipBounds.isEmpty()) {
           return null;
@@ -140,7 +103,7 @@
         Graphics2D graphics = image.createGraphics();
         graphics.draw(Path_Delegate.getDelegate(outline.mPath.mNativePath).getJavaShape());
         graphics.dispose();
-        return ShadowPainter.createDropShadow(image, ((int) child.getZ()));
+        return ShadowPainter.createDropShadow(image, (int) elevation);
     }
 
     // Copied from android.view.View#draw(Canvas, ViewGroup, long) and removed code paths
@@ -194,15 +157,4 @@
         }
         return restoreTo;
     }
-
-    private static class Shadow {
-        public BufferedImage mShadow;
-        public int mShadowWidth;
-
-        public Shadow(BufferedImage shadow, int shadowWidth) {
-            mShadow = shadow;
-            mShadowWidth = shadowWidth;
-        }
-
-    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 39ebdfc..085df85 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -145,4 +145,14 @@
     public void boostScreenBrightness(long time) throws RemoteException {
         // pass for now.
     }
+
+    @Override
+    public boolean isDeviceIdleMode() throws RemoteException {
+        return false;
+    }
+
+    @Override
+    public boolean isScreenBrightnessBoosted() throws RemoteException {
+        return false;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
index dde041b..9f9b968 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
@@ -16,6 +16,8 @@
 
 package com.android.layoutlib.bridge.bars;
 
+import android.os.Build.VERSION_CODES;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -40,12 +42,12 @@
     private static final int BLACK = 0xFF000000;
 
     public static boolean showOnScreenNavBar(int platformVersion) {
-        return platformVersion == 0 || platformVersion >= ICE_CREAM_SANDWICH;
+        return isGreaterOrEqual(platformVersion, ICE_CREAM_SANDWICH);
     }
 
     public static int getStatusBarColor(int platformVersion) {
         // return white for froyo and earlier; black otherwise.
-        return platformVersion == 0 || platformVersion >= GINGERBREAD ? BLACK : WHITE;
+        return isGreaterOrEqual(platformVersion, GINGERBREAD) ? BLACK : WHITE;
     }
 
     public static List<String> getResourceDirs(int platformVersion) {
@@ -98,7 +100,7 @@
     }
 
     public static int getTimeColor(int platformVersion) {
-        if (platformVersion == 0 || platformVersion >= KITKAT ||
+        if (isGreaterOrEqual(platformVersion, KITKAT) ||
                 platformVersion > FROYO && platformVersion < HONEYCOMB) {
             // Gingerbread and KitKat onwards.
             return WHITE;
@@ -117,4 +119,13 @@
     public static String getWifiIconType(int platformVersion) {
         return platformVersion == 0 ? "xml" : "png";
     }
+
+    /**
+     * Compare simulated platform version and code from {@link VERSION_CODES} to check if
+     * the simulated platform is greater than or equal to the version code.
+     */
+    public static boolean isGreaterOrEqual(int platformVersion, int code) {
+        // simulated platform version = 0 means that we use the latest.
+        return platformVersion == 0 || platformVersion >= code;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 13ddf07..bc1a41d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -16,6 +16,7 @@
 
 package com.android.layoutlib.bridge.bars;
 
+import com.android.annotations.NonNull;
 import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.ide.common.rendering.api.StyleResourceValue;
@@ -26,6 +27,7 @@
 import com.android.layoutlib.bridge.impl.ResourceHelper;
 import com.android.resources.Density;
 import com.android.resources.LayoutDirection;
+import com.android.resources.ResourceType;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -47,6 +49,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 
+import static android.os.Build.VERSION_CODES.LOLLIPOP;
+
 /**
  * Base "bar" class for the window decor around the the edited layout.
  * This is basically an horizontal layout that loads a given layout on creation (it is read
@@ -63,7 +67,7 @@
 
     protected abstract TextView getStyleableTextView();
 
-    protected CustomBar(Context context, int orientation, String layoutPath,
+    protected CustomBar(BridgeContext context, int orientation, String layoutPath,
             String name, int simulatedPlatformVersion) throws XmlPullParserException {
         super(context);
         mSimulatedPlatformVersion = simulatedPlatformVersion;
@@ -197,7 +201,7 @@
 
 
                 ResourceValue textColor = res.findItemInStyle(textStyle, "textColor",
-                        true /*isFrameworkAttr*/);
+                        true);
                 textColor = res.resolveResValue(textColor);
                 if (textColor != null) {
                     ColorStateList stateList = ResourceHelper.getColorStateList(
@@ -210,12 +214,39 @@
         }
     }
 
+    /**
+     * Given a theme attribute name, get the color referenced by it. The theme attribute may be
+     * used in a layout like "?attr/foo".
+     * <p/>
+     * Returns 0 if not found.
+     *
+     * @throws NumberFormatException if color resolved to an invalid string.
+     */
+    protected int getThemeAttrColor(@NonNull String attrName, boolean isFramework) {
+        if (!Config.isGreaterOrEqual(mSimulatedPlatformVersion, LOLLIPOP)) {
+            return 0;
+        }
+        assert mContext instanceof BridgeContext;
+        BridgeContext context = ((BridgeContext) mContext);
+        RenderResources renderResources = context.getRenderResources();
+        // From ?attr/foo to @color/bar. This is most likely an ItemResourceValue.
+        ResourceValue resource = renderResources.findItemInTheme(attrName, isFramework);
+        if (resource != null) {
+            // Form @color/bar to the #AARRGGBB
+            resource = renderResources.resolveResValue(resource);
+        }
+        if (resource != null && ResourceType.COLOR.equals(resource.getResourceType())) {
+            return ResourceHelper.getColor(resource.getValue());
+        }
+        return 0;
+    }
+
     private ResourceValue getResourceValue(String reference) {
         BridgeContext bridgeContext = (BridgeContext) mContext;
         RenderResources res = bridgeContext.getRenderResources();
 
         // find the resource
-        ResourceValue value = res.findResValue(reference, false /*isFramework*/);
+        ResourceValue value = res.findResValue(reference, false);
 
         // resolve it if needed
         return res.resolveResValue(value);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
index 283ff57..9450b6c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -16,22 +16,26 @@
 
 package com.android.layoutlib.bridge.bars;
 
+import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.resources.Density;
 
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.content.Context;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
 public class NavigationBar extends CustomBar {
 
-    public NavigationBar(Context context, Density density, int orientation, boolean isRtl,
+    /** Navigation bar background color attribute name. */
+    private static final String ATTR_COLOR = "navigationBarColor";
+
+    public NavigationBar(BridgeContext context, Density density, int orientation, boolean isRtl,
             boolean rtlEnabled, int simulatedPlatformVersion) throws XmlPullParserException {
         super(context, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml",
                 simulatedPlatformVersion);
 
-        setBackgroundColor(0xFF000000);
+        int color = getThemeAttrColor(ATTR_COLOR, true);
+        setBackgroundColor(color == 0 ? 0xFF000000 : color);
 
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index c7c62d6..e5f1f68 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -25,7 +25,6 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.view.Gravity;
 import android.view.View;
@@ -38,20 +37,21 @@
 
 public class StatusBar extends CustomBar {
 
-    private final Context mContext;
     private final int mSimulatedPlatformVersion;
+    /** Status bar background color attribute name. */
+    private static final String ATTR_COLOR = "colorPrimaryDark";
 
-    public StatusBar(Context context, Density density, int direction, boolean RtlEnabled,
+    public StatusBar(BridgeContext context, Density density, int direction, boolean RtlEnabled,
             int simulatedPlatformVersion) throws XmlPullParserException {
         // FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar.
         super(context, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml",
                 simulatedPlatformVersion);
-        mContext = context;
         mSimulatedPlatformVersion = simulatedPlatformVersion;
 
         // FIXME: use FILL_H?
         setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
-        setBackgroundColor(Config.getStatusBarColor(simulatedPlatformVersion));
+        int color = getThemeAttrColor(ATTR_COLOR, true);
+        setBackgroundColor(color == 0 ? Config.getStatusBarColor(simulatedPlatformVersion) : color);
 
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
@@ -82,10 +82,8 @@
                 try {
                     BridgeXmlBlockParser parser = new BridgeXmlBlockParser(
                             ParserFactory.create(stream, null), (BridgeContext) mContext, true);
-                    Drawable drawable = Drawable.createFromXml(mContext.getResources(), parser);
-                    if (drawable != null) {
-                        imageView.setImageDrawable(drawable);
-                    }
+                    imageView.setImageDrawable(
+                            Drawable.createFromXml(mContext.getResources(), parser));
                 } catch (XmlPullParserException e) {
                     Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to draw wifi icon", e,
                             null);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
index 10f1383..c610601 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
@@ -16,9 +16,10 @@
 
 package com.android.layoutlib.bridge.bars;
 
+import com.android.layoutlib.bridge.android.BridgeContext;
+
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.content.Context;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
@@ -26,7 +27,7 @@
 
     private TextView mTextView;
 
-    public TitleBar(Context context, String label, int simulatedPlatformVersion)
+    public TitleBar(BridgeContext context, String label, int simulatedPlatformVersion)
             throws XmlPullParserException {
         super(context, LinearLayout.HORIZONTAL, "/bars/title_bar.xml", "title_bar.xml",
                 simulatedPlatformVersion);
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build.gradle b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build.gradle
index 80be12d..0f37fce 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build.gradle
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build.gradle
@@ -3,7 +3,7 @@
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:0.12.+'
+        classpath 'com.android.tools.build:gradle:1.1.3'
 
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
@@ -19,22 +19,24 @@
 apply plugin: 'com.android.application'
 
 android {
-    compileSdkVersion 20
-    buildToolsVersion '20'
+    compileSdkVersion 21
+    buildToolsVersion '21.1.2'
     defaultConfig {
         applicationId 'com.android.layoutlib.test.myapplication'
         minSdkVersion 19
-        targetSdkVersion 20
+        targetSdkVersion 21
         versionCode 1
         versionName '1.0'
     }
     buildTypes {
         release {
-            runProguard false
+            minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
         }
     }
-    productFlavors {
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_6
+        targetCompatibility JavaVersion.VERSION_1_6
     }
 }
 
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/androidTest/debug/com/android/layoutlib/test/myapplication/test/BuildConfig.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/androidTest/debug/com/android/layoutlib/test/myapplication/test/BuildConfig.class
new file mode 100644
index 0000000..1ca7e01
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/androidTest/debug/com/android/layoutlib/test/myapplication/test/BuildConfig.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/BuildConfig.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/BuildConfig.class
index 2b4f7bf..ceb56bf 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/BuildConfig.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/BuildConfig.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/CustomCalendar.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/CustomCalendar.class
new file mode 100644
index 0000000..c363055
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/CustomCalendar.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/CustomDate.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/CustomDate.class
new file mode 100644
index 0000000..edda3de
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/CustomDate.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png
index 943cdf1..e38f437 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle/wrapper/gradle-wrapper.properties b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle/wrapper/gradle-wrapper.properties
index 5de946b..3b51ffe 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle/wrapper/gradle-wrapper.properties
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Apr 10 15:27:10 PDT 2013
+#Tue Mar 17 15:13:06 PDT 2015
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/androidTest/java/com/android/layoulib/test/myapplication/ApplicationTest.java b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/androidTest/java/com/android/layoulib/test/myapplication/ApplicationTest.java
deleted file mode 100644
index 7304af1..0000000
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/androidTest/java/com/android/layoulib/test/myapplication/ApplicationTest.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.android.layoulib.test.myapplication;
-
-import android.app.Application;
-import android.test.ApplicationTestCase;
-
-/**
- * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
- */
-public class ApplicationTest extends ApplicationTestCase<Application> {
-    public ApplicationTest() {
-        super(Application.class);
-    }
-}
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/CustomCalendar.java b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/CustomCalendar.java
new file mode 100644
index 0000000..80bbaf1
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/CustomCalendar.java
@@ -0,0 +1,31 @@
+package com.android.layoutlib.test.myapplication;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.CalendarView;
+
+public class CustomCalendar extends CalendarView {
+    public CustomCalendar(Context context) {
+        super(context);
+        init();
+    }
+
+    public CustomCalendar(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public CustomCalendar(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    public CustomCalendar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    private void init() {
+        setDate(871703200000L, false, true);
+    }
+}
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/CustomDate.java b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/CustomDate.java
new file mode 100644
index 0000000..cb750f4
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/CustomDate.java
@@ -0,0 +1,31 @@
+package com.android.layoutlib.test.myapplication;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.DatePicker;
+
+public class CustomDate extends DatePicker {
+    public CustomDate(Context context) {
+        super(context);
+        init();
+    }
+
+    public CustomDate(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public CustomDate(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    public CustomDate(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    private void init() {
+        init(2015, 0, 20, null);
+    }
+}
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/layout.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/layout.xml
index b8ec5661..c1f663e 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/layout.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/layout.xml
@@ -1,17 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical" android:layout_width="match_parent"
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:columnCount="2"
     android:layout_height="match_parent">
 
     <TextView
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="Some text"/>
-    <DatePicker
+    <Switch
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:checked="true"
+        android:layout_gravity="center"
+        />
+    <com.android.layoutlib.test.myapplication.CustomDate
         android:layout_width="100dp"
-        android:layout_height="100dp"/>
-    <CalendarView
-        android:layout_width="100dp"
-        android:layout_height="100dp"/>
-</LinearLayout>
\ No newline at end of file
+        android:layout_height="wrap_content"/>
+    <com.android.layoutlib.test.myapplication.CustomCalendar
+        android:layout_width="200dp"
+        android:layout_gravity="center_horizontal"
+        android:layout_height="200dp"/>
+</GridLayout>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java
index e13ad72..d7e5486 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java
@@ -56,7 +56,7 @@
 
     private static final int THUMBNAIL_SIZE = 250;
 
-    private static final double MAX_PERCENT_DIFFERENCE = 0.1;
+    private static final double MAX_PERCENT_DIFFERENCE = 0.3;
 
     public static void requireSimilar(@NonNull String relativePath, @NonNull BufferedImage image)
             throws IOException {
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index a86fcdd..ac23564 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -316,7 +316,8 @@
         FolderConfiguration config = configGenerator.getFolderConfig();
         ResourceResolver resourceResolver =
                 ResourceResolver.create(mProjectResources.getConfiguredResources(config),
-                        mFrameworkRepo.getConfiguredResources(config), "Theme.Material", false);
+                        mFrameworkRepo.getConfiguredResources(config),
+                        "Theme.Material.Light.DarkActionBar", false);
 
         return new SessionParams(
                 layoutParser,
@@ -336,7 +337,7 @@
                 @Override
                 public void warning(String tag, String message, Object data) {
                     System.out.println("Warning " + tag + ": " + message);
-                    fail(message);
+                    failWithMsg(message);
                 }
 
                 @Override
@@ -346,13 +347,13 @@
                     if (throwable != null) {
                         throwable.printStackTrace();
                     }
-                    fail(message);
+                    failWithMsg(message);
                 }
 
                 @Override
                 public void error(String tag, String message, Object data) {
                     System.out.println("Error " + tag + ": " + message);
-                    fail(message);
+                    failWithMsg(message);
                 }
 
                 @Override
@@ -361,7 +362,7 @@
                     if (throwable != null) {
                         throwable.printStackTrace();
                     }
-                    fail(message);
+                    failWithMsg(message);
                 }
             };
         }
@@ -376,12 +377,12 @@
                     if (t != null) {
                         t.printStackTrace();
                     }
-                    fail(String.format(msgFormat, args));
+                    failWithMsg(msgFormat, args);
                 }
 
                 @Override
                 public void warning(String msgFormat, Object... args) {
-                    fail(String.format(msgFormat, args));
+                    failWithMsg(msgFormat, args);
                 }
 
                 @Override
@@ -397,4 +398,8 @@
         }
         return mLogger;
     }
+
+    private static void failWithMsg(String msgFormat, Object... args) {
+        fail(msgFormat == null || args == null ? "" : String.format(msgFormat, args));
+    }
 }
diff --git a/tools/layoutlib/rename_font/build_font.py b/tools/layoutlib/rename_font/build_font.py
index c747d92..9713a4c 100755
--- a/tools/layoutlib/rename_font/build_font.py
+++ b/tools/layoutlib/rename_font/build_font.py
@@ -209,15 +209,18 @@
 
 
 def get_version(string):
-  # The string must begin with 'Version n.nn '
-  # to extract n.nn, we return the second entry in the split strings.
   string = string.strip()
-  if not string.startswith('Version '):
-    raise InvalidFontException('mal-formed font version')
-  return sanitize(string.split()[1])
+  # The spec says that the version string should start with "Version ". But not
+  # all fonts do. So, we return the complete string if it doesn't start with
+  # the prefix, else we return the rest of the string after sanitizing it.
+  prefix = 'Version '
+  if string.startswith(prefix):
+    string = string[len(prefix):]
+  return sanitize(string)
 
 
 def sanitize(string):
+  """ Remove non-standard chars. """
   return re.sub(r'[^\w-]+', '', string)
 
 if __name__ == '__main__':
diff --git a/tools/layoutlib/rename_font/build_font_single.py b/tools/layoutlib/rename_font/build_font_single.py
index 5f7dad9..4245cdc 100755
--- a/tools/layoutlib/rename_font/build_font_single.py
+++ b/tools/layoutlib/rename_font/build_font_single.py
@@ -193,15 +193,18 @@
 
 
 def get_version(string):
-  # The string must begin with 'Version n.nn '
-  # to extract n.nn, we return the second entry in the split strings.
   string = string.strip()
-  if not string.startswith('Version '):
-    raise InvalidFontException('mal-formed font version')
-  return sanitize(string.split()[1])
+  # The spec says that the version string should start with "Version ". But not
+  # all fonts do. So, we return the complete string if it doesn't start with
+  # the prefix, else we return the rest of the string after sanitizing it.
+  prefix = 'Version '
+  if string.startswith(prefix):
+    string = string[len(prefix):]
+  return sanitize(string)
 
 
 def sanitize(string):
+  """ Remove non-standard chars. """
   return re.sub(r'[^\w-]+', '', string)
 
 if __name__ == '__main__':
diff --git a/wifi/java/android/net/wifi/IRttManager.aidl b/wifi/java/android/net/wifi/IRttManager.aidl
index d929f55..90f66c4 100644
--- a/wifi/java/android/net/wifi/IRttManager.aidl
+++ b/wifi/java/android/net/wifi/IRttManager.aidl
@@ -15,8 +15,8 @@
  */
 
 package android.net.wifi;
-
 import android.os.Messenger;
+import android.net.wifi.RttManager;
 
 /**
  * {@hide}
@@ -24,4 +24,5 @@
 interface IRttManager
 {
     Messenger getMessenger();
+    RttManager.RttCapabilities getRttCapabilities();
 }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index bc95a36..5342494 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -155,6 +155,10 @@
 
     void setAllowScansWithTraffic(int enabled);
 
+    boolean getAllowScansWhileAssociated();
+
+    void setAllowScansWhileAssociated(boolean enabled);
+
     WifiConnectionStatistics getConnectionStatistics();
 
     void disableEphemeralNetwork(String SSID);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java b/wifi/java/android/net/wifi/RttManager.aidl
similarity index 67%
copy from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
copy to wifi/java/android/net/wifi/RttManager.aidl
index 272c321..5c6d447 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPanel.java
+++ b/wifi/java/android/net/wifi/RttManager.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
+/**
+ * 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
+ *     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,
@@ -14,8 +14,5 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar;
-
-public interface StatusBarPanel {
-    public boolean isInContentArea(int x, int y);
-}
+package android.net.wifi;
+parcelable RttManager.RttCapabilities;
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 57343c5..65ecf5d 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -26,10 +26,19 @@
     private static final boolean DBG = true;
     private static final String TAG = "RttManager";
 
-    public static final int RTT_TYPE_UNSPECIFIED    = 0;
-    public static final int RTT_TYPE_ONE_SIDED      = 1;
-    public static final int RTT_TYPE_11_V           = 2;
-    public static final int RTT_TYPE_11_MC          = 4;
+    /** @deprecated Type must be specified*/
+    @Deprecated
+    public static final int RTT_TYPE_UNSPECIFIED        = 0;
+    public static final int RTT_TYPE_ONE_SIDED          = 1;
+
+    /** @deprecated It is not supported*/
+    @Deprecated
+    public static final int RTT_TYPE_11_V               = 2;
+    public static final int RTT_TYPE_TWO_SIDED          = 4;
+
+    /** @deprecated It is not supported*/
+    @Deprecated
+    public static final int RTT_TYPE_11_MC              = 4;
 
     public static final int RTT_PEER_TYPE_UNSPECIFIED    = 0;
     public static final int RTT_PEER_TYPE_AP             = 1;
@@ -42,6 +51,9 @@
     public static final int RTT_CHANNEL_WIDTH_80P80   = 4;
     public static final int RTT_CHANNEL_WIDTH_5       = 5;
     public static final int RTT_CHANNEL_WIDTH_10      = 6;
+
+    /** @deprecated channel info must be specified*/
+    @Deprecated
     public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1;
 
     public static final int RTT_STATUS_SUCCESS                  = 0;
@@ -53,6 +65,12 @@
     public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL  = 6;
     public static final int RTT_STATUS_FAIL_NO_CAPABILITY       = 7;
     public static final int RTT_STATUS_ABORTED                  = 8;
+    //if the T1-T4 or TOD/TOA Timestamp is illegal
+    public static final int RTT_STATUS_FAIL_INVALID_TS          = 9;
+    //11mc protocol failed, eg, unrecognized FTMR/FTM
+    public static final int RTT_STATUS_FAIL_PROTOCOL            = 10;
+    public static final int RTT_STATUS_FAIL_SCHEDULE            = 11;
+    public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER      = 12;
 
     public static final int REASON_UNSPECIFIED              = -1;
     public static final int REASON_NOT_AVAILABLE            = -2;
@@ -61,41 +79,269 @@
 
     public static final String DESCRIPTION_KEY  = "android.net.wifi.RttManager.Description";
 
+    /**
+     * RTT BW supported bit mask
+     */
+    public static final int RTT_BW_5_SUPPORT   = 0x1;
+    public static final int RTT_BW_10_SUPPORT  = 0x2;
+    public static final int RTT_BW_20_SUPPORT  = 0x4;
+    public static final int RTT_BW_40_SUPPORT  = 0x8;
+    public static final int RTT_BW_80_SUPPORT  = 0x10;
+    public static final int RTT_BW_160_SUPPORT = 0x20;
+
+    /**
+     * RTT Preamble Support bit mask
+     */
+    public static final int PREAMBLE_LEGACY  = 0x1;
+    public static final int PREAMBLE_HT      = 0x2;
+    public static final int PREAMBLE_VHT     = 0x4;
+
+    /** @deprecated It has been replaced by RttCapabilities*/
+    @Deprecated
     public class Capabilities {
         public int supportedType;
         public int supportedPeerType;
     }
 
+    /** @deprecated It has been replaced by getRttCapabilities*/
+    @Deprecated
     public Capabilities getCapabilities() {
         return new Capabilities();
     }
 
+    /**
+     * This class describe the RTT capability of the Hardware
+     */
+    public static class RttCapabilities implements Parcelable {
+        /** @deprecated It is not supported*/
+        @Deprecated
+        public boolean supportedType;
+        /** @deprecated It is not supported*/
+        @Deprecated
+        public boolean supportedPeerType;
+        //1-sided rtt measurement is supported
+        public boolean oneSidedRttSupported;
+        //11mc 2-sided rtt measurement is supported
+        public boolean twoSided11McRttSupported;
+        //location configuration information supported
+        public boolean lciSupported;
+        //location civic records supported
+        public boolean lcrSupported;
+        //preamble supported, see bit mask definition above
+        public int preambleSupported;
+        //RTT bandwidth supported
+        public int bwSupported;
+
+        @Override
+        public String toString() {
+            StringBuffer sb = new StringBuffer();
+            sb.append("oneSidedRtt ").
+            append(oneSidedRttSupported ? "is Supported. " : "is not supported. ").
+            append("twoSided11McRtt ").
+            append(twoSided11McRttSupported ? "is Supported. " : "is not supported. ").
+            append("lci ").
+            append(lciSupported ? "is Supported. " : "is not supported. ").
+            append("lcr ").
+            append(lcrSupported ? "is Supported. " : "is not supported. ");
+
+            if ((preambleSupported & PREAMBLE_LEGACY) != 0) {
+                sb.append("Legacy ");
+            }
+
+            if ((preambleSupported & PREAMBLE_HT) != 0) {
+                sb.append("HT ");
+            }
+
+            if ((preambleSupported & PREAMBLE_VHT) != 0) {
+                sb.append("VHT ");
+            }
+
+            sb.append("is supported. \n");
+
+            if ((bwSupported & RTT_BW_5_SUPPORT) != 0) {
+                sb.append("5 MHz ");
+            }
+
+            if ((bwSupported & RTT_BW_10_SUPPORT) != 0) {
+                sb.append("10 MHz ");
+            }
+
+            if ((bwSupported & RTT_BW_20_SUPPORT) != 0) {
+                sb.append("20 MHz ");
+            }
+
+            if ((bwSupported & RTT_BW_40_SUPPORT) != 0) {
+                sb.append("40 MHz ");
+            }
+
+            if ((bwSupported & RTT_BW_80_SUPPORT) != 0) {
+                sb.append("80 MHz ");
+            }
+
+            if ((bwSupported & RTT_BW_160_SUPPORT) != 0) {
+                sb.append("160 MHz ");
+            }
+
+            sb.append("is supported.");
+
+            return sb.toString();
+        }
+        /** Implement the Parcelable interface {@hide} */
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(oneSidedRttSupported ? 1 : 0);
+            dest.writeInt(twoSided11McRttSupported ? 1 : 0);
+            dest.writeInt(lciSupported ? 1 : 0);
+            dest.writeInt(lcrSupported ? 1 : 0);
+            dest.writeInt(preambleSupported);
+            dest.writeInt(bwSupported);
+
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public static final Creator<RttCapabilities> CREATOR =
+            new Creator<RttCapabilities>() {
+               public RttCapabilities createFromParcel(Parcel in) {
+                    RttCapabilities capabilities = new RttCapabilities();
+                    capabilities.oneSidedRttSupported = in.readInt() == 1 ? true : false;
+                        capabilities.twoSided11McRttSupported = in.readInt() == 1 ? true : false;
+                        capabilities.lciSupported = in.readInt() == 1 ? true : false;
+                        capabilities.lcrSupported = in.readInt() == 1 ? true : false;
+                        capabilities.preambleSupported = in.readInt();
+                        capabilities.bwSupported = in.readInt();
+                        return capabilities;
+                    }
+                /** Implement the Parcelable interface {@hide} */
+                @Override
+                public RttCapabilities[] newArray(int size) {
+                    return new RttCapabilities[size];
+                }
+             };
+    }
+
+    public RttCapabilities getRttCapabilities() {
+        synchronized (sCapabilitiesLock) {
+            if (mRttCapabilities == null) {
+                try {
+                    mRttCapabilities = mService.getRttCapabilities();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Can not get RTT Capabilities");
+                }
+            }
+            return mRttCapabilities;
+        }
+    }
+
     /** specifies parameters for RTT request */
     public static class RttParams {
-
-        /** type of device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA */
+        /**
+         * type of destination device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA
+         */
         public int deviceType;
 
-        /** type of RTT being sought; one of RTT_TYPE_ONE_SIDED
-         *  RTT_TYPE_11_V or RTT_TYPE_11_MC or RTT_TYPE_UNSPECIFIED */
+        /**
+         * type of RTT measurement method; one of RTT_TYPE_ONE_SIDED or RTT_TYPE_TWO_SIDED.
+         */
         public int requestType;
 
         /** mac address of the device being ranged */
         public String bssid;
 
-        /** channel frequency that the device is on; optional */
+        /**
+         * The primary 20 MHz frequency (in MHz) of the channel over which the client is
+         * communicating with the access point.Similar as ScanResult.frequency
+         */
         public int frequency;
 
-        /** optional channel width. wider channels result in better accuracy,
-         *  but they take longer time, and even get aborted may times; use
-         *  RTT_CHANNEL_WIDTH_UNSPECIFIED if not specifying */
+        /**
+         * channel width used for RTT measurement. User need verify the highest BW the destination
+         * support (from scan result etc) before set this value. Wider channels result usually give
+         * better accuracy. However, the frame loss can increase. Similar as ScanResult.channelWidth
+         */
         public int channelWidth;
 
-        /** number of samples to be taken */
+        /**
+         * Not used if the AP bandwidth is 20 MHz
+         * If the AP use 40, 80 or 160 MHz, this is the center frequency
+         * if the AP use 80 + 80 MHz, this is the center frequency of the first segment
+         * similar as ScanResult.centerFreq0
+         */
+         public int centerFreq0;
+
+         /**
+          * Only used if the AP bandwidth is 80 + 80 MHz
+          * if the AP use 80 + 80 MHz, this is the center frequency of the second segment
+          * similar as ScanResult.centerFreq1
+          */
+          public int centerFreq1;
+        /**
+         * number of samples to be taken
+         * @deprecated  It has been replaced by numSamplesPerBurst
+         */
+        @Deprecated
         public int num_samples;
 
-        /** number of retries if a sample fails */
+        /**
+         * number of retries if a sample fails
+         * @deprecated It has been replaced by numRetriesPerMeasurementFrame
+         */
+        @Deprecated
         public int num_retries;
+
+        /** Number of burst. fixed to 1 for single side RTT*/
+        public int numberBurst;
+
+        /** valid only if numberBurst > 1, interval between burst(ms). Not used by singe side RTT */
+        public int interval;
+
+        /** number of samples to be taken in one burst*/
+        public int numSamplesPerBurst;
+
+        /** number of retries for each measurement frame if a sample fails
+         *  Only used by single side RTT
+         */
+        public int numRetriesPerMeasurementFrame;
+
+        /** number of retries for FTMR frame if fails Only used by 80211MC double side RTT */
+        public int numRetriesPerFTMR;
+
+        /** Request LCI information */
+        public boolean LCIRequest;
+
+        /** Request LCR information */
+        public boolean LCRRequest;
+
+        /** Timeout for each burst, unit of 250 us*/
+        public int burstTimeout;
+
+        /** preamble used for RTT measurement
+         *  should be one of PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT
+         */
+        public int preamble;
+
+        /** bandWidth used for RTT measurement.User need verify the highest BW the destination
+         * support (from scan result etc) before set this value. Wider channels result usually give
+         * better accuracy. However, the frame loss can increase too.
+         * should be one of RTT_CHANNEL_WIDTH_20 to RTT_CHANNEL_WIDTH_80
+         */
+        public int bandwidth;
+
+        public RttParams() {
+            //provide initial value for RttParams
+            deviceType = RTT_PEER_TYPE_AP;
+            numberBurst = 1;
+            numSamplesPerBurst = 8;
+            numRetriesPerMeasurementFrame  = 0;
+            burstTimeout = 40 + numSamplesPerBurst *4;
+            preamble = PREAMBLE_LEGACY;
+            bandwidth = RTT_CHANNEL_WIDTH_20;
+        }
     }
 
     /** pseudo-private class used to parcel arguments */
@@ -121,10 +367,20 @@
                     dest.writeInt(params.deviceType);
                     dest.writeInt(params.requestType);
                     dest.writeString(params.bssid);
-                    dest.writeInt(params.frequency);
                     dest.writeInt(params.channelWidth);
-                    dest.writeInt(params.num_samples);
-                    dest.writeInt(params.num_retries);
+                    dest.writeInt(params.frequency);
+                    dest.writeInt(params.centerFreq0);
+                    dest.writeInt(params.centerFreq1);
+                    dest.writeInt(params.numberBurst);
+                    dest.writeInt(params.interval);
+                    dest.writeInt(params.numSamplesPerBurst);
+                    dest.writeInt(params.numRetriesPerMeasurementFrame);
+                    dest.writeInt(params.numRetriesPerFTMR);
+                    dest.writeInt(params.LCIRequest ? 1 : 0);
+                    dest.writeInt(params.LCRRequest ? 1 : 0);
+                    dest.writeInt(params.burstTimeout);
+                    dest.writeInt(params.preamble);
+                    dest.writeInt(params.bandwidth);
                 }
             } else {
                 dest.writeInt(0);
@@ -148,11 +404,20 @@
                             params[i].deviceType = in.readInt();
                             params[i].requestType = in.readInt();
                             params[i].bssid = in.readString();
-                            params[i].frequency = in.readInt();
                             params[i].channelWidth = in.readInt();
-                            params[i].num_samples = in.readInt();
-                            params[i].num_retries = in.readInt();
-
+                            params[i].frequency = in.readInt();
+                            params[i].centerFreq0 = in.readInt();
+                            params[i].centerFreq1 = in.readInt();
+                            params[i].numberBurst = in.readInt();
+                            params[i].interval = in.readInt();
+                            params[i].numSamplesPerBurst = in.readInt();
+                            params[i].numRetriesPerMeasurementFrame = in.readInt();
+                            params[i].numRetriesPerFTMR = in.readInt();
+                            params[i].LCIRequest = in.readInt() == 1 ? true : false;
+                            params[i].LCRRequest = in.readInt() == 1 ? true : false;
+                            params[i].burstTimeout = in.readInt();
+                            params[i].preamble = in.readInt();
+                            params[i].bandwidth = in.readInt();
                         }
 
                         ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
@@ -165,46 +430,143 @@
                 };
     }
 
+    public class wifiInformationElement {
+        /** Information Element ID*/
+        public int id;
+        public String data;
+    }
     /** specifies RTT results */
     public static class RttResult {
         /** mac address of the device being ranged */
         public String bssid;
 
+        /** # of burst for this measurement*/
+        public int burstNumber;
+
+        /** total number of measurement frames in this measurement*/
+        public int measurementFrameNumber;
+
+        /** total successful number of measurement frames in this measurement*/
+        public int successMeasurementFrameNumber;
+
+        /** Maximum number of frames per burst supported by peer */
+        public int frameNumberPerBurstPeer;
+
         /** status of the request */
         public int status;
 
-        /** type of the request used */
+        /**
+         * type of the request used
+         * @deprecated It has been replaced by measurementType
+         */
+        @Deprecated
         public int requestType;
 
+        /** RTT measurement method type used, shoudl be one of RTT_TYPE_ONE_SIDED or
+         *  RTT_TYPE_TWO_SIDED.
+         */
+        public int measurementType;
+
+        /** please retry RTT measurement after this S since peer indicate busy at ths moment*/
+        public int retryAfterDuration;
+
         /** timestamp of completion, in microsecond since boot */
         public long ts;
 
-        /** average RSSI observed */
+        /** average RSSI observed, unit of 0.5 dB */
         public int rssi;
 
-        /** RSSI spread (i.e. max - min) */
+        /**
+         * RSSI spread (i.e. max - min)
+         * @deprecated It has been replaced by rssi_spread
+         */
+        @Deprecated
         public int rssi_spread;
 
-        /** average transmit rate */
+        /**RSSI spread (i.e. max - min), unit of 0.5 dB */
+        public int rssiSpread;
+
+        /**
+         * average transmit rate
+         * @deprecated It has been replaced by txRate
+         */
+        @Deprecated
         public int tx_rate;
 
-        /** average round trip time in nano second */
+        /** average transmit rate */
+        public int txRate;
+
+        /** average receiving rate */
+        public int rxRate;
+
+       /**
+        * average round trip time in nano second
+        * @deprecated  It has been replaced by rtt
+        */
+        @Deprecated
         public long rtt_ns;
 
-        /** standard deviation observed in round trip time */
+        /** average round trip time in 0.1 nano second */
+        public long rtt;
+
+        /**
+         * standard deviation observed in round trip time
+         * @deprecated It has been replaced by rttStandardDeviation
+         */
+        @Deprecated
         public long rtt_sd_ns;
 
-        /** spread (i.e. max - min) round trip time */
+        /** standard deviation of RTT in 0.1 ns */
+        public long rttStandardDeviation;
+
+        /**
+         * spread (i.e. max - min) round trip time
+         * @deprecated It has been replaced by rttSpread
+         */
+        @Deprecated
         public long rtt_spread_ns;
 
-        /** average distance in centimeter, computed based on rtt_ns */
+        /** spread (i.e. max - min) RTT in 0.1 ns */
+        public long rttSpread;
+
+        /**
+         * average distance in centimeter, computed based on rtt_ns
+         * @deprecated It has been replaced by distance
+         */
+        @Deprecated
         public int distance_cm;
 
-        /** standard deviation observed in distance */
+        /** average distance in cm, computed based on rtt */
+        public int distance;
+
+        /**
+         * standard deviation observed in distance
+         * @deprecated It has been replaced with distanceStandardDeviation
+         */
+        @Deprecated
         public int distance_sd_cm;
 
-        /** spread (i.e. max - min) distance */
+        /** standard deviation observed in distance in cm*/
+        public int distanceStandardDeviation;
+
+        /**
+         * spread (i.e. max - min) distance
+         * @deprecated It has been replaced by distanceSpread
+         */
+        @Deprecated
         public int distance_spread_cm;
+
+        /** spread (i.e. max - min) distance in cm */
+        public int distanceSpread;
+
+        /** the duration of this measurement burst*/
+        public int burstDuration;
+
+        /** LCI information Element*/
+        wifiInformationElement LCI;
+
+        /** LCR information Element*/
+        wifiInformationElement LCR;
     }
 
 
@@ -228,18 +590,28 @@
                 dest.writeInt(mResults.length);
                 for (RttResult result : mResults) {
                     dest.writeString(result.bssid);
+                    dest.writeInt(result.burstNumber);
+                    dest.writeInt(result.measurementFrameNumber);
+                    dest.writeInt(result.successMeasurementFrameNumber);
+                    dest.writeInt(result.frameNumberPerBurstPeer);
                     dest.writeInt(result.status);
-                    dest.writeInt(result.requestType);
+                    dest.writeInt(result.measurementType);
+                    dest.writeInt(result.retryAfterDuration);
                     dest.writeLong(result.ts);
                     dest.writeInt(result.rssi);
-                    dest.writeInt(result.rssi_spread);
-                    dest.writeInt(result.tx_rate);
-                    dest.writeLong(result.rtt_ns);
-                    dest.writeLong(result.rtt_sd_ns);
-                    dest.writeLong(result.rtt_spread_ns);
-                    dest.writeInt(result.distance_cm);
-                    dest.writeInt(result.distance_sd_cm);
-                    dest.writeInt(result.distance_spread_cm);
+                    dest.writeInt(result.rssiSpread);
+                    dest.writeInt(result.txRate);
+                    dest.writeLong(result.rtt);
+                    dest.writeLong(result.rttStandardDeviation);
+                    dest.writeLong(result.rttSpread);
+                    dest.writeInt(result.distance);
+                    dest.writeInt(result.distanceStandardDeviation);
+                    dest.writeInt(result.distanceSpread);
+                    dest.writeInt(result.burstDuration);
+                    //dest.writeInt(result.LCI.id);
+                    //dest.writeString(result.LCI.data);
+                    //dest.writeInt(result.LCR.id);
+                    //dest.writeString(result.LCR.data);
                 }
             } else {
                 dest.writeInt(0);
@@ -261,18 +633,28 @@
                         for (int i = 0; i < num; i++) {
                             results[i] = new RttResult();
                             results[i].bssid = in.readString();
+                            results[i].burstNumber = in.readInt();
+                            results[i].measurementFrameNumber = in.readInt();
+                            results[i].successMeasurementFrameNumber = in.readInt();
+                            results[i].frameNumberPerBurstPeer = in.readInt();
                             results[i].status = in.readInt();
-                            results[i].requestType = in.readInt();
+                            results[i].measurementType = in.readInt();
+                            results[i].retryAfterDuration = in.readInt();
                             results[i].ts = in.readLong();
                             results[i].rssi = in.readInt();
-                            results[i].rssi_spread = in.readInt();
-                            results[i].tx_rate = in.readInt();
-                            results[i].rtt_ns = in.readLong();
-                            results[i].rtt_sd_ns = in.readLong();
-                            results[i].rtt_spread_ns = in.readLong();
-                            results[i].distance_cm = in.readInt();
-                            results[i].distance_sd_cm = in.readInt();
-                            results[i].distance_spread_cm = in.readInt();
+                            results[i].rssiSpread = in.readInt();
+                            results[i].txRate = in.readInt();
+                            results[i].rtt = in.readLong();
+                            results[i].rttStandardDeviation = in.readLong();
+                            results[i].rttSpread = in.readLong();
+                            results[i].distance = in.readInt();
+                            results[i].distanceStandardDeviation = in.readInt();
+                            results[i].distanceSpread = in.readInt();
+                            results[i].burstDuration = in.readInt();
+                            //results[i].LCI.id = in.readInt();
+                            //results[i].LCI.data = in.readString();
+                            //results[i].LCR.id = in.readInt();
+                            //results[i].LCR.data = in.readString();
                         }
 
                         ParcelableRttResults parcelableResults = new ParcelableRttResults(results);
@@ -292,7 +674,70 @@
         public void onAborted();
     }
 
+    private boolean rttParamSanity(RttParams params, int index) {
+        if (mRttCapabilities == null) {
+            if(getRttCapabilities() == null) {
+                Log.e(TAG, "Can not get RTT capabilities");
+                //throw new IllegalStateException("RTT chip is not working");
+            }
+        }
+
+        if (params.deviceType != RTT_PEER_TYPE_AP) {
+            return false;
+        } else if (params.requestType != RTT_TYPE_ONE_SIDED && params.requestType !=
+                RTT_TYPE_TWO_SIDED) {
+            Log.e(TAG, "Request " + index + ": Illegal Request Type: " + params.requestType);
+            return false;
+        } else if (params.requestType == RTT_TYPE_ONE_SIDED &&
+                !mRttCapabilities.oneSidedRttSupported) {
+            Log.e(TAG, "Request " + index + ": One side RTT is not supported");
+            return false;
+        } else if (params.requestType == RTT_TYPE_TWO_SIDED &&
+                !mRttCapabilities.twoSided11McRttSupported) {
+            Log.e(TAG, "Request " + index + ": two side RTT is not supported");
+            return false;
+        } else if ( params.numberBurst <= 0 ) {
+            Log.e(TAG, "Request " + index + ": Illegal number of burst: " + params.numberBurst);
+            return false;
+        } else if (params.numberBurst >  1 && params.interval <= 0) {
+            Log.e(TAG, "Request " + index + ": Illegal interval value: " + params.interval);
+            return false;
+        } else if (params.numSamplesPerBurst <= 0) {
+            Log.e(TAG, "Request " + index + ": Illegal sample number per burst: " +
+                    params.numSamplesPerBurst);
+            return false;
+        } else if (params.numRetriesPerMeasurementFrame < 0 || params.numRetriesPerFTMR < 0) {
+            Log.e(TAG, "Request " + index + ": Illegal retry number");
+            return false;
+        } else if (params.LCIRequest && !mRttCapabilities.lciSupported) {
+            Log.e(TAG, "Request " + index + ": LCI is not supported");
+            return false;
+        } else if (params.LCRRequest && !mRttCapabilities.lcrSupported) {
+            Log.e(TAG, "Request " + index + ": LCR is not supported");
+            return false;
+        } else if (params.burstTimeout <= 0){
+            Log.e(TAG, "Request " + index + ": Illegal burst timeout: " + params.burstTimeout);
+            return false;
+        } else if ((params.preamble & mRttCapabilities.preambleSupported) == 0) {
+            Log.e(TAG, "Request " + index + ": Do not support this preamble: " + params.preamble);
+            return false;
+        } else if ((params.bandwidth & mRttCapabilities.bwSupported) == 0) {
+            Log.e(TAG, "Request " + index + ": Do not support this bandwidth: " + params.bandwidth);
+            return false;
+        }
+
+        return true;
+    }
+
     public void startRanging(RttParams[] params, RttListener listener) {
+        int index  = 0;
+        for(RttParams rttParam : params) {
+            if (!rttParamSanity(rttParam, index)) {
+                throw new IllegalArgumentException("RTT Request Parameter Illegal");
+            }
+            index++;
+        }
+
         validateChannel();
         ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
         sAsyncChannel.sendMessage(CMD_OP_START_RANGING,
@@ -315,12 +760,14 @@
 
     private Context mContext;
     private IRttManager mService;
+    private RttCapabilities mRttCapabilities;
 
     private static final int INVALID_KEY = 0;
     private static int sListenerKey = 1;
 
     private static final SparseArray sListenerMap = new SparseArray();
     private static final Object sListenerMapLock = new Object();
+    private static final Object sCapabilitiesLock = new Object();
 
     private static AsyncChannel sAsyncChannel;
     private static CountDownLatch sConnected;
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index b4f4927..e8a51e3 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -16,8 +16,6 @@
 
 package android.net.wifi;
 
-import android.net.wifi.passpoint.WifiPasspointInfo;
-import android.net.wifi.passpoint.WifiPasspointManager;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -215,11 +213,19 @@
     public int distanceSdCm;
 
     /**
-     * Passpoint ANQP information. This is not fetched automatically.
-     * Use {@link WifiPasspointManager#requestAnqpInfo} to request ANQP info.
-     * {@hide}
+     * Indicates if the scan result represents a passpoint AP
      */
-    public WifiPasspointInfo passpoint;
+    public boolean passpointNetwork;
+
+    /**
+     * Indicates if venue name
+     */
+    public String venueName;
+
+    /**
+     * Indicates operator name
+     */
+    public String operatorFriendlyName;
 
     /**
      * {@hide}
@@ -292,6 +298,7 @@
         this.centerFreq0 = UNSPECIFIED;
         this.centerFreq1 = UNSPECIFIED;
         this.is80211McRTTResponder = false;
+        this.passpointNetwork = false;
     }
 
     /** {@hide} */
@@ -310,6 +317,7 @@
         this.centerFreq0 = UNSPECIFIED;
         this.centerFreq1 = UNSPECIFIED;
         this.is80211McRTTResponder = false;
+        this.passpointNetwork = false;
     }
 
     /** {@hide} */
@@ -329,6 +337,7 @@
         this.centerFreq0 = centerFreq0;
         this.centerFreq1 = centerFreq1;
         this.is80211McRTTResponder = is80211McRTTResponder;
+        this.passpointNetwork = false;
     }
 
     /** copy constructor {@hide} */
@@ -348,13 +357,15 @@
             distanceCm = source.distanceCm;
             distanceSdCm = source.distanceSdCm;
             seen = source.seen;
-            passpoint = source.passpoint;
             autoJoinStatus = source.autoJoinStatus;
             untrusted = source.untrusted;
             numConnection = source.numConnection;
             numUsage = source.numUsage;
             numIpConfigFailures = source.numIpConfigFailures;
             isAutoJoinCandidate = source.isAutoJoinCandidate;
+            passpointNetwork = source.passpointNetwork;
+            venueName = source.venueName;
+            operatorFriendlyName = source.operatorFriendlyName;
         }
     }
 
@@ -388,7 +399,7 @@
         sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")).
                 append("(cm)");
 
-        sb.append(", passpoint: ").append(passpoint != null ? "yes" : "no");
+        sb.append(", passpoint: ").append(passpointNetwork ? "yes" : "no");
         if (autoJoinStatus != 0) {
             sb.append(", status: ").append(autoJoinStatus);
         }
@@ -431,12 +442,10 @@
         dest.writeInt(numUsage);
         dest.writeInt(numIpConfigFailures);
         dest.writeInt(isAutoJoinCandidate);
-        if (passpoint != null) {
-            dest.writeInt(1);
-            passpoint.writeToParcel(dest, flags);
-        } else {
-            dest.writeInt(0);
-        }
+        dest.writeInt(passpointNetwork ? 1 : 0);
+        dest.writeString(venueName);
+        dest.writeString(operatorFriendlyName);
+
         if (informationElements != null) {
             dest.writeInt(informationElements.length);
             for (int i = 0; i < informationElements.length; i++) {
@@ -478,9 +487,9 @@
                 sr.numUsage = in.readInt();
                 sr.numIpConfigFailures = in.readInt();
                 sr.isAutoJoinCandidate = in.readInt();
-                if (in.readInt() == 1) {
-                    sr.passpoint = WifiPasspointInfo.CREATOR.createFromParcel(in);
-                }
+                sr.passpointNetwork = in.readInt() == 1;
+                sr.venueName = in.readString();
+                sr.operatorFriendlyName = in.readString();
                 int n = in.readInt();
                 if (n != 0) {
                     sr.informationElements = new InformationElement[n];
diff --git a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
index 6263463..0f73342 100644
--- a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
+++ b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
@@ -26,12 +26,35 @@
  * @hide
  */
 public final class WifiActivityEnergyInfo implements Parcelable {
-    private final long mTimestamp;
-    private final int mStackState;
-    private final int mControllerTxTimeMs;
-    private final int mControllerRxTimeMs;
-    private final int mControllerIdleTimeMs;
-    private final int mControllerEnergyUsed;
+    /**
+     * @hide
+     */
+    public long mTimestamp;
+
+    /**
+     * @hide
+     */
+    public int mStackState;
+
+    /**
+     * @hide
+     */
+    public int mControllerTxTimeMs;
+
+    /**
+     * @hide
+     */
+    public int mControllerRxTimeMs;
+
+    /**
+     * @hide
+     */
+    public int mControllerIdleTimeMs;
+
+    /**
+     * @hide
+     */
+    public int mControllerEnergyUsed;
 
     public static final int STACK_STATE_INVALID = 0;
     public static final int STACK_STATE_STATE_ACTIVE = 1;
@@ -118,6 +141,7 @@
         return (int)mControllerIdleTimeMs;
     }
 
+
     /**
      * product of current(mA), voltage(V) and time(ms)
      * @return energy used
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 7e04f2b..11bdebb 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -973,13 +973,18 @@
             }
         }
 
-        if (FQDN != null) {
-            /* must have a providerFriendlyName */
-            if (providerFriendlyName == null) {
+        if (TextUtils.isEmpty(FQDN) == false) {
+            /* this is passpoint configuration; it must not have an SSID */
+            if (TextUtils.isEmpty(SSID) == false) {
+                return false;
+            }
+            /* this is passpoint configuration; it must have a providerFriendlyName */
+            if (TextUtils.isEmpty(providerFriendlyName)) {
                 return false;
             }
             /* this is passpoint configuration; it must have enterprise config */
-            if (enterpriseConfig == null) {
+            if (enterpriseConfig == null
+                    || enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.NONE ) {
                 return false;
             }
         }
@@ -989,6 +994,16 @@
     }
 
     /**
+     * Identify if this configuration represents a passpoint network
+     */
+    public boolean isPasspoint() {
+        return !TextUtils.isEmpty(FQDN)
+                && !TextUtils.isEmpty(providerFriendlyName)
+                && enterpriseConfig != null
+                && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
+    }
+
+    /**
      * Helper function, identify if a configuration is linked
      * @hide
      */
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 36fc96b..440ad61 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -235,8 +235,10 @@
         public static final int SIM     = 4;
         /** EAP-Authentication and Key Agreement */
         public static final int AKA     = 5;
+        /** EAP-Authentication and Key Agreement Prime */
+        public static final int AKA_PRIME = 6;
         /** @hide */
-        public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA" };
+        public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'" };
 
         /** Prevent initialization */
         private Eap() {}
@@ -286,6 +288,7 @@
             case Eap.TTLS:
             case Eap.SIM:
             case Eap.AKA:
+            case Eap.AKA_PRIME:
                 mFields.put(EAP_KEY, Eap.strings[eapMethod]);
                 mFields.put(OPP_KEY_CACHING, "1");
                 break;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index b292c22..275c7d1 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -861,6 +861,14 @@
     public static final int WIFI_FEATURE_TDLS_OFFCHANNEL  = 0x2000;  // Support for TDLS off channel
     /** @hide */
     public static final int WIFI_FEATURE_EPR              = 0x4000;  // Enhanced power reporting
+    /** @hide */
+    public static final int WIFI_FEATURE_AP_STA            = 0x8000;  // Support for AP STA Concurrency
+    /** @hide */
+    public static final int WIFI_FEATURE_LINK_LAYER_STATS  = 0x10000; // Link layer stats collection
+    /** @hide */
+    public static final int WIFI_FEATURE_LOGGER            = 0x20000; // WiFi Logger
+    /** @hide */
+    public static final int WIFI_FEATURE_HAL_EPNO          = 0x40000; // WiFi PNO enhanced
 
     private int getSupportedFeatures() {
         try {
@@ -972,7 +980,7 @@
      * @return true if this adapter supports advanced power/performance counters
      */
     public boolean isEnhancedPowerReportingSupported() {
-        return isFeatureSupported(WIFI_FEATURE_EPR);
+        return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS);
     }
 
     /**
@@ -2598,6 +2606,48 @@
         }
     }
 
+    /**
+     * Set setting for allowing Scans when infrastructure is associated
+     * @hide
+     */
+    public void setAllowScansWhileAssociated(boolean enabled) {
+        try {
+            mService.setAllowScansWhileAssociated(enabled);
+        } catch (RemoteException e) {
 
+        }
+    }
 
+    /**
+     * Get setting for allowing Scans when infrastructure is associated
+     * @hide
+     */
+    public boolean getAllowScansWhileAssociated() {
+        try {
+            return mService.getAllowScansWhileAssociated();
+        } catch (RemoteException e) {
+        }
+        return false;
+    }
+
+    /**
+     * Resets all wifi manager settings back to factory defaults.
+     *
+     * @hide
+     */
+    public void factoryReset() {
+        // Enable wifi
+        setWifiEnabled(true);
+        // Delete all Wifi SSIDs
+        List<WifiConfiguration> networks = getConfiguredNetworks();
+        if (networks != null) {
+            for (WifiConfiguration config : networks) {
+                removeNetwork(config.networkId);
+            }
+            saveConfiguration();
+        }
+
+        // Turn mobile hotspot off
+        setWifiApEnabled(null, false);
+    }
 }
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
index b9b17eb..0245a3d 100644
--- a/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
@@ -262,7 +262,7 @@
                 for (ScanResult sr : mAnqpRequest)
                     if (sr.BSSID.equals(result.bssid)) {
                         Log.d(TAG, "find hit " + result.bssid);
-                        sr.passpoint = result;
+                        /* sr.passpoint = result; */
                         mAnqpRequest.remove(sr);
                         Log.d(TAG, "mAnqpRequest.len=" + mAnqpRequest.size());
                         break;