Merge "Allow badging updates to install sessions." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index e8e5fec..dab4f64 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -260,6 +260,7 @@
 
   public static final class R.attr {
     ctor public R.attr();
+    field public static final int __removed2 = 16843937; // 0x10104a1
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -482,7 +483,7 @@
     field public static final int datePickerMode = 16843956; // 0x10104b4
     field public static final int datePickerStyle = 16843612; // 0x101035c
     field public static final int dateTextAppearance = 16843593; // 0x1010349
-    field public static final int dayOfWeekBackgroundColor = 16843924; // 0x1010494
+    field public static final int dayOfWeekBackground = 16843924; // 0x1010494
     field public static final int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
     field public static final int defaultValue = 16843245; // 0x10101ed
@@ -612,12 +613,20 @@
     field public static final int format12Hour = 16843722; // 0x10103ca
     field public static final int format24Hour = 16843723; // 0x10103cb
     field public static final int fragment = 16843491; // 0x10102e3
+    field public static final int fragmentAllowEnterTransitionOverlap = 16843977; // 0x10104c9
+    field public static final int fragmentAllowReturnTransitionOverlap = 16843978; // 0x10104ca
     field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7
     field public static final int fragmentCloseExitAnimation = 16843496; // 0x10102e8
+    field public static final int fragmentEnterTransition = 16843972; // 0x10104c4
+    field public static final int fragmentExitTransition = 16843971; // 0x10104c3
     field public static final int fragmentFadeEnterAnimation = 16843497; // 0x10102e9
     field public static final int fragmentFadeExitAnimation = 16843498; // 0x10102ea
     field public static final int fragmentOpenEnterAnimation = 16843493; // 0x10102e5
     field public static final int fragmentOpenExitAnimation = 16843494; // 0x10102e6
+    field public static final int fragmentReenterTransition = 16843976; // 0x10104c8
+    field public static final int fragmentReturnTransition = 16843974; // 0x10104c6
+    field public static final int fragmentSharedElementEnterTransition = 16843973; // 0x10104c5
+    field public static final int fragmentSharedElementReturnTransition = 16843975; // 0x10104c7
     field public static final int freezesText = 16843116; // 0x101016c
     field public static final int fromAlpha = 16843210; // 0x10101ca
     field public static final int fromDegrees = 16843187; // 0x10101b3
@@ -655,7 +664,6 @@
     field public static final int hasCode = 16842764; // 0x101000c
     field public static final int headerAmPmTextAppearance = 16843936; // 0x10104a0
     field public static final int headerBackground = 16843055; // 0x101012f
-    field public static final int headerBackgroundColor = 16843937; // 0x10104a1
     field public static final int headerDayOfMonthTextAppearance = 16843927; // 0x1010497
     field public static final int headerDividersEnabled = 16843310; // 0x101022e
     field public static final int headerMonthTextAppearance = 16843926; // 0x1010496
@@ -960,6 +968,7 @@
     field public static final int pathData = 16843807; // 0x101041f
     field public static final int pathPattern = 16842796; // 0x101002c
     field public static final int pathPrefix = 16842795; // 0x101002b
+    field public static final int patternPathData = 16843979; // 0x10104cb
     field public static final int permission = 16842758; // 0x1010006
     field public static final int permissionFlags = 16843719; // 0x10103c7
     field public static final int permissionGroup = 16842762; // 0x101000a
@@ -1418,7 +1427,7 @@
     field public static final int windowActionBarOverlay = 16843492; // 0x10102e4
     field public static final int windowActionModeOverlay = 16843485; // 0x10102dd
     field public static final int windowAllowEnterTransitionOverlap = 16843836; // 0x101043c
-    field public static final int windowAllowExitTransitionOverlap = 16843835; // 0x101043b
+    field public static final int windowAllowReturnTransitionOverlap = 16843835; // 0x101043b
     field public static final int windowAnimationStyle = 16842926; // 0x10100ae
     field public static final int windowBackground = 16842836; // 0x1010054
     field public static final int windowClipToOutline = 16843948; // 0x10104ac
@@ -3447,7 +3456,7 @@
     method public boolean navigateUpToFromChild(android.app.Activity, android.content.Intent);
     method public void onActionModeFinished(android.view.ActionMode);
     method public void onActionModeStarted(android.view.ActionMode);
-    method protected void onActivityReenter(int, android.content.Intent);
+    method public void onActivityReenter(int, android.content.Intent);
     method protected void onActivityResult(int, int, android.content.Intent);
     method public void onAttachFragment(android.app.Fragment);
     method public void onAttachedToWindow();
@@ -3458,7 +3467,7 @@
     method public boolean onContextItemSelected(android.view.MenuItem);
     method public void onContextMenuClosed(android.view.Menu);
     method protected void onCreate(android.os.Bundle);
-    method protected void onCreate(android.os.Bundle, android.os.PersistableBundle);
+    method public void onCreate(android.os.Bundle, android.os.PersistableBundle);
     method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo);
     method public java.lang.CharSequence onCreateDescription();
     method protected deprecated android.app.Dialog onCreateDialog(int);
@@ -3490,7 +3499,7 @@
     method public void onPanelClosed(int, android.view.Menu);
     method protected void onPause();
     method protected void onPostCreate(android.os.Bundle);
-    method protected void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
+    method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
     method protected void onPostResume();
     method protected deprecated void onPrepareDialog(int, android.app.Dialog);
     method protected deprecated void onPrepareDialog(int, android.app.Dialog, android.os.Bundle);
@@ -3500,11 +3509,11 @@
     method public void onProvideAssistData(android.os.Bundle);
     method protected void onRestart();
     method protected void onRestoreInstanceState(android.os.Bundle);
-    method protected void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
+    method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method protected void onResume();
     method public deprecated java.lang.Object onRetainNonConfigurationInstance();
     method protected void onSaveInstanceState(android.os.Bundle);
-    method protected void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
+    method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method public boolean onSearchRequested();
     method protected void onStart();
     method protected void onStop();
@@ -3536,8 +3545,8 @@
     method public void setContentView(android.view.View);
     method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public final void setDefaultKeyMode(int);
-    method public void setEnterSharedElementListener(android.app.SharedElementListener);
-    method public void setExitSharedElementListener(android.app.SharedElementListener);
+    method public void setEnterSharedElementCallback(android.app.SharedElementCallback);
+    method public void setExitSharedElementCallback(android.app.SharedElementCallback);
     method public final void setFeatureDrawable(int, android.graphics.drawable.Drawable);
     method public final void setFeatureDrawableAlpha(int, int);
     method public final void setFeatureDrawableResource(int, int);
@@ -3915,6 +3924,7 @@
     field public static final int MODE_IGNORED = 1; // 0x1
     field public static final java.lang.String OPSTR_COARSE_LOCATION = "android:coarse_location";
     field public static final java.lang.String OPSTR_FINE_LOCATION = "android:fine_location";
+    field public static final java.lang.String OPSTR_GET_USAGE_STATS = "android:get_usage_stats";
     field public static final java.lang.String OPSTR_MONITOR_HIGH_POWER_LOCATION = "android:monitor_location_high_power";
     field public static final java.lang.String OPSTR_MONITOR_LOCATION = "android:monitor_location";
   }
@@ -4243,14 +4253,22 @@
     method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public final boolean equals(java.lang.Object);
     method public final android.app.Activity getActivity();
+    method public boolean getAllowEnterTransitionOverlap();
+    method public boolean getAllowReturnTransitionOverlap();
     method public final android.os.Bundle getArguments();
     method public final android.app.FragmentManager getChildFragmentManager();
+    method public android.transition.Transition getEnterTransition();
+    method public android.transition.Transition getExitTransition();
     method public final android.app.FragmentManager getFragmentManager();
     method public final int getId();
     method public android.app.LoaderManager getLoaderManager();
     method public final android.app.Fragment getParentFragment();
+    method public android.transition.Transition getReenterTransition();
     method public final android.content.res.Resources getResources();
     method public final boolean getRetainInstance();
+    method public android.transition.Transition getReturnTransition();
+    method public android.transition.Transition getSharedElementEnterTransition();
+    method public android.transition.Transition getSharedElementReturnTransition();
     method public final java.lang.String getString(int);
     method public final java.lang.String getString(int, java.lang.Object...);
     method public final java.lang.String getTag();
@@ -4299,11 +4317,21 @@
     method public void onViewCreated(android.view.View, android.os.Bundle);
     method public void onViewStateRestored(android.os.Bundle);
     method public void registerForContextMenu(android.view.View);
+    method public void setAllowEnterTransitionOverlap(boolean);
+    method public void setAllowReturnTransitionOverlap(boolean);
     method public void setArguments(android.os.Bundle);
+    method public void setEnterSharedElementTransitionCallback(android.app.SharedElementCallback);
+    method public void setEnterTransition(android.transition.Transition);
+    method public void setExitSharedElementTransitionCallback(android.app.SharedElementCallback);
+    method public void setExitTransition(android.transition.Transition);
     method public void setHasOptionsMenu(boolean);
     method public void setInitialSavedState(android.app.Fragment.SavedState);
     method public void setMenuVisibility(boolean);
+    method public void setReenterTransition(android.transition.Transition);
     method public void setRetainInstance(boolean);
+    method public void setReturnTransition(android.transition.Transition);
+    method public void setSharedElementEnterTransition(android.transition.Transition);
+    method public void setSharedElementReturnTransition(android.transition.Transition);
     method public void setTargetFragment(android.app.Fragment, int);
     method public void setUserVisibleHint(boolean);
     method public void startActivity(android.content.Intent);
@@ -4403,7 +4431,6 @@
     method public abstract android.app.FragmentTransaction setBreadCrumbTitle(java.lang.CharSequence);
     method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
     method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
-    method public abstract android.app.FragmentTransaction setCustomTransition(int, int);
     method public abstract android.app.FragmentTransaction setTransition(int);
     method public abstract android.app.FragmentTransaction setTransitionStyle(int);
     method public abstract android.app.FragmentTransaction show(android.app.Fragment);
@@ -5166,14 +5193,14 @@
     field public static final int START_STICKY_COMPATIBILITY = 0; // 0x0
   }
 
-  public abstract class SharedElementListener {
-    ctor public SharedElementListener();
-    method public android.os.Parcelable captureSharedElementSnapshot(android.view.View, android.graphics.Matrix, android.graphics.RectF);
-    method public android.view.View createSnapshotView(android.content.Context, android.os.Parcelable);
-    method public void handleRejectedSharedElements(java.util.List<android.view.View>);
-    method public void remapSharedElements(java.util.List<java.lang.String>, java.util.Map<java.lang.String, android.view.View>);
-    method public void setSharedElementEnd(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
-    method public void setSharedElementStart(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
+  public abstract class SharedElementCallback {
+    ctor public SharedElementCallback();
+    method public android.os.Parcelable onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix, android.graphics.RectF);
+    method public android.view.View onCreateSnapshotView(android.content.Context, android.os.Parcelable);
+    method public void onMapSharedElements(java.util.List<java.lang.String>, java.util.Map<java.lang.String, android.view.View>);
+    method public void onRejectSharedElements(java.util.List<android.view.View>);
+    method public void onSharedElementEnd(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
+    method public void onSharedElementStart(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
   }
 
   public deprecated class TabActivity extends android.app.ActivityGroup {
@@ -5365,8 +5392,8 @@
     field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
     field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
     field public static final java.lang.String ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED";
-    field public static final java.lang.String ACTION_LOCK_TASK_ENTERING = "android.app.action.ACTION_LOCK_TASK_ENTERING";
-    field public static final java.lang.String ACTION_LOCK_TASK_EXITING = "android.app.action.ACTION_LOCK_TASK_EXITING";
+    field public static final java.lang.String ACTION_LOCK_TASK_ENTERING = "android.app.action.LOCK_TASK_ENTERING";
+    field public static final java.lang.String ACTION_LOCK_TASK_EXITING = "android.app.action.LOCK_TASK_EXITING";
     field public static final java.lang.String ACTION_PASSWORD_CHANGED = "android.app.action.ACTION_PASSWORD_CHANGED";
     field public static final java.lang.String ACTION_PASSWORD_EXPIRING = "android.app.action.ACTION_PASSWORD_EXPIRING";
     field public static final java.lang.String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
@@ -5398,7 +5425,7 @@
     method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
     method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
-    method public java.util.List<byte[]> getInstalledCaCerts();
+    method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
@@ -5419,7 +5446,7 @@
     method public boolean getScreenCaptureDisabled(android.content.ComponentName);
     method public boolean getStorageEncryption(android.content.ComponentName);
     method public int getStorageEncryptionStatus();
-    method public boolean hasCaCertInstalled(byte[]);
+    method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
     method public boolean hasGrantedPolicy(android.content.ComponentName, int);
     method public boolean installCaCert(android.content.ComponentName, byte[]);
     method public boolean isActivePasswordSufficient();
@@ -5481,23 +5508,23 @@
     field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0
     field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
     field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "android.app.extra.DEFAULT_MANAGED_PROFILE_NAME";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.DEVICE_ADMIN_PACKAGE_CHECKSUM";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
+    field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.deviceAdminPackageName";
-    field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.ManagedProfileEmailAddress";
-    field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.LOCALE";
-    field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.LOCAL_TIME";
-    field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.TIME_ZONE";
-    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.WIFI_HIDDEN";
-    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.WIFI_PAC_URL";
-    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PASSWORD = "android.app.extra.WIFI_PASSWORD";
-    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS = "android.app.extra.WIFI_PROXY_BYPASS_HOSTS";
-    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_HOST = "android.app.extra.WIFI_PROXY_HOST";
-    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.WIFI_PROXY_PORT";
-    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.WIFI_SECURITY_TYPE";
-    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.WIFI_SSID";
+    field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
+    field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
+    field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
+    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
+    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.PROVISIONING_WIFI_PAC_URL";
+    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PASSWORD = "android.app.extra.PROVISIONING_WIFI_PASSWORD";
+    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS = "android.app.extra.PROVISIONING_WIFI_PROXY_BYPASS";
+    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_HOST = "android.app.extra.PROVISIONING_WIFI_PROXY_HOST";
+    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
+    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
+    field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID";
     field public static int FLAG_MANAGED_CAN_ACCESS_PARENT;
     field public static int FLAG_PARENT_CAN_ACCESS_MANAGED;
     field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
@@ -5508,6 +5535,7 @@
     field public static final int KEYGUARD_DISABLE_TRUST_AGENTS = 16; // 0x10
     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 KEY_PROVISIONING_EMAIL_ADDRESS = "android.app.key.PROVISIONING_EMAIL_ADDRESS";
     field public static final java.lang.String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning";
     field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000
     field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000
@@ -5679,6 +5707,19 @@
 
 package android.app.usage {
 
+  public final class ConfigurationStats implements android.os.Parcelable {
+    ctor public ConfigurationStats(android.app.usage.ConfigurationStats);
+    method public int describeContents();
+    method public int getActivationCount();
+    method public android.content.res.Configuration getConfiguration();
+    method public long getFirstTimeStamp();
+    method public long getLastTimeActive();
+    method public long getLastTimeStamp();
+    method public long getTotalTimeActive();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public final class UsageEvents implements android.os.Parcelable {
     method public int describeContents();
     method public boolean getNextEvent(android.app.usage.UsageEvents.Event);
@@ -5691,9 +5732,11 @@
   public static final class UsageEvents.Event {
     ctor public UsageEvents.Event();
     method public java.lang.String getClassName();
+    method public android.content.res.Configuration getConfiguration();
     method public int getEventType();
     method public java.lang.String getPackageName();
     method public long getTimeStamp();
+    field public static final int CONFIGURATION_CHANGE = 5; // 0x5
     field public static final int MOVE_TO_BACKGROUND = 2; // 0x2
     field public static final int MOVE_TO_FOREGROUND = 1; // 0x1
     field public static final int NONE = 0; // 0x0
@@ -5714,6 +5757,7 @@
 
   public final class UsageStatsManager {
     method public java.util.Map<java.lang.String, android.app.usage.UsageStats> queryAndAggregateUsageStats(long, long);
+    method public java.util.List<android.app.usage.ConfigurationStats> queryConfigurations(int, long, long);
     method public android.app.usage.UsageEvents queryEvents(long, long);
     method public java.util.List<android.app.usage.UsageStats> queryUsageStats(int, long, long);
     field public static final int INTERVAL_BEST = 4; // 0x4
@@ -5832,7 +5876,7 @@
     field public static final int RESIZE_VERTICAL = 2; // 0x2
     field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1
     field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2
-    field public static final int WIDGET_CATEGORY_RECENTS = 4; // 0x4
+    field public static final int WIDGET_CATEGORY_SEARCHBOX = 4; // 0x4
     field public int autoAdvanceViewId;
     field public android.content.ComponentName configure;
     field public int icon;
@@ -7840,7 +7884,7 @@
     field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
     field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
     field public static final java.lang.String EXTRA_UID = "android.intent.extra.UID";
-    field public static final java.lang.String EXTRA_USER = "android.intent.extra.user";
+    field public static final java.lang.String EXTRA_USER = "android.intent.extra.USER";
     field public static final int FILL_IN_ACTION = 1; // 0x1
     field public static final int FILL_IN_CATEGORIES = 4; // 0x4
     field public static final int FILL_IN_CLIP_DATA = 128; // 0x80
@@ -8803,6 +8847,9 @@
     method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
     method public abstract java.lang.String[] getSystemSharedLibraryNames();
     method public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public abstract android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
+    method public abstract android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle);
+    method public abstract java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
     method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
     method public abstract boolean hasSystemFeature(java.lang.String);
     method public abstract boolean isSafeMode();
@@ -11395,8 +11442,6 @@
     ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
     method public int getColor();
     method public android.graphics.PorterDuff.Mode getMode();
-    method public void setColor(int);
-    method public void setMode(android.graphics.PorterDuff.Mode);
   }
 
   public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -13975,7 +14020,7 @@
     ctor public SettingInjectorService(java.lang.String);
     method public final android.os.IBinder onBind(android.content.Intent);
     method protected abstract boolean onGetEnabled();
-    method protected deprecated java.lang.String onGetSummary();
+    method protected abstract deprecated java.lang.String onGetSummary();
     method public final void onStart(android.content.Intent, int);
     method public final int onStartCommand(android.content.Intent, int, int);
     field public static final java.lang.String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged";
@@ -15896,13 +15941,13 @@
   }
 
   public abstract class VolumeProvider {
-    ctor public VolumeProvider(int, int);
+    ctor public VolumeProvider(int, int, int);
+    method public final int getCurrentVolume();
     method public final int getMaxVolume();
     method public final int getVolumeControl();
-    method public final void notifyVolumeChanged();
     method public void onAdjustVolume(int);
-    method public abstract int onGetCurrentVolume();
     method public void onSetVolumeTo(int);
+    method public final void setCurrentVolume(int);
     field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
     field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
     field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
@@ -16974,6 +17019,7 @@
 package android.net {
 
   public class ConnectivityManager {
+    method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
     method public android.net.NetworkInfo getActiveNetworkInfo();
     method public android.net.NetworkInfo[] getAllNetworkInfo();
     method public android.net.Network[] getAllNetworks();
@@ -16987,8 +17033,8 @@
     method public boolean isActiveNetworkMetered();
     method public boolean isDefaultNetworkActive();
     method public static boolean isNetworkTypeValid(int);
-    method public void registerDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
+    method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
     method public void reportBadNetwork(android.net.Network);
     method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public deprecated boolean requestRouteToHost(int, int);
@@ -16996,7 +17042,6 @@
     method public static boolean setProcessDefaultNetwork(android.net.Network);
     method public deprecated int startUsingNetworkFeature(int, java.lang.String);
     method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
-    method public void unregisterDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
     method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
     field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
     field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
@@ -17070,6 +17115,7 @@
     method public int getPrefixLength();
     method public int getScope();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
   }
 
   public final class LinkProperties implements android.os.Parcelable {
@@ -17282,6 +17328,7 @@
     method public android.net.Uri getPacFileUrl();
     method public int getPort();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
   }
 
   public abstract class PskKeyManager {
@@ -17953,23 +18000,6 @@
     enum_constant public static final android.net.wifi.SupplicantState UNINITIALIZED;
   }
 
-  public class WifiAdapter implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.lang.String getName();
-    method public boolean is5GHzBandSupported();
-    method public boolean isDeviceToApRttSupported();
-    method public boolean isDeviceToDeviceRttSupported();
-    method public boolean isEnhancedPowerReportingSupported();
-    method public boolean isOffChannelTdlsSupported();
-    method public boolean isP2pSupported();
-    method public boolean isPasspointSupported();
-    method public boolean isPortableHotspotSupported();
-    method public boolean isPreferredNetworkOffloadSupported();
-    method public boolean isTdlsSupported();
-    method public boolean isWifiScannerSupported();
-    method public void writeToParcel(android.os.Parcel, int);
-  }
-
   public class WifiConfiguration implements android.os.Parcelable {
     ctor public WifiConfiguration();
     method public int describeContents();
@@ -18103,7 +18133,7 @@
   public class WifiManager {
     method public int addNetwork(android.net.wifi.WifiConfiguration);
     method public static int calculateSignalLevel(int, int);
-    method public void cancelWps(android.net.wifi.WifiManager.ActionListener);
+    method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
     method public static int compareSignalLevel(int, int);
     method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(java.lang.String);
     method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, java.lang.String);
@@ -18111,13 +18141,18 @@
     method public boolean disableNetwork(int);
     method public boolean disconnect();
     method public boolean enableNetwork(int, boolean);
-    method public java.util.List<android.net.wifi.WifiAdapter> getAdapters();
     method public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
     method public android.net.wifi.WifiInfo getConnectionInfo();
     method public android.net.DhcpInfo getDhcpInfo();
     method public java.util.List<android.net.wifi.ScanResult> getScanResults();
     method public int getWifiState();
+    method public boolean is5GHzBandSupported();
+    method public boolean isDeviceToApRttSupported();
+    method public boolean isEnhancedPowerReportingSupported();
+    method public boolean isP2pSupported();
+    method public boolean isPreferredNetworkOffloadSupported();
     method public boolean isScanAlwaysAvailable();
+    method public boolean isTdlsSupported();
     method public boolean isWifiEnabled();
     method public boolean pingSupplicant();
     method public boolean reassociate();
@@ -18128,12 +18163,10 @@
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
     method public boolean setWifiEnabled(boolean);
     method public boolean startScan();
-    method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsListener);
+    method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
     method public int updateNetwork(android.net.wifi.WifiConfiguration);
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
-    field public static final int BUSY = 2; // 0x2
-    field public static final int ERROR = 0; // 0x0
     field public static final int ERROR_AUTHENTICATING = 1; // 0x1
     field public static final java.lang.String EXTRA_BSSID = "bssid";
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
@@ -18144,8 +18177,6 @@
     field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
     field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
     field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
-    field public static final int INVALID_ARGS = 8; // 0x8
-    field public static final int IN_PROGRESS = 1; // 0x1
     field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
     field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
     field public static final java.lang.String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
@@ -18168,11 +18199,6 @@
     field public static final int WPS_WEP_PROHIBITED = 4; // 0x4
   }
 
-  public static abstract interface WifiManager.ActionListener {
-    method public abstract void onFailure(int);
-    method public abstract void onSuccess();
-  }
-
   public class WifiManager.MulticastLock {
     method public void acquire();
     method public boolean isHeld();
@@ -18188,10 +18214,11 @@
     method public void setWorkSource(android.os.WorkSource);
   }
 
-  public static abstract interface WifiManager.WpsListener {
-    method public abstract void onCompletion();
-    method public abstract void onFailure(int);
-    method public abstract void onStartSuccess(java.lang.String);
+  public static abstract class WifiManager.WpsCallback {
+    ctor public WifiManager.WpsCallback();
+    method public abstract void onFailed(int);
+    method public abstract void onStarted(java.lang.String);
+    method public abstract void onSucceeded();
   }
 
   public class WpsInfo implements android.os.Parcelable {
@@ -21542,7 +21569,7 @@
     field public static final int JELLY_BEAN_MR2 = 18; // 0x12
     field public static final int KITKAT = 19; // 0x13
     field public static final int KITKAT_WATCH = 20; // 0x14
-    field public static final int L = 10000; // 0x2710
+    field public static final int L = 21; // 0x15
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -22443,9 +22470,6 @@
 
   public class UserManager {
     method public android.os.Bundle getApplicationRestrictions(java.lang.String);
-    method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
-    method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
-    method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
     method public long getSerialNumberForUser(android.os.UserHandle);
     method public int getUserCount();
     method public android.os.UserHandle getUserForSerialNumber(long);
@@ -23673,7 +23697,7 @@
     field public static final java.lang.String DATE = "date";
     field public static final java.lang.String DEFAULT_SORT_ORDER = "date DESC";
     field public static final java.lang.String DURATION = "duration";
-    field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.call_type_filter";
+    field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
     field public static final java.lang.String FEATURES = "features";
     field public static final int FEATURES_NONE = 0; // 0x0
     field public static final int FEATURES_VIDEO = 1; // 0x1
@@ -24037,11 +24061,11 @@
 
   public static final class ContactsContract.CommonDataKinds.Callable implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
     ctor public ContactsContract.CommonDataKinds.Callable();
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final android.net.Uri CONTENT_FILTER_URI;
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
   }
 
   protected static abstract interface ContactsContract.CommonDataKinds.CommonColumns implements android.provider.ContactsContract.CommonDataKinds.BaseTypes {
@@ -24052,11 +24076,11 @@
 
   public static final class ContactsContract.CommonDataKinds.Contactables implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
     ctor public ContactsContract.CommonDataKinds.Contactables();
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final android.net.Uri CONTENT_FILTER_URI;
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String VISIBLE_CONTACTS_ONLY = "visible_contacts_only";
   }
 
@@ -24064,15 +24088,15 @@
     method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
     method public static final int getTypeLabelResource(int);
     field public static final java.lang.String ADDRESS = "data1";
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final android.net.Uri CONTENT_FILTER_URI;
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2";
     field public static final android.net.Uri CONTENT_LOOKUP_URI;
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/email_v2";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DISPLAY_NAME = "data4";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final int TYPE_HOME = 1; // 0x1
     field public static final int TYPE_MOBILE = 4; // 0x4
     field public static final int TYPE_OTHER = 3; // 0x3
@@ -24082,10 +24106,10 @@
   public static final class ContactsContract.CommonDataKinds.Event implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
     method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
     method public static int getTypeResource(java.lang.Integer);
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String START_DATE = "data1";
     field public static final int TYPE_ANNIVERSARY = 1; // 0x1
     field public static final int TYPE_BIRTHDAY = 3; // 0x3
@@ -24093,19 +24117,19 @@
   }
 
   public static final class ContactsContract.CommonDataKinds.GroupMembership implements android.provider.ContactsContract.DataColumnsWithJoins {
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group_membership";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String GROUP_ROW_ID = "data1";
     field public static final java.lang.String GROUP_SOURCE_ID = "group_sourceid";
   }
 
   public static final class ContactsContract.CommonDataKinds.Identity implements android.provider.ContactsContract.DataColumnsWithJoins {
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/identity";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String IDENTITY = "data1";
     field public static final java.lang.String NAMESPACE = "data2";
   }
@@ -24115,11 +24139,11 @@
     method public static final int getProtocolLabelResource(int);
     method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
     method public static final int getTypeLabelResource(int);
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im";
     field public static final java.lang.String CUSTOM_PROTOCOL = "data6";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String PROTOCOL = "data5";
     field public static final int PROTOCOL_AIM = 0; // 0x0
     field public static final int PROTOCOL_CUSTOM = -1; // 0xffffffff
@@ -24137,10 +24161,10 @@
   }
 
   public static final class ContactsContract.CommonDataKinds.Nickname implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String NAME = "data1";
     field public static final int TYPE_DEFAULT = 1; // 0x1
     field public static final int TYPE_INITIALS = 5; // 0x5
@@ -24151,22 +24175,22 @@
   }
 
   public static final class ContactsContract.CommonDataKinds.Note implements android.provider.ContactsContract.DataColumnsWithJoins {
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String NOTE = "data1";
   }
 
   public static final class ContactsContract.CommonDataKinds.Organization implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
     method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
     method public static final int getTypeLabelResource(int);
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String COMPANY = "data1";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization";
     field public static final java.lang.String DEPARTMENT = "data5";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String JOB_DESCRIPTION = "data6";
     field public static final java.lang.String OFFICE_LOCATION = "data9";
     field public static final java.lang.String PHONETIC_NAME = "data8";
@@ -24179,13 +24203,13 @@
   public static final class ContactsContract.CommonDataKinds.Phone implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
     method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
     method public static final int getTypeLabelResource(int);
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final android.net.Uri CONTENT_FILTER_URI;
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String NORMALIZED_NUMBER = "data4";
     field public static final java.lang.String NUMBER = "data1";
     field public static final java.lang.String SEARCH_DISPLAY_NAME_KEY = "search_display_name";
@@ -24213,10 +24237,10 @@
   }
 
   public static final class ContactsContract.CommonDataKinds.Photo implements android.provider.ContactsContract.DataColumnsWithJoins {
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String PHOTO = "data15";
     field public static final java.lang.String PHOTO_FILE_ID = "data14";
   }
@@ -24224,10 +24248,10 @@
   public static final class ContactsContract.CommonDataKinds.Relation implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
     method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
     method public static final int getTypeLabelResource(int);
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String NAME = "data1";
     field public static final int TYPE_ASSISTANT = 1; // 0x1
     field public static final int TYPE_BROTHER = 2; // 0x2
@@ -24248,10 +24272,10 @@
   public static final class ContactsContract.CommonDataKinds.SipAddress implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
     method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
     method public static final int getTypeLabelResource(int);
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sip_address";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String SIP_ADDRESS = "data1";
     field public static final int TYPE_HOME = 1; // 0x1
     field public static final int TYPE_OTHER = 3; // 0x3
@@ -24259,11 +24283,11 @@
   }
 
   public static final class ContactsContract.CommonDataKinds.StructuredName implements android.provider.ContactsContract.DataColumnsWithJoins {
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name";
     field public static final java.lang.String DISPLAY_NAME = "data1";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String FAMILY_NAME = "data3";
     field public static final java.lang.String FULL_NAME_STYLE = "data10";
     field public static final java.lang.String GIVEN_NAME = "data2";
@@ -24278,14 +24302,14 @@
   public static final class ContactsContract.CommonDataKinds.StructuredPostal implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
     method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
     method public static final int getTypeLabelResource(int);
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CITY = "data7";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/postal-address_v2";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String COUNTRY = "data10";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String FORMATTED_ADDRESS = "data1";
     field public static final java.lang.String NEIGHBORHOOD = "data6";
     field public static final java.lang.String POBOX = "data5";
@@ -24298,10 +24322,10 @@
   }
 
   public static final class ContactsContract.CommonDataKinds.Website implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final int TYPE_BLOG = 2; // 0x2
     field public static final int TYPE_FTP = 6; // 0x6
     field public static final int TYPE_HOME = 4; // 0x4
@@ -24349,7 +24373,6 @@
     method public static deprecated void markAsContacted(android.content.ContentResolver, long);
     method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri, boolean);
     method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri);
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final android.net.Uri CONTENT_FILTER_URI;
     field public static final android.net.Uri CONTENT_FREQUENT_URI;
     field public static final android.net.Uri CONTENT_GROUP_URI;
@@ -24362,8 +24385,9 @@
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String CONTENT_VCARD_TYPE = "text/x-vcard";
     field public static final android.net.Uri CONTENT_VCARD_URI;
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
   }
 
   public static final class ContactsContract.Contacts.AggregationSuggestions implements android.provider.BaseColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns {
@@ -24408,11 +24432,11 @@
 
   public static final class ContactsContract.Data implements android.provider.ContactsContract.DataColumnsWithJoins {
     method public static android.net.Uri getContactLookupUri(android.content.ContentResolver, android.net.Uri);
-    field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/data";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
-    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+    field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
     field public static final java.lang.String VISIBLE_CONTACTS_ONLY = "visible_contacts_only";
   }
 
@@ -24656,7 +24680,7 @@
     ctor public ContactsContract.QuickContact();
     method public static void showQuickContact(android.content.Context, android.view.View, android.net.Uri, int, java.lang.String[]);
     method public static void showQuickContact(android.content.Context, android.graphics.Rect, android.net.Uri, int, java.lang.String[]);
-    field public static final java.lang.String ACTION_QUICK_CONTACT = "com.android.contacts.action.QUICK_CONTACT";
+    field public static final java.lang.String ACTION_QUICK_CONTACT = "android.provider.action.QUICK_CONTACT";
     field public static final java.lang.String EXTRA_EXCLUDE_MIMES = "android.provider.extra.EXCLUDE_MIMES";
     field public static final int MODE_LARGE = 3; // 0x3
     field public static final int MODE_MEDIUM = 2; // 0x2
@@ -27164,9 +27188,9 @@
 package android.service.voice {
 
   public class AlwaysOnHotwordDetector {
-    method public android.content.Intent createIntentToEnroll();
-    method public android.content.Intent createIntentToReEnroll();
-    method public android.content.Intent createIntentToUnEnroll();
+    method public android.content.Intent createEnrollIntent();
+    method public android.content.Intent createReEnrollIntent();
+    method public android.content.Intent createUnEnrollIntent();
     method public int getSupportedRecognitionModes();
     method public boolean startRecognition(int);
     method public boolean stopRecognition();
@@ -28271,7 +28295,6 @@
     method public final void setRequestingRingback(boolean);
     method public final void setRinging();
     method public final void setStatusHints(android.telecomm.StatusHints);
-    method public final void startActivityFromInCall(android.app.PendingIntent);
     method public static java.lang.String stateToString(int);
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_DIALING = 3; // 0x3
@@ -28302,8 +28325,6 @@
     method public final java.util.Collection<android.telecomm.Connection> getAllConnections();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConference(android.telecomm.Connection, android.telecomm.Connection);
-    method public void onConnectionAdded(android.telecomm.Connection);
-    method public void onConnectionRemoved(android.telecomm.Connection);
     method public android.telecomm.Connection onCreateIncomingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
     method public android.telecomm.Connection onCreateOutgoingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
     method public void onRemoteConferenceAdded(android.telecomm.RemoteConference);
@@ -28331,10 +28352,15 @@
     method public java.lang.CharSequence getLabel();
     method public java.lang.CharSequence getShortDescription();
     method public java.lang.String getSubscriptionNumber();
+    method public java.util.List<java.lang.String> getSupportedUriSchemes();
+    method public boolean supportsUriScheme(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final java.lang.String SCHEME_SIP = "sip";
+    field public static final java.lang.String SCHEME_TEL = "tel";
+    field public static final java.lang.String SCHEME_VOICEMAIL = "voicemail";
   }
 
   public static class PhoneAccount.Builder {
@@ -28347,6 +28373,8 @@
     method public android.telecomm.PhoneAccount.Builder withLabel(java.lang.CharSequence);
     method public android.telecomm.PhoneAccount.Builder withShortDescription(java.lang.CharSequence);
     method public android.telecomm.PhoneAccount.Builder withSubscriptionNumber(java.lang.String);
+    method public android.telecomm.PhoneAccount.Builder withSupportedUriScheme(java.lang.String);
+    method public android.telecomm.PhoneAccount.Builder withSupportedUriSchemes(java.util.List<java.lang.String>);
   }
 
   public class PhoneAccountHandle implements android.os.Parcelable {
@@ -28449,7 +28477,6 @@
     method public void onParentChanged(android.telecomm.RemoteConnection, android.telecomm.RemoteConnection);
     method public void onPostDialWait(android.telecomm.RemoteConnection, java.lang.String);
     method public void onRequestingRingback(android.telecomm.RemoteConnection, boolean);
-    method public void onStartActivityFromInCall(android.telecomm.RemoteConnection, android.app.PendingIntent);
     method public void onStateChanged(android.telecomm.RemoteConnection, int);
     method public void onStatusHintsChanged(android.telecomm.RemoteConnection, android.telecomm.StatusHints);
   }
@@ -28475,15 +28502,18 @@
     method public void addNewIncomingCall(android.telecomm.PhoneAccountHandle, android.os.Bundle);
     method public void cancelMissedCallsNotification();
     method public void clearAccounts(java.lang.String);
-    method public android.telecomm.PhoneAccountHandle getDefaultOutgoingPhoneAccount();
+    method public android.telecomm.PhoneAccountHandle getConnectionManager();
+    method public android.telecomm.PhoneAccountHandle getDefaultOutgoingPhoneAccount(java.lang.String);
     method public java.util.List<android.telecomm.PhoneAccountHandle> getEnabledPhoneAccounts();
     method public android.telecomm.PhoneAccount getPhoneAccount(android.telecomm.PhoneAccountHandle);
+    method public java.util.List<android.telecomm.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
     method public boolean handleMmi(java.lang.String);
     method public boolean hasMultipleEnabledAccounts();
     method public boolean isInCall();
     method public void registerPhoneAccount(android.telecomm.PhoneAccount);
     method public void showInCallScreen(boolean);
     method public void unregisterPhoneAccount(android.telecomm.PhoneAccountHandle);
+    field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecomm.intent.action.CHANGE_PHONE_ACCOUNTS";
     field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.intent.action.CONNECTION_SERVICE_CONFIGURE";
     field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecomm.intent.action.SHOW_CALL_SETTINGS";
     field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
@@ -28704,49 +28734,11 @@
     method public int getStatus();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
-    field public static int INVALID_CHANNEL;
-    field public static int STATUS_MISSING_RESOURCE;
-    field public static int STATUS_NO_ERROR;
-    field public static int STATUS_NO_SUCH_ELEMENT;
-    field public static int STATUS_UNKNOWN_ERROR;
-  }
-
-  public class MessagingConfigurationManager {
-    method public boolean getCarrierConfigBoolean(java.lang.String, boolean);
-    method public boolean getCarrierConfigBoolean(long, java.lang.String, boolean);
-    method public int getCarrierConfigInt(java.lang.String, int);
-    method public int getCarrierConfigInt(long, java.lang.String, int);
-    method public java.lang.String getCarrierConfigString(java.lang.String, java.lang.String);
-    method public java.lang.String getCarrierConfigString(long, java.lang.String, java.lang.String);
-    method public static android.telephony.MessagingConfigurationManager getDefault();
-    field public static final java.lang.String CONF_ALIAS_ENABLED = "aliasEnabled";
-    field public static final java.lang.String CONF_ALIAS_MAX_CHARS = "aliasMaxChars";
-    field public static final java.lang.String CONF_ALIAS_MIN_CHARS = "aliasMinChars";
-    field public static final java.lang.String CONF_ALLOW_ATTACH_AUDIO = "allowAttachAudio";
-    field public static final java.lang.String CONF_APPEND_TRANSACTION_ID = "enabledTransID";
-    field public static final java.lang.String CONF_EMAIL_GATEWAY_NUMBER = "emailGatewayNumber";
-    field public static final java.lang.String CONF_HTTP_PARAMS = "httpParams";
-    field public static final java.lang.String CONF_HTTP_SOCKET_TIMEOUT = "httpSocketTimeout";
-    field public static final java.lang.String CONF_MAX_IMAGE_HEIGHT = "maxImageHeight";
-    field public static final java.lang.String CONF_MAX_IMAGE_WIDTH = "maxImageWidth";
-    field public static final java.lang.String CONF_MAX_MESSAGE_SIZE = "maxMessageSize";
-    field public static final java.lang.String CONF_MESSAGE_TEXT_MAX_SIZE = "maxMessageTextSize";
-    field public static final java.lang.String CONF_MMS_DELIVERY_REPORT_ENABLED = "enableMMSDeliveryReports";
-    field public static final java.lang.String CONF_MMS_ENABLED = "enabledMMS";
-    field public static final java.lang.String CONF_MMS_READ_REPORT_ENABLED = "enableMMSReadReports";
-    field public static final java.lang.String CONF_MULTIPART_SMS_ENABLED = "enableMultipartSMS";
-    field public static final java.lang.String CONF_NAI_SUFFIX = "naiSuffix";
-    field public static final java.lang.String CONF_NOTIFY_WAP_MMSC_ENABLED = "enabledNotifyWapMMSC";
-    field public static final java.lang.String CONF_RECIPIENT_LIMIT = "recipientLimit";
-    field public static final java.lang.String CONF_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES = "sendMultipartSmsAsSeparateMessages";
-    field public static final java.lang.String CONF_SMS_DELIVERY_REPORT_ENABLED = "enableSMSDeliveryReports";
-    field public static final java.lang.String CONF_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD = "smsToMmsTextLengthThreshold";
-    field public static final java.lang.String CONF_SMS_TO_MMS_TEXT_THRESHOLD = "smsToMmsTextThreshold";
-    field public static final java.lang.String CONF_SUBJECT_MAX_LENGTH = "maxSubjectLength";
-    field public static final java.lang.String CONF_SUPPORT_MMS_CONTENT_DISPOSITION = "supportMmsContentDisposition";
-    field public static final java.lang.String CONF_UA_PROF_TAG_NAME = "uaProfTagName";
-    field public static final java.lang.String CONF_UA_PROF_URL = "uaProfUrl";
-    field public static final java.lang.String CONF_USER_AGENT = "userAgent";
+    field public static final int INVALID_CHANNEL = -1; // 0xffffffff
+    field public static final int STATUS_MISSING_RESOURCE = 2; // 0x2
+    field public static final int STATUS_NO_ERROR = 1; // 0x1
+    field public static final int STATUS_NO_SUCH_ELEMENT = 3; // 0x3
+    field public static final int STATUS_UNKNOWN_ERROR = 4; // 0x4
   }
 
   public class NeighboringCellInfo implements android.os.Parcelable {
@@ -28891,48 +28883,59 @@
   }
 
   public final class SmsManager {
-    method public android.net.Uri addMultimediaMessageDraft(byte[]);
-    method public android.net.Uri addTextMessageDraft(java.lang.String, java.lang.String);
-    method public boolean archiveStoredConversation(long, boolean);
-    method public boolean deleteStoredConversation(long);
-    method public boolean deleteStoredMessage(android.net.Uri);
     method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
-    method public void downloadMultimediaMessage(java.lang.String, android.content.ContentValues, android.app.PendingIntent);
-    method public void downloadMultimediaMessage(long, java.lang.String, android.content.ContentValues, android.app.PendingIntent);
-    method public boolean getAutoPersisting();
+    method public void downloadMultimediaMessage(java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
+    method public android.os.Bundle getCarrierConfigValues();
     method public static android.telephony.SmsManager getDefault();
-    method public android.net.Uri importMultimediaMessage(byte[], java.lang.String, long, boolean, boolean);
-    method public android.net.Uri importTextMessage(java.lang.String, int, java.lang.String, long, boolean, boolean);
+    method public static android.telephony.SmsManager getSmsManagerUsingSubId(long);
+    method public long getSubId();
     method public void injectSmsPdu(byte[], java.lang.String, android.app.PendingIntent);
     method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
-    method public void sendMultimediaMessage(byte[], java.lang.String, android.content.ContentValues, android.app.PendingIntent);
-    method public void sendMultimediaMessage(long, byte[], java.lang.String, android.content.ContentValues, android.app.PendingIntent);
+    method public void sendMultimediaMessage(android.net.Uri, java.lang.String, android.os.Bundle, android.app.PendingIntent);
     method public void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
-    method public void sendStoredMultimediaMessage(android.net.Uri, android.content.ContentValues, android.app.PendingIntent);
-    method public void sendStoredMultimediaMessage(long, android.net.Uri, android.content.ContentValues, android.app.PendingIntent);
-    method public void sendStoredMultipartTextMessage(android.net.Uri, java.lang.String, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
-    method public void sendStoredMultipartTextMessage(long, android.net.Uri, java.lang.String, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
-    method public void sendStoredTextMessage(android.net.Uri, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
-    method public void sendStoredTextMessage(long, android.net.Uri, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
     method public void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
-    method public void setAutoPersisting(boolean);
     method public void updateMmsDownloadStatus(int, byte[]);
     method public void updateMmsSendStatus(int, boolean);
     method public void updateSmsSendStatus(int, boolean);
-    method public boolean updateStoredMessageStatus(android.net.Uri, android.content.ContentValues);
-    field public static final java.lang.String MESSAGE_STATUS_READ = "read";
-    field public static final java.lang.String MESSAGE_STATUS_SEEN = "seen";
+    field public static final java.lang.String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA";
+    field public static final java.lang.String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled";
+    field public static final java.lang.String MMS_CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars";
+    field public static final java.lang.String MMS_CONFIG_ALIAS_MIN_CHARS = "aliasMinChars";
+    field public static final java.lang.String MMS_CONFIG_ALLOW_ATTACH_AUDIO = "allowAttachAudio";
+    field public static final java.lang.String MMS_CONFIG_APPEND_TRANSACTION_ID = "enabledTransID";
+    field public static final java.lang.String MMS_CONFIG_EMAIL_GATEWAY_NUMBER = "emailGatewayNumber";
+    field public static final java.lang.String MMS_CONFIG_GROUP_MMS_ENABLED = "enableGroupMms";
+    field public static final java.lang.String MMS_CONFIG_HTTP_PARAMS = "httpParams";
+    field public static final java.lang.String MMS_CONFIG_HTTP_SOCKET_TIMEOUT = "httpSocketTimeout";
+    field public static final java.lang.String MMS_CONFIG_MAX_IMAGE_HEIGHT = "maxImageHeight";
+    field public static final java.lang.String MMS_CONFIG_MAX_IMAGE_WIDTH = "maxImageWidth";
+    field public static final java.lang.String MMS_CONFIG_MAX_MESSAGE_SIZE = "maxMessageSize";
+    field public static final java.lang.String MMS_CONFIG_MESSAGE_TEXT_MAX_SIZE = "maxMessageTextSize";
+    field public static final java.lang.String MMS_CONFIG_MMS_DELIVERY_REPORT_ENABLED = "enableMMSDeliveryReports";
+    field public static final java.lang.String MMS_CONFIG_MMS_ENABLED = "enabledMMS";
+    field public static final java.lang.String MMS_CONFIG_MMS_READ_REPORT_ENABLED = "enableMMSReadReports";
+    field public static final java.lang.String MMS_CONFIG_MULTIPART_SMS_ENABLED = "enableMultipartSMS";
+    field public static final java.lang.String MMS_CONFIG_NAI_SUFFIX = "naiSuffix";
+    field public static final java.lang.String MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED = "enabledNotifyWapMMSC";
+    field public static final java.lang.String MMS_CONFIG_RECIPIENT_LIMIT = "recipientLimit";
+    field public static final java.lang.String MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES = "sendMultipartSmsAsSeparateMessages";
+    field public static final java.lang.String MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED = "enableSMSDeliveryReports";
+    field public static final java.lang.String MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD = "smsToMmsTextLengthThreshold";
+    field public static final java.lang.String MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD = "smsToMmsTextThreshold";
+    field public static final java.lang.String MMS_CONFIG_SUBJECT_MAX_LENGTH = "maxSubjectLength";
+    field public static final java.lang.String MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION = "supportMmsContentDisposition";
+    field public static final java.lang.String MMS_CONFIG_UA_PROF_TAG_NAME = "uaProfTagName";
+    field public static final java.lang.String MMS_CONFIG_UA_PROF_URL = "uaProfUrl";
+    field public static final java.lang.String MMS_CONFIG_USER_AGENT = "userAgent";
     field public static final int MMS_ERROR_HTTP_FAILURE = 4; // 0x4
     field public static final int MMS_ERROR_INVALID_APN = 2; // 0x2
+    field public static final int MMS_ERROR_IO_ERROR = 5; // 0x5
     field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3
     field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1
-    field public static final java.lang.String MMS_EXTRA_DATA = "data";
     field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1
     field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4
     field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3
     field public static final int RESULT_ERROR_RADIO_OFF = 2; // 0x2
-    field public static final int SMS_TYPE_INCOMING = 0; // 0x0
-    field public static final int SMS_TYPE_OUTGOING = 1; // 0x1
     field public static final int STATUS_ON_ICC_FREE = 0; // 0x0
     field public static final int STATUS_ON_ICC_READ = 1; // 0x1
     field public static final int STATUS_ON_ICC_SENT = 5; // 0x5
@@ -29740,6 +29743,9 @@
     method public android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
     method public java.lang.String[] getSystemSharedLibraryNames();
     method public java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
+    method public android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
+    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 boolean hasSystemFeature(java.lang.String);
     method public boolean isSafeMode();
@@ -31503,13 +31509,13 @@
     method public abstract android.graphics.Path getPath(float, float, float, float);
   }
 
-  public class PatternMotion extends android.transition.PathMotion {
-    ctor public PatternMotion();
-    ctor public PatternMotion(android.content.Context, android.util.AttributeSet);
-    ctor public PatternMotion(android.graphics.Path);
+  public class PatternPathMotion extends android.transition.PathMotion {
+    ctor public PatternPathMotion();
+    ctor public PatternPathMotion(android.content.Context, android.util.AttributeSet);
+    ctor public PatternPathMotion(android.graphics.Path);
     method public android.graphics.Path getPath(float, float, float, float);
-    method public android.graphics.Path getPattern();
-    method public void setPattern(android.graphics.Path);
+    method public android.graphics.Path getPatternPath();
+    method public void setPatternPath(android.graphics.Path);
   }
 
   public final class Scene {
@@ -32503,8 +32509,6 @@
     method public final long getRefreshPeriodNano();
     method public final long getStartTimeNano();
     field public static final long UNDEFINED_TIME_NANO = -1L; // 0xffffffffffffffffL
-    field protected long[] mFramesPresentedTimeNano;
-    field protected long mRefreshPeriodNano;
   }
 
   public class GestureDetector {
@@ -32926,6 +32930,7 @@
     field public static final int KEYCODE_GUIDE = 172; // 0xac
     field public static final int KEYCODE_H = 36; // 0x24
     field public static final int KEYCODE_HEADSETHOOK = 79; // 0x4f
+    field public static final int KEYCODE_HELP = 259; // 0x103
     field public static final int KEYCODE_HENKAN = 214; // 0xd6
     field public static final int KEYCODE_HOME = 3; // 0x3
     field public static final int KEYCODE_I = 37; // 0x25
@@ -33026,9 +33031,36 @@
     field public static final int KEYCODE_T = 48; // 0x30
     field public static final int KEYCODE_TAB = 61; // 0x3d
     field public static final int KEYCODE_TV = 170; // 0xaa
+    field public static final int KEYCODE_TV_ANTENNA_CABLE = 242; // 0xf2
+    field public static final int KEYCODE_TV_AUDIO_DESCRIPTION = 252; // 0xfc
+    field public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254; // 0xfe
+    field public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253; // 0xfd
+    field public static final int KEYCODE_TV_CONTENTS_MENU = 256; // 0x100
     field public static final int KEYCODE_TV_DATA_SERVICE = 230; // 0xe6
     field public static final int KEYCODE_TV_INPUT = 178; // 0xb2
+    field public static final int KEYCODE_TV_INPUT_COMPONENT_1 = 249; // 0xf9
+    field public static final int KEYCODE_TV_INPUT_COMPONENT_2 = 250; // 0xfa
+    field public static final int KEYCODE_TV_INPUT_COMPOSITE_1 = 247; // 0xf7
+    field public static final int KEYCODE_TV_INPUT_COMPOSITE_2 = 248; // 0xf8
+    field public static final int KEYCODE_TV_INPUT_HDMI_1 = 243; // 0xf3
+    field public static final int KEYCODE_TV_INPUT_HDMI_2 = 244; // 0xf4
+    field public static final int KEYCODE_TV_INPUT_HDMI_3 = 245; // 0xf5
+    field public static final int KEYCODE_TV_INPUT_HDMI_4 = 246; // 0xf6
+    field public static final int KEYCODE_TV_INPUT_VGA_1 = 251; // 0xfb
+    field public static final int KEYCODE_TV_MEDIA_CONTEXT_MENU = 257; // 0x101
+    field public static final int KEYCODE_TV_NETWORK = 241; // 0xf1
+    field public static final int KEYCODE_TV_NUMBER_ENTRY = 234; // 0xea
     field public static final int KEYCODE_TV_POWER = 177; // 0xb1
+    field public static final int KEYCODE_TV_RADIO_SERVICE = 232; // 0xe8
+    field public static final int KEYCODE_TV_SATELLITE = 237; // 0xed
+    field public static final int KEYCODE_TV_SATELLITE_BS = 238; // 0xee
+    field public static final int KEYCODE_TV_SATELLITE_CS = 239; // 0xef
+    field public static final int KEYCODE_TV_SATELLITE_SERVICE = 240; // 0xf0
+    field public static final int KEYCODE_TV_TELETEXT = 233; // 0xe9
+    field public static final int KEYCODE_TV_TERRESTRIAL_ANALOG = 235; // 0xeb
+    field public static final int KEYCODE_TV_TERRESTRIAL_DIGITAL = 236; // 0xec
+    field public static final int KEYCODE_TV_TIMER_PROGRAMMING = 258; // 0x102
+    field public static final int KEYCODE_TV_ZOOM_MODE = 255; // 0xff
     field public static final int KEYCODE_U = 49; // 0x31
     field public static final int KEYCODE_UNKNOWN = 0; // 0x0
     field public static final int KEYCODE_V = 50; // 0x32
@@ -34309,7 +34341,7 @@
   }
 
   public final class ViewAnimationUtils {
-    method public static final android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
+    method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
   }
 
   public class ViewConfiguration {
@@ -34768,7 +34800,7 @@
     method public abstract void closePanel(int);
     method public android.view.View findViewById(int);
     method public boolean getAllowEnterTransitionOverlap();
-    method public boolean getAllowExitTransitionOverlap();
+    method public boolean getAllowReturnTransitionOverlap();
     method public final android.view.WindowManager.LayoutParams getAttributes();
     method public final android.view.Window.Callback getCallback();
     method public final android.view.Window getContainer();
@@ -34817,7 +34849,7 @@
     method public abstract void restoreHierarchyState(android.os.Bundle);
     method public abstract android.os.Bundle saveHierarchyState();
     method public void setAllowEnterTransitionOverlap(boolean);
-    method public void setAllowExitTransitionOverlap(boolean);
+    method public void setAllowReturnTransitionOverlap(boolean);
     method public void setAttributes(android.view.WindowManager.LayoutParams);
     method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
     method public void setBackgroundDrawableResource(int);
@@ -35834,7 +35866,7 @@
     method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
     method public static final void removeComposingSpans(android.text.Spannable);
     method public boolean reportFullscreenMode(boolean);
-    method public boolean requestUpdateCursorAnchorInfo(int);
+    method public boolean requestCursorUpdates(int);
     method public boolean sendKeyEvent(android.view.KeyEvent);
     method public boolean setComposingRegion(int, int);
     method public static void setComposingSpans(android.text.Spannable);
@@ -35873,20 +35905,16 @@
     method public int getComposingTextStart();
     method public float getInsertionMarkerBaseline();
     method public float getInsertionMarkerBottom();
+    method public int getInsertionMarkerFlags();
     method public float getInsertionMarkerHorizontal();
     method public float getInsertionMarkerTop();
     method public android.graphics.Matrix getMatrix();
     method public int getSelectionEnd();
     method public int getSelectionStart();
-    method public boolean isInsertionMarkerClipped();
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; // 0x1
-    field public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; // 0x3
-    field public static final int CHARACTER_RECT_TYPE_MASK = 15; // 0xf
-    field public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4; // 0x4
-    field public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2; // 0x2
-    field public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0; // 0x0
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int FLAG_HAS_INVISIBLE_REGION = 2; // 0x2
+    field public static final int FLAG_HAS_VISIBLE_REGION = 1; // 0x1
   }
 
   public static final class CursorAnchorInfo.Builder {
@@ -35895,7 +35923,7 @@
     method public android.view.inputmethod.CursorAnchorInfo build();
     method public void reset();
     method public android.view.inputmethod.CursorAnchorInfo.Builder setComposingText(int, java.lang.CharSequence);
-    method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, boolean);
+    method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, int);
     method public android.view.inputmethod.CursorAnchorInfo.Builder setMatrix(android.graphics.Matrix);
     method public android.view.inputmethod.CursorAnchorInfo.Builder setSelectionRange(int, int);
   }
@@ -35997,15 +36025,15 @@
     method public abstract boolean performEditorAction(int);
     method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
     method public abstract boolean reportFullscreenMode(boolean);
-    method public abstract boolean requestUpdateCursorAnchorInfo(int);
+    method public abstract boolean requestCursorUpdates(int);
     method public abstract boolean sendKeyEvent(android.view.KeyEvent);
     method public abstract boolean setComposingRegion(int, int);
     method public abstract boolean setComposingText(java.lang.CharSequence, int);
     method public abstract boolean setSelection(int, int);
+    field public static final int CURSOR_UPDATE_IMMEDIATE = 1; // 0x1
+    field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2
     field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
     field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
-    field public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1; // 0x1
-    field public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 2; // 0x2
   }
 
   public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
@@ -36027,7 +36055,7 @@
     method public boolean performEditorAction(int);
     method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
     method public boolean reportFullscreenMode(boolean);
-    method public boolean requestUpdateCursorAnchorInfo(int);
+    method public boolean requestCursorUpdates(int);
     method public boolean sendKeyEvent(android.view.KeyEvent);
     method public boolean setComposingRegion(int, int);
     method public boolean setComposingText(java.lang.CharSequence, int);
@@ -36519,6 +36547,7 @@
     method public abstract java.lang.String getMethod();
     method public abstract java.util.Map<java.lang.String, java.lang.String> getRequestHeaders();
     method public abstract android.net.Uri getUrl();
+    method public abstract boolean hasGesture();
     method public abstract boolean hasUserGestureInsecure();
     method public abstract boolean isForMainFrame();
   }
@@ -36776,7 +36805,6 @@
     method public deprecated void onGlobalFocusChanged(android.view.View, android.view.View);
     method public void onPause();
     method public void onResume();
-    method public static void optOutDataReductionProxy();
     method public boolean overlayHorizontalScrollbar();
     method public boolean overlayVerticalScrollbar();
     method public boolean pageDown(boolean);
@@ -36808,7 +36836,7 @@
     method public void setWebViewClient(android.webkit.WebViewClient);
     method public deprecated boolean showFindDialog(java.lang.String, boolean);
     method public void stopLoading();
-    method public boolean zoomBy(float);
+    method public void zoomBy(float);
     method public boolean zoomIn();
     method public boolean zoomOut();
     field public static final java.lang.String SCHEME_GEO = "geo:0,0?q=";
diff --git a/api/removed.txt b/api/removed.txt
index 8915fc3..0aa6d54 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -30,6 +30,12 @@
     method public void wakeUp(long);
   }
 
+  public class UserManager {
+    method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
+    method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
+    method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
+  }
+
 }
 
 package android.service.notification {
@@ -48,6 +54,38 @@
 
 }
 
+package android.view.inputmethod {
+
+  public class BaseInputConnection implements android.view.inputmethod.InputConnection {
+    method public final boolean requestUpdateCursorAnchorInfo(int);
+  }
+
+  public final class CursorAnchorInfo implements android.os.Parcelable {
+    method public boolean isInsertionMarkerClipped();
+    field public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; // 0x1
+    field public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; // 0x3
+    field public static final int CHARACTER_RECT_TYPE_MASK = 15; // 0xf
+    field public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4; // 0x4
+    field public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2; // 0x2
+    field public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0; // 0x0
+  }
+
+  public static final class CursorAnchorInfo.Builder {
+    method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, boolean);
+  }
+
+  public abstract interface InputConnection {
+    method public abstract boolean requestUpdateCursorAnchorInfo(int);
+    field public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 2; // 0x2
+    field public static final int REQUEST_UPDATE_CURSOR_UPDATE_IMMEDIATE = 1; // 0x1
+  }
+
+  public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
+    method public final boolean requestUpdateCursorAnchorInfo(int);
+  }
+
+}
+
 package com.android.internal {
 
   public static final class R.attr {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8ab344e..89a9692 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -788,8 +788,8 @@
     final Handler mHandler = new Handler();
 
     ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
-    SharedElementListener mEnterTransitionListener = SharedElementListener.NULL_LISTENER;
-    SharedElementListener mExitTransitionListener = SharedElementListener.NULL_LISTENER;
+    SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
+    SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK;
 
     /** Return the intent that started this activity. */
     public Intent getIntent() {
@@ -955,7 +955,7 @@
      * @see #onRestoreInstanceState
      * @see #onPostCreate
      */
-    protected void onCreate(@Nullable Bundle savedInstanceState,
+    public void onCreate(@Nullable Bundle savedInstanceState,
             @Nullable PersistableBundle persistentState) {
         onCreate(savedInstanceState);
     }
@@ -1040,7 +1040,7 @@
      * @see #onResume
      * @see #onSaveInstanceState
      */
-    protected void onRestoreInstanceState(Bundle savedInstanceState,
+    public void onRestoreInstanceState(Bundle savedInstanceState,
             PersistableBundle persistentState) {
         if (savedInstanceState != null) {
             onRestoreInstanceState(savedInstanceState);
@@ -1130,7 +1130,7 @@
      *
      * @see #onCreate
      */
-    protected void onPostCreate(@Nullable Bundle savedInstanceState,
+    public void onPostCreate(@Nullable Bundle savedInstanceState,
             @Nullable PersistableBundle persistentState) {
         onPostCreate(savedInstanceState);
     }
@@ -1380,7 +1380,7 @@
      * @see #onRestoreInstanceState(Bundle, PersistableBundle)
      * @see #onPause
      */
-    protected void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
+    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
         onSaveInstanceState(outState);
     }
 
@@ -4769,7 +4769,7 @@
      * @param data An Intent, which can return result data to the caller
      *               (various data can be attached to Intent "extras").
      */
-    protected void onActivityReenter(int resultCode, Intent data) {
+    public void onActivityReenter(int resultCode, Intent data) {
     }
 
     /**
@@ -5410,6 +5410,7 @@
             mTranslucentCallback = callback;
             mChangeCanvasToTranslucent =
                     ActivityManagerNative.getDefault().convertToTranslucent(mToken, options);
+            WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, false);
             drawComplete = true;
         } catch (RemoteException e) {
             // Make callback return as though it timed out.
@@ -5778,33 +5779,33 @@
 
     /**
      * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
-     * android.view.View, String)} was used to start an Activity, <var>listener</var>
+     * android.view.View, String)} was used to start an Activity, <var>callback</var>
      * will be called to handle shared elements on the <i>launched</i> Activity. This requires
      * {@link Window#FEATURE_CONTENT_TRANSITIONS}.
      *
-     * @param listener Used to manipulate shared element transitions on the launched Activity.
+     * @param callback Used to manipulate shared element transitions on the launched Activity.
      */
-    public void setEnterSharedElementListener(SharedElementListener listener) {
-        if (listener == null) {
-            listener = SharedElementListener.NULL_LISTENER;
+    public void setEnterSharedElementCallback(SharedElementCallback callback) {
+        if (callback == null) {
+            callback = SharedElementCallback.NULL_CALLBACK;
         }
-        mEnterTransitionListener = listener;
+        mEnterTransitionListener = callback;
     }
 
     /**
      * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
-     * android.view.View, String)} was used to start an Activity, <var>listener</var>
+     * android.view.View, String)} was used to start an Activity, <var>callback</var>
      * will be called to handle shared elements on the <i>launching</i> Activity. Most
      * calls will only come when returning from the started Activity.
      * This requires {@link Window#FEATURE_CONTENT_TRANSITIONS}.
      *
-     * @param listener Used to manipulate shared element transitions on the launching Activity.
+     * @param callback Used to manipulate shared element transitions on the launching Activity.
      */
-    public void setExitSharedElementListener(SharedElementListener listener) {
-        if (listener == null) {
-            listener = SharedElementListener.NULL_LISTENER;
+    public void setExitSharedElementCallback(SharedElementCallback callback) {
+        if (callback == null) {
+            callback = SharedElementCallback.NULL_CALLBACK;
         }
-        mExitTransitionListener = listener;
+        mExitTransitionListener = callback;
     }
 
     /**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index bc54055..3e03893 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -18,12 +18,14 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.os.BatteryStats;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+
 import com.android.internal.app.ProcessStats;
 import com.android.internal.os.TransferPipe;
 import com.android.internal.util.FastPrintWriter;
@@ -2464,7 +2466,11 @@
         }
     }
 
-    /** @hide */
+    /**
+     * Gets the userId of the current foreground user. Requires system permissions.
+     * @hide
+     */
+    @SystemApi
     public static int getCurrentUser() {
         UserInfo ui;
         try {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 38999a8..4f2a3bc 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1938,7 +1938,7 @@
         if (dumpFullInfo) {
             printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
                     "Shared", "Private", "Swapped", "Heap", "Heap", "Heap");
-            printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
+            printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "",
                     "Clean", "Clean", "Dirty", "Size", "Alloc", "Free");
             printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
                     "------", "------", "------", "------", "------", "------");
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index a09a2e7..9e80a4b 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -197,7 +197,7 @@
     final protected ArrayList<View> mSharedElements = new ArrayList<View>();
     final protected ArrayList<String> mSharedElementNames = new ArrayList<String>();
     final protected ArrayList<View> mTransitioningViews = new ArrayList<View>();
-    protected SharedElementListener mListener;
+    protected SharedElementCallback mListener;
     protected ResultReceiver mResultReceiver;
     final private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback();
     final protected boolean mIsReturning;
@@ -208,7 +208,7 @@
 
     public ActivityTransitionCoordinator(Window window,
             ArrayList<String> allSharedElementNames,
-            SharedElementListener listener, boolean isReturning) {
+            SharedElementCallback listener, boolean isReturning) {
         super(new Handler());
         mWindow = window;
         mListener = listener;
@@ -218,7 +218,7 @@
 
     protected void viewsReady(ArrayMap<String, View> sharedElements) {
         sharedElements.retainAll(mAllSharedElementNames);
-        mListener.remapSharedElements(mAllSharedElementNames, sharedElements);
+        mListener.onMapSharedElements(mAllSharedElementNames, sharedElements);
         mSharedElementNames.addAll(sharedElements.keySet());
         mSharedElements.addAll(sharedElements.values());
         if (getViewsTransition() != null) {
@@ -251,9 +251,11 @@
      */
     protected void setEpicenter() {
         View epicenter = null;
-        if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty() &&
-                mAllSharedElementNames.get(0).equals(mSharedElementNames.get(0))) {
-            epicenter = mSharedElements.get(0);
+        if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty()) {
+            int index = mSharedElementNames.indexOf(mAllSharedElementNames.get(0));
+            if (index >= 0) {
+                epicenter = mSharedElements.get(index);
+            }
         }
         setEpicenter(epicenter);
     }
@@ -458,20 +460,21 @@
                         tempMatrix, tempRect, null);
             }
         }
-        mListener.setSharedElementStart(mSharedElementNames, mSharedElements, snapshots);
+        mListener.onSharedElementStart(mSharedElementNames, mSharedElements, snapshots);
         return originalImageState;
     }
 
     protected void notifySharedElementEnd(ArrayList<View> snapshots) {
-        mListener.setSharedElementEnd(mSharedElementNames, mSharedElements, snapshots);
+        mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, snapshots);
     }
 
     protected void scheduleSetSharedElementEnd(final ArrayList<View> snapshots) {
-        getDecor().getViewTreeObserver().addOnPreDrawListener(
+        final View decorView = getDecor();
+        decorView.getViewTreeObserver().addOnPreDrawListener(
                 new ViewTreeObserver.OnPreDrawListener() {
                     @Override
                     public boolean onPreDraw() {
-                        getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+                        decorView.getViewTreeObserver().removeOnPreDrawListener(this);
                         notifySharedElementEnd(snapshots);
                         return true;
                     }
@@ -526,7 +529,7 @@
                 Parcelable parcelable = sharedElementBundle.getParcelable(KEY_SNAPSHOT);
                 View snapshot = null;
                 if (parcelable != null) {
-                    snapshot = mListener.createSnapshotView(context, parcelable);
+                    snapshot = mListener.onCreateSnapshotView(context, parcelable);
                 }
                 if (snapshot != null) {
                     setSharedElementState(snapshot, name, state, null, null, decorLoc);
@@ -618,7 +621,7 @@
         sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ());
         sharedElementBundle.putFloat(KEY_ELEVATION, view.getElevation());
 
-        Parcelable bitmap = mListener.captureSharedElementSnapshot(view, tempMatrix, tempBounds);
+        Parcelable bitmap = mListener.onCaptureSharedElementSnapshot(view, tempMatrix, tempBounds);
         if (bitmap != null) {
             sharedElementBundle.putParcelable(KEY_SNAPSHOT, bitmap);
         }
@@ -664,8 +667,7 @@
                 GhostView.addGhost(view, decor);
                 ViewGroup parent = (ViewGroup) view.getParent();
                 if (moveWithParent && !isInTransitionGroup(parent, decor)) {
-                    GhostViewListeners listener =
-                            new GhostViewListeners(view, decor);
+                    GhostViewListeners listener = new GhostViewListeners(view, parent, decor);
                     parent.getViewTreeObserver().addOnPreDrawListener(listener);
                     mGhostViewListeners.add(listener);
                 }
@@ -723,11 +725,12 @@
     }
 
     protected void scheduleGhostVisibilityChange(final int visibility) {
-        getDecor().getViewTreeObserver()
+        final View decorView = getDecor();
+        decorView.getViewTreeObserver()
                 .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                     @Override
                     public boolean onPreDraw() {
-                        getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+                        decorView.getViewTreeObserver().removeOnPreDrawListener(this);
                         setGhostVisibility(visibility);
                         return true;
                     }
@@ -769,10 +772,12 @@
     private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener {
         private View mView;
         private ViewGroup mDecor;
+        private View mParent;
         private Matrix mMatrix = new Matrix();
 
-        public GhostViewListeners(View view, ViewGroup decor) {
+        public GhostViewListeners(View view, View parent, ViewGroup decor) {
             mView = view;
+            mParent = parent;
             mDecor = decor;
         }
 
@@ -782,10 +787,9 @@
 
         @Override
         public boolean onPreDraw() {
-            ViewGroup parent = ((ViewGroup) mView.getParent());
             GhostView ghostView = GhostView.getGhost(mView);
             if (ghostView == null) {
-                parent.getViewTreeObserver().removeOnPreDrawListener(this);
+                mParent.getViewTreeObserver().removeOnPreDrawListener(this);
             } else {
                 GhostView.calculateMatrix(mView, mDecor, mMatrix);
                 ghostView.setMatrix(mMatrix);
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 613e248..ad4a22b 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -151,6 +151,7 @@
             mEnterActivityOptions = options;
             mIsEnterTriggered = false;
             if (mEnterActivityOptions.isReturning()) {
+                restoreExitedViews();
                 int result = mEnterActivityOptions.getResultCode();
                 if (result != 0) {
                     activity.onActivityReenter(result, mEnterActivityOptions.getResultData());
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index a64e0ed..2c596e5 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
@@ -385,6 +386,7 @@
     }
 
     /** @hide */
+    @SystemApi
     public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis,
             PendingIntent operation, WorkSource workSource) {
         setImpl(type, triggerAtMillis, windowMillis, intervalMillis, operation, workSource, null);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 66928ca..ba9c9d6 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -220,6 +220,9 @@
     /** Continually monitoring location data with a relatively high power request. */
     public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION
             = "android:monitor_location_high_power";
+    /** Access to {@link android.app.usage.UsageStatsManager}. */
+    public static final String OPSTR_GET_USAGE_STATS
+            = "android:get_usage_stats";
     /** Activate a VPN connection without user intervention. @hide */
     @SystemApi
     public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn";
@@ -331,7 +334,7 @@
             null,
             OPSTR_MONITOR_LOCATION,
             OPSTR_MONITOR_HIGH_POWER_LOCATION,
-            null,
+            OPSTR_GET_USAGE_STATS,
             null,
             null,
             null,
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 6843827..8b755cc 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -45,14 +45,17 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
 import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -864,6 +867,49 @@
         return getApplicationLogo(getApplicationInfo(packageName, 0));
     }
 
+    @Override
+    public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
+        final int badgeResId = getBadgeResIdForUser(user.getIdentifier());
+        if (badgeResId == 0) {
+            return icon;
+        }
+        Drawable badgeIcon = getDrawable("system", badgeResId, null);
+        return getBadgedDrawable(icon, badgeIcon, null, true);
+    }
+
+    @Override
+    public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user,
+            Rect badgeLocation, int badgeDensity) {
+        Drawable badgeDrawable = getUserBadgeForDensity(user, badgeDensity);
+        if (badgeDrawable == null) {
+            return drawable;
+        }
+        return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
+    }
+
+    @Override
+    public Drawable getUserBadgeForDensity(UserHandle user, int density) {
+        UserInfo userInfo = getUserIfProfile(user.getIdentifier());
+        if (userInfo != null && userInfo.isManagedProfile()) {
+            if (density <= 0) {
+                density = mContext.getResources().getDisplayMetrics().densityDpi;
+            }
+            return Resources.getSystem().getDrawableForDensity(
+                    com.android.internal.R.drawable.ic_corp_badge, density);
+        }
+        return null;
+    }
+
+    @Override
+    public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
+        UserInfo userInfo = getUserIfProfile(user.getIdentifier());
+        if (userInfo != null && userInfo.isManagedProfile()) {
+            return Resources.getSystem().getString(
+                    com.android.internal.R.string.managed_profile_label_badge, label);
+        }
+        return label;
+    }
+
     @Override public Resources getResourcesForActivity(
         ComponentName activityName) throws NameNotFoundException {
         return getResourcesForApplication(
@@ -1640,12 +1686,86 @@
         if (itemInfo.showUserIcon != UserHandle.USER_NULL) {
             return new BitmapDrawable(getUserManager().getUserIcon(itemInfo.showUserIcon));
         }
-        Drawable dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo);
+        Drawable dr = null;
+        if (itemInfo.packageName != null) {
+            dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo);
+        }
         if (dr == null) {
             dr = itemInfo.loadDefaultIcon(this);
         }
-        return getUserManager().getBadgedDrawableForUser(dr,
-                new UserHandle(mContext.getUserId()));
+        return getUserBadgedDrawableForDensity(dr, new UserHandle(mContext.getUserId()), null, 0);
+    }
+
+    private Drawable getBadgedDrawable(Drawable drawable, Drawable badgeDrawable,
+            Rect badgeLocation, boolean tryBadgeInPlace) {
+        final int badgedWidth = drawable.getIntrinsicWidth();
+        final int badgedHeight = drawable.getIntrinsicHeight();
+        final boolean canBadgeInPlace = tryBadgeInPlace
+                && (drawable instanceof BitmapDrawable)
+                && ((BitmapDrawable) drawable).getBitmap().isMutable();
+
+        final Bitmap bitmap;
+        if (canBadgeInPlace) {
+            bitmap = ((BitmapDrawable) drawable).getBitmap();
+        } else {
+            bitmap = Bitmap.createBitmap(badgedWidth, badgedHeight, Bitmap.Config.ARGB_8888);
+        }
+        Canvas canvas = new Canvas(bitmap);
+
+        if (!canBadgeInPlace) {
+            drawable.setBounds(0, 0, badgedWidth, badgedHeight);
+            drawable.draw(canvas);
+        }
+
+        if (badgeLocation != null) {
+            if (badgeLocation.left < 0 || badgeLocation.top < 0
+                    || badgeLocation.width() > badgedWidth || badgeLocation.height() > badgedHeight) {
+                throw new IllegalArgumentException("Badge location " + badgeLocation
+                        + " not in badged drawable bounds "
+                        + new Rect(0, 0, badgedWidth, badgedHeight));
+            }
+            badgeDrawable.setBounds(0, 0, badgeLocation.width(), badgeLocation.height());
+
+            canvas.save();
+            canvas.translate(badgeLocation.left, badgeLocation.top);
+            badgeDrawable.draw(canvas);
+            canvas.restore();
+        } else {
+            badgeDrawable.setBounds(0, 0, badgedWidth, badgedHeight);
+            badgeDrawable.draw(canvas);
+        }
+
+        if (!canBadgeInPlace) {
+            BitmapDrawable mergedDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
+
+            if (drawable instanceof BitmapDrawable) {
+                BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
+                mergedDrawable.setTargetDensity(bitmapDrawable.getBitmap().getDensity());
+            }
+
+            return mergedDrawable;
+        }
+
+        return drawable;
+    }
+
+    private int getBadgeResIdForUser(int userHandle) {
+        // Return the framework-provided badge.
+        UserInfo userInfo = getUserIfProfile(userHandle);
+        if (userInfo != null && userInfo.isManagedProfile()) {
+            return com.android.internal.R.drawable.ic_corp_icon_badge;
+        }
+        return 0;
+    }
+
+    private UserInfo getUserIfProfile(int userHandle) {
+        List<UserInfo> userProfiles = mUserManager.getProfiles(UserHandle.myUserId());
+        for (UserInfo user : userProfiles) {
+            if (user.id == userHandle) {
+                return user;
+            }
+        }
+        return null;
     }
 
     private final ContextImpl mContext;
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 67863a5..8227915 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -23,15 +23,17 @@
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.transition.Transition;
-import android.transition.TransitionInflater;
 import android.transition.TransitionManager;
 import android.transition.TransitionSet;
+import android.transition.TransitionUtils;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.LogWriter;
 import android.util.Pair;
+import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -42,8 +44,6 @@
     final int[] mOps;
     final int mTransition;
     final int mTransitionStyle;
-    final int mCustomTransition;
-    final int mSceneRoot;
     final String mName;
     final int mIndex;
     final int mBreadCrumbTitleRes;
@@ -96,8 +96,6 @@
         mBreadCrumbTitleText = bse.mBreadCrumbTitleText;
         mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes;
         mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText;
-        mCustomTransition = bse.mCustomTransition;
-        mSceneRoot = bse.mSceneRoot;
         mSharedElementSourceNames = bse.mSharedElementSourceNames;
         mSharedElementTargetNames = bse.mSharedElementTargetNames;
     }
@@ -112,8 +110,6 @@
         mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
         mBreadCrumbShortTitleRes = in.readInt();
         mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-        mCustomTransition = in.readInt();
-        mSceneRoot = in.readInt();
         mSharedElementSourceNames = in.createStringArrayList();
         mSharedElementTargetNames = in.createStringArrayList();
     }
@@ -164,8 +160,6 @@
         bse.mBreadCrumbTitleText = mBreadCrumbTitleText;
         bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes;
         bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText;
-        bse.mCustomTransition = mCustomTransition;
-        bse.mSceneRoot = mSceneRoot;
         bse.mSharedElementSourceNames = mSharedElementSourceNames;
         bse.mSharedElementTargetNames = mSharedElementTargetNames;
         bse.bumpBackStackNesting(1);
@@ -186,8 +180,6 @@
         TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0);
         dest.writeInt(mBreadCrumbShortTitleRes);
         TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0);
-        dest.writeInt(mCustomTransition);
-        dest.writeInt(mSceneRoot);
         dest.writeStringList(mSharedElementSourceNames);
         dest.writeStringList(mSharedElementTargetNames);
     }
@@ -254,8 +246,6 @@
     int mBreadCrumbShortTitleRes;
     CharSequence mBreadCrumbShortTitleText;
 
-    int mCustomTransition;
-    int mSceneRoot;
     ArrayList<String> mSharedElementSourceNames;
     ArrayList<String> mSharedElementTargetNames;
 
@@ -573,13 +563,6 @@
     }
 
     @Override
-    public FragmentTransaction setCustomTransition(int sceneRootId, int transitionId) {
-        mSceneRoot = sceneRootId;
-        mCustomTransition = transitionId;
-        return this;
-    }
-
-    @Override
     public FragmentTransaction addSharedElement(View sharedElement, String name) {
         String transitionName = sharedElement.getTransitionName();
         if (transitionName == null) {
@@ -760,8 +743,15 @@
 
         bumpBackStackNesting(1);
 
-        TransitionState state = beginTransition(mSharedElementSourceNames,
-                mSharedElementTargetNames);
+        SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
+        SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
+
+        calculateFragments(firstOutFragments, lastInFragments);
+
+        TransitionState state = null;
+        if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
+            state = beginTransition(firstOutFragments, lastInFragments, false);
+        }
 
         Op op = mHead;
         while (op != null) {
@@ -854,142 +844,606 @@
         }
 
         if (state != null) {
-            updateTransitionEndState(state, mSharedElementTargetNames);
+            updateTransitionEndState(state, firstOutFragments, lastInFragments, false);
         }
     }
 
-    private TransitionState beginTransition(ArrayList<String> sourceNames,
-            ArrayList<String> targetNames) {
-        if (mCustomTransition <= 0 || mSceneRoot <= 0) {
-            return null;
+    private static void setFirstOut(SparseArray<Fragment> fragments, Fragment fragment) {
+        if (fragment != null) {
+            int containerId = fragment.mContainerId;
+            if (containerId != 0 && !fragment.isHidden() && fragment.isAdded() &&
+                    fragment.getView() != null && fragments.get(containerId) == null) {
+                fragments.put(containerId, fragment);
+            }
         }
-        View rootView = mManager.mContainer.findViewById(mSceneRoot);
-        if (!(rootView instanceof ViewGroup)) {
-            throw new IllegalArgumentException("SceneRoot is not a ViewGroup");
-        }
-        TransitionState state = new TransitionState();
-        // get Transition scene root and create Transitions
-        state.sceneRoot = (ViewGroup) rootView;
-        state.sceneRoot.captureTransitioningViews(state.transitioningViews);
+    }
 
-        state.exitTransition = TransitionInflater.from(mManager.mActivity)
-                .inflateTransition(mCustomTransition);
-        state.sharedElementTransition = TransitionInflater.from(mManager.mActivity)
-                .inflateTransition(mCustomTransition);
-        state.enterTransition = TransitionInflater.from(mManager.mActivity)
-                .inflateTransition(mCustomTransition);
+    private void setLastIn(SparseArray<Fragment> fragments, Fragment fragment) {
+        if (fragment != null) {
+            int containerId = fragment.mContainerId;
+            if (containerId != 0) {
+                fragments.put(containerId, fragment);
+            }
+        }
+    }
+
+    /**
+     * Finds the first removed fragment and last added fragments when going forward.
+     * If none of the fragments have transitions, then both lists will be empty.
+     *
+     * @param firstOutFragments The list of first fragments to be removed, keyed on the
+     *                          container ID. This list will be modified by the method.
+     * @param lastInFragments The list of last fragments to be added, keyed on the
+     *                        container ID. This list will be modified by the method.
+     */
+    private void calculateFragments(SparseArray<Fragment> firstOutFragments,
+            SparseArray<Fragment> lastInFragments) {
+        Op op = mHead;
+        while (op != null) {
+            switch (op.cmd) {
+                case OP_ADD:
+                    setLastIn(lastInFragments, op.fragment);
+                    break;
+                case OP_REPLACE: {
+                    Fragment f = op.fragment;
+                    if (mManager.mAdded != null) {
+                        for (int i = 0; i < mManager.mAdded.size(); i++) {
+                            Fragment old = mManager.mAdded.get(i);
+                            if (f == null || old.mContainerId == f.mContainerId) {
+                                if (old == f) {
+                                    f = null;
+                                } else {
+                                    setFirstOut(firstOutFragments, old);
+                                }
+                            }
+                        }
+                    }
+                    setLastIn(lastInFragments, f);
+                    break;
+                }
+                case OP_REMOVE:
+                    setFirstOut(firstOutFragments, op.fragment);
+                    break;
+                case OP_HIDE:
+                    setFirstOut(firstOutFragments, op.fragment);
+                    break;
+                case OP_SHOW:
+                    setLastIn(lastInFragments, op.fragment);
+                    break;
+                case OP_DETACH:
+                    setFirstOut(firstOutFragments, op.fragment);
+                    break;
+                case OP_ATTACH:
+                    setLastIn(lastInFragments, op.fragment);
+                    break;
+            }
+
+            op = op.next;
+        }
+
+        if (!haveTransitions(firstOutFragments, lastInFragments, false)) {
+            firstOutFragments.clear();
+            lastInFragments.clear();
+        }
+    }
+
+    /**
+     * @return true if custom transitions exist on any fragment in firstOutFragments or
+     * lastInFragments or false otherwise.
+     */
+    private static boolean haveTransitions(SparseArray<Fragment> firstOutFragments,
+            SparseArray<Fragment> lastInFragments, boolean isBack) {
+        for (int i = firstOutFragments.size() - 1; i >= 0; i--) {
+            Fragment f = firstOutFragments.valueAt(i);
+            if (isBack) {
+                if (f.getReturnTransition() != null ||
+                        f.getSharedElementReturnTransition() != null) {
+                    return true;
+                }
+            } else if (f.getExitTransition() != null) {
+                return true;
+            }
+        }
+
+        for (int i = lastInFragments.size() - 1; i >= 0; i--) {
+            Fragment f = lastInFragments.valueAt(i);
+            if (isBack) {
+                if (f.getReenterTransition() != null) {
+                    return true;
+                }
+            } else if (f.getEnterTransition() != null ||
+                    f.getSharedElementEnterTransition() != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Finds the first removed fragment and last added fragments when popping the back stack.
+     * If none of the fragments have transitions, then both lists will be empty.
+     *
+     * @param firstOutFragments The list of first fragments to be removed, keyed on the
+     *                          container ID. This list will be modified by the method.
+     * @param lastInFragments The list of last fragments to be added, keyed on the
+     *                        container ID. This list will be modified by the method.
+     */
+    public void calculateBackFragments(SparseArray<Fragment> firstOutFragments,
+            SparseArray<Fragment> lastInFragments) {
+        Op op = mHead;
+        while (op != null) {
+            switch (op.cmd) {
+                case OP_ADD:
+                    setFirstOut(firstOutFragments, op.fragment);
+                    break;
+                case OP_REPLACE:
+                    if (op.removed != null) {
+                        for (int i = op.removed.size() - 1; i >= 0; i--) {
+                            setLastIn(lastInFragments, op.removed.get(i));
+                        }
+                    }
+                    setFirstOut(firstOutFragments, op.fragment);
+                    break;
+                case OP_REMOVE:
+                    setLastIn(lastInFragments, op.fragment);
+                    break;
+                case OP_HIDE:
+                    setLastIn(lastInFragments, op.fragment);
+                    break;
+                case OP_SHOW:
+                    setFirstOut(firstOutFragments, op.fragment);
+                    break;
+                case OP_DETACH:
+                    setLastIn(lastInFragments, op.fragment);
+                    break;
+                case OP_ATTACH:
+                    setFirstOut(firstOutFragments, op.fragment);
+                    break;
+            }
+
+            op = op.next;
+        }
+
+        if (!haveTransitions(firstOutFragments, lastInFragments, true)) {
+            firstOutFragments.clear();
+            lastInFragments.clear();
+        }
+    }
+
+    /**
+     * When custom fragment transitions are used, this sets up the state for each transition
+     * and begins the transition. A different transition is started for each fragment container
+     * and consists of up to 3 different transitions: the exit transition, a shared element
+     * transition and an enter transition.
+     *
+     * <p>The exit transition operates against the leaf nodes of the first fragment
+     * with a view that was removed. If no such fragment was removed, then no exit
+     * transition is executed. The exit transition comes from the outgoing fragment.</p>
+     *
+     * <p>The enter transition operates against the last fragment that was added. If
+     * that fragment does not have a view or no fragment was added, then no enter
+     * transition is executed. The enter transition comes from the incoming fragment.</p>
+     *
+     * <p>The shared element transition operates against all views and comes either
+     * from the outgoing fragment or the incoming fragment, depending on whether this
+     * is going forward or popping the back stack. When going forward, the incoming
+     * fragment's enter shared element transition is used, but when going back, the
+     * outgoing fragment's return shared element transition is used. Shared element
+     * transitions only operate if there is both an incoming and outgoing fragment.</p>
+     *
+     * @param firstOutFragments The list of first fragments to be removed, keyed on the
+     *                          container ID.
+     * @param lastInFragments The list of last fragments to be added, keyed on the
+     *                        container ID.
+     * @param isBack true if this is popping the back stack or false if this is a
+     *               forward operation.
+     * @return The TransitionState used to complete the operation of the transition
+     * in {@link #updateTransitionEndState(android.app.BackStackRecord.TransitionState,
+     * android.util.SparseArray, android.util.SparseArray, boolean)}.
+     */
+    private TransitionState beginTransition(SparseArray<Fragment> firstOutFragments,
+            SparseArray<Fragment> lastInFragments, boolean isBack) {
+        TransitionState state = new TransitionState();
+
         // Adding a non-existent target view makes sure that the transitions don't target
         // any views by default. They'll only target the views we tell add. If we don't
         // add any, then no views will be targeted.
-        View nonExistentView = new View(mManager.mActivity);
-        state.enterTransition.addTarget(nonExistentView);
-        state.exitTransition.addTarget(nonExistentView);
-        state.sharedElementTransition.addTarget(nonExistentView);
+        state.nonExistentView = new View(mManager.mActivity);
 
-        setSharedElementEpicenter(state.enterTransition, state);
+        ArrayMap<String, View> tempViews1 = new ArrayMap<String, View>();
+        ArrayMap<String, View> tempViews2 = new ArrayMap<String, View>();
+        ArrayList<String> tempNames = new ArrayList<String>();
+        ArrayList<View> tempViewList = new ArrayList<View>();
 
-        state.excludingTransition = new TransitionSet()
-                .addTransition(state.exitTransition)
-                .addTransition(state.enterTransition);
-
-        if (sourceNames != null) {
-            // Map shared elements.
-            state.sceneRoot.findNamedViews(state.namedViews);
-            state.namedViews.retainAll(sourceNames);
-            View epicenterView = state.namedViews.get(sourceNames.get(0));
-            if (epicenterView != null) {
-                // The epicenter is only the first shared element.
-                setEpicenter(state.exitTransition, epicenterView);
-                setEpicenter(state.sharedElementTransition, epicenterView);
-            }
-            state.transitioningViews.removeAll(state.namedViews.values());
-            state.excludingTransition.addTransition(state.sharedElementTransition);
-            addTransitioningViews(state.sharedElementTransition, state.namedViews.values());
+        // Go over all leaving fragments.
+        for (int i = 0; i < firstOutFragments.size(); i++) {
+            int containerId = firstOutFragments.keyAt(i);
+            configureTransitions(containerId, state, isBack, firstOutFragments,
+                    lastInFragments, tempViews1, tempViews2, tempNames, tempViewList);
         }
 
-        // Adds the (maybe) exiting views, not including the shared element.
-        // If some stay, that's ok.
-        addTransitioningViews(state.exitTransition, state.transitioningViews);
+        // Now go over all entering fragments that didn't have a leaving fragment.
+        for (int i = 0; i < lastInFragments.size(); i++) {
+            int containerId = lastInFragments.keyAt(i);
+            if (firstOutFragments.get(containerId) == null) {
+                configureTransitions(containerId, state, isBack, firstOutFragments,
+                        lastInFragments, tempViews1, tempViews2, tempNames, tempViewList);
+            }
+        }
 
-        // Prepare for shared element name mapping. This could be chained in the case
-        // of popping several back stack states.
-        state.excludingTransition.setNameOverrides(new ArrayMap<String, String>());
-        setNameOverrides(state, sourceNames, targetNames);
-
-        // Don't include any subtree in the views that are hidden when capturing the
-        // view hierarchy transitions. They should be as if not there.
-        excludeHiddenFragments(state, true);
-
-        TransitionManager.beginDelayedTransition(state.sceneRoot, state.excludingTransition);
+        if (state.overallTransitions.size() == 0) {
+            state = null;
+        }
         return state;
     }
 
-    private void updateTransitionEndState(TransitionState state, ArrayList<String> names) {
-        // Find all views that are entering.
-        ArrayList<View> enteringViews = new ArrayList<View>();
-        state.sceneRoot.captureTransitioningViews(enteringViews);
-        enteringViews.removeAll(state.transitioningViews);
+    private static Transition getEnterTransition(Fragment inFragment, boolean isBack) {
+        if (inFragment == null) {
+            return null;
+        }
+        return isBack ? inFragment.getReenterTransition() : inFragment.getEnterTransition();
+    }
 
-        if (names != null) {
-            // find all shared elements.
-            state.namedViews.clear();
-            state.sceneRoot.findNamedViews(state.namedViews);
-            state.namedViews.retainAll(names);
-            if (!state.namedViews.isEmpty()) {
-                enteringViews.removeAll(state.namedViews.values());
-                addTransitioningViews(state.sharedElementTransition, state.namedViews.values());
-                // now we know the epicenter of the entering transition.
-                state.mEnteringEpicenterView = state.namedViews.get(names.get(0));
+    private static Transition getExitTransition(Fragment outFragment, boolean isBack) {
+        if (outFragment == null) {
+            return null;
+        }
+        return isBack ? outFragment.getReturnTransition() : outFragment.getExitTransition();
+    }
+
+    private static Transition getSharedElementTransition(Fragment inFragment, Fragment outFragment,
+            boolean isBack) {
+        if (inFragment == null || outFragment == null) {
+            return null;
+        }
+        return isBack ? outFragment.getSharedElementReturnTransition() :
+                inFragment.getSharedElementEnterTransition();
+    }
+
+    private static Transition captureExitingViews(Transition exitTransition, Fragment outFragment,
+            ArrayList<View> viewList) {
+        if (exitTransition != null) {
+            View root = outFragment.getView();
+            viewList.clear();
+            root.captureTransitioningViews(viewList);
+            if (viewList.isEmpty()) {
+                exitTransition = null;
+            } else {
+                addTransitioningViews(exitTransition, viewList);
+            }
+        }
+        return exitTransition;
+    }
+
+    private ArrayMap<String, View> remapSharedElements(TransitionState state, Fragment outFragment,
+            ArrayMap<String, View> namedViews, ArrayMap<String, View> tempViews2, boolean isBack) {
+        if (mSharedElementSourceNames != null) {
+            outFragment.getView().findNamedViews(namedViews);
+            if (isBack) {
+                namedViews.retainAll(mSharedElementTargetNames);
+            } else {
+                namedViews = remapNames(mSharedElementSourceNames, mSharedElementTargetNames,
+                        namedViews, tempViews2);
             }
         }
 
-        // Add all entering views to the enter transition.
-        addTransitioningViews(state.enterTransition, enteringViews);
-
-        // Don't allow capturing state for the newly-hidden fragments.
-        excludeHiddenFragments(state, false);
-
-        // Allow capturing state for the newly-shown fragments
-        includeVisibleFragments(state.excludingTransition);
-    }
-
-    private void addTransitioningViews(Transition transition, Collection<View> views) {
-        if (views.isEmpty()) {
-            // Add a view so that we can modify the valid views at the end of the
-            // fragment transaction.
-            transition.addTarget(new View(mManager.mActivity));
+        if (isBack) {
+            outFragment.mEnterTransitionCallback.onMapSharedElements(
+                    mSharedElementTargetNames, namedViews);
+            setBackNameOverrides(state, namedViews, false);
         } else {
-            for (View view : views) {
-                transition.addTarget(view);
+            outFragment.mExitTransitionCallback.onMapSharedElements(
+                    mSharedElementTargetNames, namedViews);
+            setNameOverrides(state, namedViews, false);
+        }
+
+        return namedViews;
+    }
+
+    /**
+     * Prepares the enter transition by adding a non-existent view to the transition's target list
+     * and setting it epicenter callback. By adding a non-existent view to the target list,
+     * we can prevent any view from being targeted at the beginning of the transition.
+     * We will add to the views before the end state of the transition is captured so that the
+     * views will appear. At the start of the transition, we clear the list of targets so that
+     * we can restore the state of the transition and use it again.
+     */
+    private void prepareEnterTransition(TransitionState state, final Transition enterTransition,
+            final View container, final Fragment inFragment) {
+        if (enterTransition != null) {
+            final ArrayList<View> enteringViews = new ArrayList<View>();
+            final View nonExistentView = state.nonExistentView;
+            enterTransition.addTarget(state.nonExistentView);
+            enterTransition.addListener(new Transition.TransitionListenerAdapter() {
+                @Override
+                public void onTransitionStart(Transition transition) {
+                    transition.removeListener(this);
+                    transition.removeTarget(nonExistentView);
+                    int numViews = enteringViews.size();
+                    for (int i = 0; i < numViews; i++) {
+                        transition.removeTarget(enteringViews.get(i));
+                    }
+                }
+            });
+            container.getViewTreeObserver().addOnPreDrawListener(
+                    new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            container.getViewTreeObserver().removeOnPreDrawListener(this);
+                            View view = inFragment.getView();
+                            if (view != null) {
+                                view.captureTransitioningViews(enteringViews);
+                                addTransitioningViews(enterTransition, enteringViews);
+                            }
+                            return true;
+                        }
+                    });
+            setSharedElementEpicenter(enterTransition, state);
+        }
+    }
+
+    private static Transition mergeTransitions(Transition enterTransition,
+            Transition exitTransition, Transition sharedElementTransition, Fragment inFragment,
+            boolean isBack) {
+        boolean overlap = true;
+        if (enterTransition != null && exitTransition != null) {
+            overlap = isBack ? inFragment.getAllowReturnTransitionOverlap() :
+                    inFragment.getAllowEnterTransitionOverlap();
+        }
+
+        Transition transition;
+        if (overlap) {
+            transition = TransitionUtils.mergeTransitions(enterTransition, exitTransition,
+                    sharedElementTransition);
+        } else {
+            TransitionSet staggered = new TransitionSet()
+                    .addTransition(exitTransition)
+                    .addTransition(enterTransition)
+                    .setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
+            transition = TransitionUtils.mergeTransitions(staggered, sharedElementTransition);
+        }
+        return transition;
+    }
+
+    /**
+     * Configures custom transitions for a specific fragment container.
+     *
+     * @param containerId The container ID of the fragments to configure the transition for.
+     * @param state The Transition State to be shared with {@link #updateTransitionEndState(
+     * android.app.BackStackRecord.TransitionState, android.util.SparseArray,
+     * android.util.SparseArray, boolean)} later.
+     * @param firstOutFragments The list of first fragments to be removed, keyed on the
+     *                          container ID.
+     * @param lastInFragments The list of last fragments to be added, keyed on the
+     *                        container ID.
+     * @param isBack true if this is popping the back stack or false if this is a
+     *               forward operation.
+     * @param tempViews1 A temporary mapping of names to Views, used to avoid allocation
+     *                   inside a loop.
+     * @param tempViews2 A temporary mapping of names to Views, used to avoid allocation
+     *                   inside a loop.
+     * @param tempNames  A temporary list of Strings, used to avoid allocation inside a loop.
+     * @param tempViewList A temporary list of Views, used to avoid allocation inside a loop.
+     */
+    private void configureTransitions(int containerId, TransitionState state, boolean isBack,
+            SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments,
+            ArrayMap<String, View> tempViews1, ArrayMap<String, View> tempViews2,
+            ArrayList<String> tempNames, ArrayList<View> tempViewList) {
+        ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.findViewById(containerId);
+        if (sceneRoot != null) {
+            Fragment inFragment = lastInFragments.get(containerId);
+            Fragment outFragment = firstOutFragments.get(containerId);
+
+            Transition enterTransition = getEnterTransition(inFragment, isBack);
+            Transition sharedElementTransition = getSharedElementTransition(inFragment, outFragment,
+                    isBack);
+            Transition exitTransition = getExitTransition(outFragment, isBack);
+            exitTransition = captureExitingViews(exitTransition, outFragment, tempViewList);
+
+            ArrayMap<String, View> namedViews = tempViews1;
+            namedViews.clear();
+            if (sharedElementTransition != null) {
+                namedViews = remapSharedElements(state,
+                        outFragment, namedViews, tempViews2, isBack);
+            }
+
+            // Notify the start of the transition.
+            SharedElementCallback callback = isBack ?
+                    outFragment.mEnterTransitionCallback :
+                    inFragment.mEnterTransitionCallback;
+            tempNames.clear();
+            tempNames.addAll(namedViews.keySet());
+            tempViewList.clear();
+            tempViewList.addAll(namedViews.values());
+            callback.onSharedElementStart(tempNames, tempViewList, null);
+
+            // Set the epicenter of the exit transition
+            if (mSharedElementTargetNames != null && exitTransition != null) {
+                View epicenterView = namedViews.get(mSharedElementTargetNames.get(0));
+                if (epicenterView != null) {
+                    setEpicenter(exitTransition, epicenterView);
+                }
+            }
+
+            prepareEnterTransition(state, enterTransition, sceneRoot, inFragment);
+
+            Transition transition = mergeTransitions(enterTransition, exitTransition,
+                    sharedElementTransition, inFragment, isBack);
+
+            if (transition != null) {
+                state.overallTransitions.put(containerId, transition);
+                transition.setNameOverrides(state.nameOverrides);
+                // We want to exclude hidden views later, so we need a non-null list in the
+                // transition now.
+                transition.excludeTarget(state.nonExistentView, true);
+                // Now exclude all currently hidden fragments.
+                excludeHiddenFragments(state, containerId, transition);
+                cleanupHiddenFragments(transition, state);
+                TransitionManager.beginDelayedTransition(sceneRoot, transition);
             }
         }
     }
 
-    private void excludeHiddenFragments(TransitionState state, boolean forceExclude) {
-        if (mManager.mAdded != null) {
-            for (int i = 0; i < mManager.mAdded.size(); i++) {
-                Fragment fragment = mManager.mAdded.get(i);
-                if (fragment.mView != null && fragment.mHidden
-                        && (forceExclude || !state.hiddenViews.contains(fragment.mView))) {
-                    state.excludingTransition.excludeTarget(fragment.mView, true);
-                    state.hiddenViews.add(fragment.mView);
+    /**
+     * Remaps a name-to-View map, substituting different names for keys.
+     *
+     * @param inMap A list of keys found in the map, in the order in toGoInMap
+     * @param toGoInMap A list of keys to use for the new map, in the order of inMap
+     * @param namedViews The current mapping
+     * @param tempMap A temporary mapping that will be filled with the new values.
+     * @return tempMap after it has been mapped with the new names as keys.
+     */
+    private static ArrayMap<String, View> remapNames(ArrayList<String> inMap,
+            ArrayList<String> toGoInMap, ArrayMap<String, View> namedViews,
+            ArrayMap<String, View> tempMap) {
+        tempMap.clear();
+        if (!namedViews.isEmpty()) {
+            int numKeys = inMap.size();
+            for (int i = 0; i < numKeys; i++) {
+                View view = namedViews.get(inMap.get(i));
+                if (view != null) {
+                    tempMap.put(toGoInMap.get(i), view);
                 }
             }
         }
-        if (forceExclude && state.hiddenViews.isEmpty()) {
-            state.excludingTransition.excludeTarget(new View(mManager.mActivity), true);
+        return tempMap;
+    }
+
+    /**
+     * After making all fragment changes, this updates the custom transitions to take into
+     * account the entering views and any remapping.
+     *
+     * @param state The transition State as returned from {@link #beginTransition(
+     * android.util.SparseArray, android.util.SparseArray, boolean)}.
+     * @param outFragments The list of first fragments to be removed, keyed on the
+     *                     container ID.
+     * @param inFragments The list of last fragments to be added, keyed on the
+     *                    container ID.
+     * @param isBack true if this is popping the back stack or false if this is a
+     *               forward operation.
+     */
+    private void updateTransitionEndState(TransitionState state, SparseArray<Fragment> outFragments,
+            SparseArray<Fragment> inFragments, boolean isBack) {
+        ArrayMap<String, View> tempViews1 = new ArrayMap<String, View>();
+        ArrayMap<String, View> tempViews2 = new ArrayMap<String, View>();
+        ArrayList<String> tempNames = new ArrayList<String>();
+        ArrayList<View> tempViews = new ArrayList<View>();
+
+        int numInFragments = inFragments.size();
+        for (int i = 0; i < numInFragments; i++) {
+            Fragment inFragment = inFragments.valueAt(i);
+            tempViews1.clear();
+            ArrayMap<String, View> namedViews = mapEnteringSharedElements(inFragment, tempViews1,
+                    tempViews2, isBack);
+            // remap shared elements and set the name mapping used in the shared element transition.
+            if (isBack) {
+                inFragment.mExitTransitionCallback.onMapSharedElements(
+                        mSharedElementTargetNames, namedViews);
+                setBackNameOverrides(state, namedViews, true);
+            } else {
+                inFragment.mEnterTransitionCallback.onMapSharedElements(
+                        mSharedElementTargetNames, namedViews);
+                setNameOverrides(state, namedViews, true);
+            }
+
+            if (mSharedElementTargetNames != null && !namedViews.isEmpty()) {
+                // now we know the epicenter of the entering transition.
+                View epicenter = namedViews.get(mSharedElementTargetNames.get(0));
+                if (epicenter != null) {
+                    state.enteringEpicenterView = epicenter;
+                }
+            }
+
+            int containerId = inFragments.keyAt(i);
+            SharedElementCallback sharedElementCallback = isBack ?
+                    outFragments.get(containerId).mEnterTransitionCallback :
+                    inFragment.mEnterTransitionCallback;
+            tempNames.clear();
+            tempNames.addAll(namedViews.keySet());
+            tempViews.clear();
+            tempViews.addAll(namedViews.values());
+            sharedElementCallback.onSharedElementEnd(tempNames, tempViews, null);
+        }
+
+        // Don't include any newly-hidden fragments in the transition.
+        excludeHiddenFragments(state);
+    }
+
+    private ArrayMap<String, View> mapEnteringSharedElements(Fragment inFragment,
+            ArrayMap<String, View> namedViews, ArrayMap<String, View> tempViews2, boolean isBack) {
+        View root = inFragment.getView();
+        if (root != null) {
+            if (mSharedElementSourceNames != null) {
+                root.findNamedViews(namedViews);
+                if (isBack) {
+                    namedViews = remapNames(mSharedElementSourceNames,
+                            mSharedElementTargetNames, namedViews, tempViews2);
+                } else {
+                    namedViews.retainAll(mSharedElementTargetNames);
+                }
+            }
+        }
+        return namedViews;
+    }
+
+    private static void cleanupHiddenFragments(Transition transition, TransitionState state) {
+        final ArrayList<View> hiddenViews = state.hiddenFragmentViews;
+        transition.addListener(new Transition.TransitionListenerAdapter() {
+            @Override
+            public void onTransitionStart(Transition transition) {
+                transition.removeListener(this);
+                int numViews = hiddenViews.size();
+                for (int i = 0; i < numViews; i++) {
+                    transition.excludeTarget(hiddenViews.get(i), false);
+                }
+            }
+        });
+    }
+
+    private void excludeHiddenFragments(TransitionState state, int containerId,
+            Transition transition) {
+        if (mManager.mAdded != null) {
+            for (int i = 0; i < mManager.mAdded.size(); i++) {
+                Fragment fragment = mManager.mAdded.get(i);
+                if (fragment.mView != null && fragment.mContainer != null &&
+                        fragment.mContainerId == containerId) {
+                    if (fragment.mHidden) {
+                        if (!state.hiddenFragmentViews.contains(fragment.mView)) {
+                            transition.excludeTarget(fragment.mView, true);
+                            state.hiddenFragmentViews.add(fragment.mView);
+                        }
+                    } else {
+                        transition.excludeTarget(fragment.mView, false);
+                        state.hiddenFragmentViews.remove(fragment.mView);
+                    }
+                }
+            }
         }
     }
 
-    private void includeVisibleFragments(Transition transition) {
-        if (mManager.mAdded != null) {
-            for (int i = 0; i < mManager.mAdded.size(); i++) {
-                Fragment fragment = mManager.mAdded.get(i);
-                if (fragment.mView != null && !fragment.mHidden) {
-                    transition.excludeTarget(fragment.mView, false);
+    private void excludeHiddenFragments(TransitionState state) {
+        int numTransitions = state.overallTransitions.size();
+        for (int i = 0; i < numTransitions; i++) {
+            Transition transition = state.overallTransitions.valueAt(i);
+            int containerId = state.overallTransitions.keyAt(i);
+            excludeHiddenFragments(state, containerId, transition);
+        }
+    }
+
+    private static void addTransitioningViews(Transition transition, final Collection<View> views) {
+        for (View view : views) {
+            transition.addTarget(view);
+        }
+
+        transition.addListener(new Transition.TransitionListenerAdapter() {
+            @Override
+            public void onTransitionStart(Transition transition) {
+                transition.removeListener(this);
+                for (View view : views) {
+                    transition.removeTarget(view);
                 }
             }
-        }
+        });
     }
 
     private static void setEpicenter(Transition transition, View view) {
@@ -1010,16 +1464,17 @@
 
             @Override
             public Rect onGetEpicenter(Transition transition) {
-                if (mEpicenter == null && state.mEnteringEpicenterView != null) {
+                if (mEpicenter == null && state.enteringEpicenterView != null) {
                     mEpicenter = new Rect();
-                    state.mEnteringEpicenterView.getBoundsOnScreen(mEpicenter);
+                    state.enteringEpicenterView.getBoundsOnScreen(mEpicenter);
                 }
                 return mEpicenter;
             }
         });
     }
 
-    public TransitionState popFromBackStack(boolean doStateMove, TransitionState state) {
+    public TransitionState popFromBackStack(boolean doStateMove, TransitionState state,
+            SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) {
         if (FragmentManagerImpl.DEBUG) {
             Log.v(TAG, "popFromBackStack: " + this);
             LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
@@ -1029,8 +1484,10 @@
         }
 
         if (state == null) {
-            state = beginTransition(mSharedElementTargetNames, mSharedElementSourceNames);
-        } else {
+            if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) {
+                state = beginTransition(firstOutFragments, lastInFragments, true);
+            }
+        } else if (!doStateMove) {
             setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames);
         }
 
@@ -1110,7 +1567,7 @@
             mManager.moveToState(mManager.mCurState,
                     FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true);
             if (state != null) {
-                updateTransitionEndState(state, mSharedElementSourceNames);
+                updateTransitionEndState(state, firstOutFragments, lastInFragments, true);
                 state = null;
             }
         }
@@ -1122,15 +1579,17 @@
         return state;
     }
 
-    private static void setNameOverride(Transition transition, String source, String target) {
-        ArrayMap<String, String> overrides = transition.getNameOverrides();
-        for (int index = 0; index < overrides.size(); index++) {
-            if (source.equals(overrides.valueAt(index))) {
-                overrides.setValueAt(index, target);
-                return;
+    private static void setNameOverride(ArrayMap<String, String> overrides,
+            String source, String target) {
+        if (source != null && target != null && !source.equals(target)) {
+            for (int index = 0; index < overrides.size(); index++) {
+                if (source.equals(overrides.valueAt(index))) {
+                    overrides.setValueAt(index, target);
+                    return;
+                }
             }
+            overrides.put(source, target);
         }
-        overrides.put(source, target);
     }
 
     private static void setNameOverrides(TransitionState state, ArrayList<String> sourceNames,
@@ -1139,7 +1598,36 @@
             for (int i = 0; i < sourceNames.size(); i++) {
                 String source = sourceNames.get(i);
                 String target = targetNames.get(i);
-                setNameOverride(state.excludingTransition, source, target);
+                setNameOverride(state.nameOverrides, source, target);
+            }
+        }
+    }
+
+    private void setBackNameOverrides(TransitionState state, ArrayMap<String, View> namedViews,
+            boolean isEnd) {
+        int count = mSharedElementTargetNames.size();
+        for (int i = 0; i < count; i++) {
+            String source = mSharedElementSourceNames.get(i);
+            String originalTarget = mSharedElementTargetNames.get(i);
+            String target = namedViews.get(originalTarget).getTransitionName();
+            if (isEnd) {
+                setNameOverride(state.nameOverrides, source, target);
+            } else {
+                setNameOverride(state.nameOverrides, target, source);
+            }
+        }
+    }
+
+    private void setNameOverrides(TransitionState state, ArrayMap<String, View> namedViews,
+            boolean isEnd) {
+        int count = namedViews.size();
+        for (int i = 0; i < count; i++) {
+            String source = namedViews.keyAt(i);
+            String target = namedViews.valueAt(i).getTransitionName();
+            if (isEnd) {
+                setNameOverride(state.nameOverrides, source, target);
+            } else {
+                setNameOverride(state.nameOverrides, target, source);
             }
         }
     }
@@ -1161,14 +1649,11 @@
     }
 
     public class TransitionState {
-        public ArrayList<View> hiddenViews = new ArrayList<View>();
-        public ArrayList<View> transitioningViews = new ArrayList<View>();
-        public ArrayMap<String, View> namedViews = new ArrayMap<String, View>();
-        public Transition exitTransition;
-        public Transition sharedElementTransition;
-        public Transition enterTransition;
-        public TransitionSet excludingTransition;
-        public ViewGroup sceneRoot;
-        public View mEnteringEpicenterView;
+        public SparseArray<Transition> overallTransitions = new SparseArray<Transition>();
+        public ArrayMap<String, String> nameOverrides = new ArrayMap<String, String>();
+        public ArrayList<View> hiddenFragmentViews = new ArrayList<View>();
+
+        public View enteringEpicenterView;
+        public View nonExistentView;
     }
 }
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 47d3fd6..f432c49 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -21,8 +21,6 @@
 import android.graphics.Matrix;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
 import android.os.ResultReceiver;
 import android.text.TextUtils;
 import android.transition.Transition;
@@ -71,12 +69,13 @@
         Bundle resultReceiverBundle = new Bundle();
         resultReceiverBundle.putParcelable(KEY_REMOTE_RECEIVER, this);
         mResultReceiver.send(MSG_SET_REMOTE_RECEIVER, resultReceiverBundle);
-        getDecor().getViewTreeObserver().addOnPreDrawListener(
+        final View decorView = getDecor();
+        decorView.getViewTreeObserver().addOnPreDrawListener(
                 new ViewTreeObserver.OnPreDrawListener() {
                     @Override
                     public boolean onPreDraw() {
                         if (mIsReadyForTransition) {
-                            getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
                         }
                         return mIsReadyForTransition;
                     }
@@ -170,7 +169,7 @@
 
     private void sendSharedElementDestination() {
         boolean allReady;
-        if (allowOverlappingTransitions()) {
+        if (allowOverlappingTransitions() && getEnterViewsTransition() != null) {
             allReady = false;
         } else {
             allReady = !getDecor().isLayoutRequested();
@@ -189,11 +188,12 @@
             moveSharedElementsToOverlay();
             mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state);
         } else {
-            getDecor().getViewTreeObserver()
+            final View decorView = getDecor();
+            decorView.getViewTreeObserver()
                     .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                         @Override
                         public boolean onPreDraw() {
-                            getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
                             if (mResultReceiver != null) {
                                 Bundle state = captureSharedElementState();
                                 setSharedElementMatrices();
@@ -209,7 +209,7 @@
         }
     }
 
-    private static SharedElementListener getListener(Activity activity, boolean isReturning) {
+    private static SharedElementCallback getListener(Activity activity, boolean isReturning) {
         return isReturning ? activity.mExitTransitionListener : activity.mEnterTransitionListener;
     }
 
@@ -294,7 +294,7 @@
         ArrayList<String> rejectedNames = new ArrayList<String>(mAllSharedElementNames);
         rejectedNames.removeAll(mSharedElementNames);
         ArrayList<View> rejectedSnapshots = createSnapshots(sharedElementState, rejectedNames);
-        mListener.handleRejectedSharedElements(rejectedSnapshots);
+        mListener.onRejectSharedElements(rejectedSnapshots);
         startRejectedAnimations(rejectedSnapshots);
 
         // Now start shared element transition
@@ -344,11 +344,12 @@
         }
         final Bundle sharedElementState = mSharedElementsBundle;
         mSharedElementsBundle = null;
-        getDecor().getViewTreeObserver()
+        final View decorView = getDecor();
+        decorView.getViewTreeObserver()
                 .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                     @Override
                     public boolean onPreDraw() {
-                        getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+                        decorView.getViewTreeObserver().removeOnPreDrawListener(this);
                         startTransition(new Runnable() {
                             @Override
                             public void run() {
@@ -358,7 +359,7 @@
                         return false;
                     }
                 });
-        getDecor().invalidate();
+        decorView.invalidate();
     }
 
     private void requestLayoutForSharedElements() {
@@ -466,6 +467,7 @@
             Drawable background = getDecor().getBackground();
             if (background != null) {
                 background = background.mutate();
+                getWindow().setBackgroundDrawable(background);
                 mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 255);
                 mBackgroundAnimator.setDuration(getFadeDuration());
                 mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 3760b96..a59a927 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -79,7 +79,7 @@
         mActivity = activity;
     }
 
-    private static SharedElementListener getListener(Activity activity, boolean isReturning) {
+    private static SharedElementCallback getListener(Activity activity, boolean isReturning) {
         return isReturning ? activity.mEnterTransitionListener : activity.mExitTransitionListener;
     }
 
@@ -140,7 +140,8 @@
         if (getDecor() != null) {
             getDecor().suppressLayout(true);
         }
-        if (!mSharedElements.isEmpty() && getSharedElementTransition() != null) {
+        if (mExitSharedElementBundle != null && !mExitSharedElementBundle.isEmpty() &&
+                !mSharedElements.isEmpty() && getSharedElementTransition() != null) {
             startTransition(new Runnable() {
                 public void run() {
                     startSharedElementExit();
@@ -164,18 +165,19 @@
         });
         final ArrayList<View> sharedElementSnapshots = createSnapshots(mExitSharedElementBundle,
                 mSharedElementNames);
-        getDecor().getViewTreeObserver()
+        final View decorView = getDecor();
+        decorView.getViewTreeObserver()
                 .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                     @Override
                     public boolean onPreDraw() {
-                        getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+                        decorView.getViewTreeObserver().removeOnPreDrawListener(this);
                         setSharedElementState(mExitSharedElementBundle, sharedElementSnapshots);
                         return true;
                     }
                 });
         setGhostVisibility(View.INVISIBLE);
         scheduleGhostVisibilityChange(View.INVISIBLE);
-        mListener.setSharedElementEnd(mSharedElementNames, mSharedElements, sharedElementSnapshots);
+        mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, sharedElementSnapshots);
         TransitionManager.beginDelayedTransition(getDecor(), transition);
         scheduleGhostVisibilityChange(View.VISIBLE);
         setGhostVisibility(View.VISIBLE);
@@ -259,6 +261,8 @@
             ViewGroup decor = getDecor();
             Drawable background;
             if (decor != null && (background = decor.getBackground()) != null) {
+                background = background.mutate();
+                getWindow().setBackgroundDrawable(background);
                 mBackgroundAnimator = ObjectAnimator.ofInt(background, "alpha", 0);
                 mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
                     @Override
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 2ff3d57..672ef7b 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -23,10 +23,14 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.transition.Transition;
+import android.transition.TransitionInflater;
+import android.transition.TransitionSet;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
 import android.util.AttributeSet;
@@ -58,11 +62,11 @@
     final boolean mRetainInstance;
     final boolean mDetached;
     final Bundle mArguments;
-    
+
     Bundle mSavedFragmentState;
-    
+
     Fragment mInstance;
-    
+
     public FragmentState(Fragment frag) {
         mClassName = frag.getClass().getName();
         mIndex = frag.mIndex;
@@ -74,7 +78,7 @@
         mDetached = frag.mDetached;
         mArguments = frag.mArguments;
     }
-    
+
     public FragmentState(Parcel in) {
         mClassName = in.readString();
         mIndex = in.readInt();
@@ -87,18 +91,18 @@
         mArguments = in.readBundle();
         mSavedFragmentState = in.readBundle();
     }
-    
+
     public Fragment instantiate(Activity activity, Fragment parent) {
         if (mInstance != null) {
             return mInstance;
         }
-        
+
         if (mArguments != null) {
             mArguments.setClassLoader(activity.getClassLoader());
         }
-        
+
         mInstance = Fragment.instantiate(activity, mClassName, mArguments);
-        
+
         if (mSavedFragmentState != null) {
             mSavedFragmentState.setClassLoader(activity.getClassLoader());
             mInstance.mSavedFragmentState = mSavedFragmentState;
@@ -117,7 +121,7 @@
 
         return mInstance;
     }
-    
+
     public int describeContents() {
         return 0;
     }
@@ -134,13 +138,13 @@
         dest.writeBundle(mArguments);
         dest.writeBundle(mSavedFragmentState);
     }
-    
+
     public static final Parcelable.Creator<FragmentState> CREATOR
             = new Parcelable.Creator<FragmentState>() {
         public FragmentState createFromParcel(Parcel in) {
             return new FragmentState(in);
         }
-        
+
         public FragmentState[] newArray(int size) {
             return new FragmentState[size];
         }
@@ -299,17 +303,17 @@
  * how you can determine if a fragment placed in a container is no longer
  * running in a layout with that container and avoid creating its view hierarchy
  * in that case.)
- * 
+ *
  * <p>The attributes of the &lt;fragment&gt; tag are used to control the
  * LayoutParams provided when attaching the fragment's view to the parent
  * container.  They can also be parsed by the fragment in {@link #onInflate}
  * as parameters.
- * 
+ *
  * <p>The fragment being instantiated must have some kind of unique identifier
  * so that it can be re-associated with a previous instance if the parent
  * activity needs to be destroyed and recreated.  This can be provided these
  * ways:
- * 
+ *
  * <ul>
  * <li>If nothing is explicitly supplied, the view ID of the container will
  * be used.
@@ -318,7 +322,7 @@
  * <li><code>android:id</code> can be used in &lt;fragment&gt; to provide
  * a specific identifier for the fragment.
  * </ul>
- * 
+ *
  * <a name="BackStack"></a>
  * <h3>Back Stack</h3>
  *
@@ -347,7 +351,7 @@
 public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener {
     private static final ArrayMap<String, Class<?>> sClassMap =
             new ArrayMap<String, Class<?>>();
-    
+
     static final int INVALID_STATE = -1;   // Invalid state used as a null value.
     static final int INITIALIZING = 0;     // Not yet created.
     static final int CREATED = 1;          // Created.
@@ -355,9 +359,11 @@
     static final int STOPPED = 3;          // Fully created, not started.
     static final int STARTED = 4;          // Created and started, not resumed.
     static final int RESUMED = 5;          // Created started and resumed.
-    
+
+    private static final Transition USE_DEFAULT_TRANSITION = new TransitionSet();
+
     int mState = INITIALIZING;
-    
+
     // Non-null if the fragment's view hierarchy is currently animating away,
     // meaning we need to wait a bit on completely destroying it.  This is the
     // animation that is running.
@@ -370,13 +376,13 @@
     // When instantiated from saved state, this is the saved state.
     Bundle mSavedFragmentState;
     SparseArray<Parcelable> mSavedViewState;
-    
+
     // Index into active fragment array.
     int mIndex = -1;
-    
+
     // Internal unique name for this fragment;
     String mWho;
-    
+
     // Construction arguments;
     Bundle mArguments;
 
@@ -391,25 +397,25 @@
 
     // True if the fragment is in the list of added fragments.
     boolean mAdded;
-    
+
     // If set this fragment is being removed from its activity.
     boolean mRemoving;
 
     // True if the fragment is in the resumed state.
     boolean mResumed;
-    
+
     // Set to true if this fragment was instantiated from a layout file.
     boolean mFromLayout;
-    
+
     // Set to true when the view has actually been inflated in its layout.
     boolean mInLayout;
 
     // True if this fragment has been restored from previously saved state.
     boolean mRestored;
-    
+
     // Number of active back stack entries this fragment is in.
     int mBackStackNesting;
-    
+
     // The fragment manager we are associated with.  Set as soon as the
     // fragment is used in a transaction; cleared after it has been removed
     // from all transactions.
@@ -428,29 +434,29 @@
     // was dynamically added to the view hierarchy, or the ID supplied in
     // layout.
     int mFragmentId;
-    
+
     // When a fragment is being dynamically added to the view hierarchy, this
     // is the identifier of the parent container it is being added to.
     int mContainerId;
-    
+
     // The optional named tag for this fragment -- usually used to find
     // fragments that are not part of the layout.
     String mTag;
-    
+
     // Set to true when the app has requested that this fragment be hidden
     // from the user.
     boolean mHidden;
-    
+
     // Set to true when the app has requested that this fragment be detached.
     boolean mDetached;
 
     // If set this fragment would like its instance retained across
     // configuration changes.
     boolean mRetainInstance;
-    
+
     // If set this fragment is being retained across the current config change.
     boolean mRetaining;
-    
+
     // If set this fragment has menu items to contribute.
     boolean mHasMenu;
 
@@ -459,16 +465,16 @@
 
     // Used to verify that subclasses call through to super class.
     boolean mCalled;
-    
+
     // If app has requested a specific animation, this is the one to use.
     int mNextAnim;
-    
+
     // The parent container of the fragment after dynamically added to UI.
     ViewGroup mContainer;
-    
+
     // The View generated for this fragment.
     View mView;
-    
+
     // Whether this fragment should defer starting until after other fragments
     // have been started and their loaders are finished.
     boolean mDeferStart;
@@ -479,7 +485,19 @@
     LoaderManagerImpl mLoaderManager;
     boolean mLoadersStarted;
     boolean mCheckedForLoaderManager;
-    
+
+    private Transition mEnterTransition = null;
+    private Transition mReturnTransition = USE_DEFAULT_TRANSITION;
+    private Transition mExitTransition = null;
+    private Transition mReenterTransition = USE_DEFAULT_TRANSITION;
+    private Transition mSharedElementEnterTransition = null;
+    private Transition mSharedElementReturnTransition = USE_DEFAULT_TRANSITION;
+    private Boolean mAllowReturnTransitionOverlap;
+    private Boolean mAllowEnterTransitionOverlap;
+
+    SharedElementCallback mEnterTransitionCallback = SharedElementCallback.NULL_CALLBACK;
+    SharedElementCallback mExitTransitionCallback = SharedElementCallback.NULL_CALLBACK;
+
     /**
      * State information that has been retrieved from a fragment instance
      * through {@link FragmentManager#saveFragmentInstanceState(Fragment)
@@ -543,7 +561,7 @@
      * will not be called when the fragment is re-instantiated; instead,
      * arguments can be supplied by the caller with {@link #setArguments}
      * and later retrieved by the Fragment with {@link #getArguments}.
-     * 
+     *
      * <p>Applications should generally not implement a constructor.  The
      * first place application code an run where the fragment is ready to
      * be used is in {@link #onAttach(Activity)}, the point where the fragment
@@ -609,7 +627,7 @@
                     + " empty constructor that is public", e);
         }
     }
-    
+
     final void restoreViewState(Bundle savedInstanceState) {
         if (mSavedViewState != null) {
             mView.restoreHierarchyState(mSavedViewState);
@@ -649,7 +667,7 @@
     @Override final public int hashCode() {
         return super.hashCode();
     }
-    
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder(128);
@@ -669,7 +687,7 @@
         sb.append('}');
         return sb.toString();
     }
-    
+
     /**
      * Return the identifier this fragment is known by.  This is either
      * the android:id value supplied in a layout or the container view ID
@@ -678,14 +696,14 @@
     final public int getId() {
         return mFragmentId;
     }
-    
+
     /**
      * Get the tag name of the fragment, if specified.
      */
     final public String getTag() {
         return mTag;
     }
-    
+
     /**
      * Supply the construction arguments for this fragment.  This can only
      * be called before the fragment has been attached to its activity; that
@@ -760,7 +778,7 @@
     final public Activity getActivity() {
         return mActivity;
     }
-    
+
     /**
      * Return <code>getActivity().getResources()</code>.
      */
@@ -770,7 +788,7 @@
         }
         return mActivity.getResources();
     }
-    
+
     /**
      * Return a localized, styled CharSequence from the application's package's
      * default string table.
@@ -870,7 +888,7 @@
     final public boolean isRemoving() {
         return mRemoving;
     }
-    
+
     /**
      * Return true if the layout is included as part of an activity view
      * hierarchy via the &lt;fragment&gt; tag.  This will always be true when
@@ -889,7 +907,7 @@
     final public boolean isResumed() {
         return mResumed;
     }
-    
+
     /**
      * Return true if the fragment is currently visible to the user.  This means
      * it: (1) has been added, (2) has its view attached to the window, and 
@@ -899,7 +917,7 @@
         return isAdded() && !isHidden() && mView != null
                 && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE;
     }
-    
+
     /**
      * Return true if the fragment has been hidden.  By default fragments
      * are shown.  You can find out about changes to this state with
@@ -910,7 +928,7 @@
     final public boolean isHidden() {
         return mHidden;
     }
-    
+
     /**
      * Called when the hidden state (as returned by {@link #isHidden()} of
      * the fragment has changed.  Fragments start out not hidden; this will
@@ -920,7 +938,7 @@
      */
     public void onHiddenChanged(boolean hidden) {
     }
-    
+
     /**
      * Control whether a fragment instance is retained across Activity
      * re-creation (such as from a configuration change).  This can only
@@ -942,16 +960,16 @@
         }
         mRetainInstance = retain;
     }
-    
+
     final public boolean getRetainInstance() {
         return mRetainInstance;
     }
-    
+
     /**
      * Report that this fragment would like to participate in populating
      * the options menu by receiving a call to {@link #onCreateOptionsMenu}
      * and related methods.
-     * 
+     *
      * @param hasMenu If true, the fragment has menu items to contribute.
      */
     public void setHasOptionsMenu(boolean hasMenu) {
@@ -1034,7 +1052,7 @@
     public void startActivity(Intent intent) {
         startActivity(intent, null);
     }
-    
+
     /**
      * Call {@link Activity#startActivity(Intent, Bundle)} from the fragment's
      * containing Activity.
@@ -1081,13 +1099,13 @@
             mActivity.startActivityFromFragment(this, intent, requestCode, options);
         }
     }
-    
+
     /**
      * Receive the result from a previous call to
      * {@link #startActivityForResult(Intent, int)}.  This follows the
      * related Activity API as described there in
      * {@link Activity#onActivityResult(int, int, Intent)}.
-     * 
+     *
      * @param requestCode The integer request code originally supplied to
      *                    startActivityForResult(), allowing you to identify who this
      *                    result came from.
@@ -1098,7 +1116,7 @@
      */
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
     }
-    
+
     /**
      * @hide Hack so that DialogFragment can make its Dialog before creating
      * its views, and the view construction can use the dialog's context for
@@ -1115,7 +1133,7 @@
             return mActivity.getLayoutInflater();
         }
     }
-    
+
     /**
      * @deprecated Use {@link #onInflate(Activity, AttributeSet, Bundle)} instead.
      */
@@ -1131,7 +1149,7 @@
      * tag in a layout file.  Note this is <em>before</em> the fragment's
      * {@link #onAttach(Activity)} has been called; all you should do here is
      * parse the attributes and save them away.
-     * 
+     *
      * <p>This is called every time the fragment is inflated, even if it is
      * being inflated into a new instance with saved state.  It typically makes
      * sense to re-parse the parameters each time, to allow them to change with
@@ -1169,8 +1187,33 @@
     public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
         onInflate(attrs, savedInstanceState);
         mCalled = true;
+
+        TypedArray a = activity.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.Fragment);
+        mEnterTransition = loadTransition(activity, a, mEnterTransition, null,
+                com.android.internal.R.styleable.Fragment_fragmentEnterTransition);
+        mReturnTransition = loadTransition(activity, a, mReturnTransition, USE_DEFAULT_TRANSITION,
+                com.android.internal.R.styleable.Fragment_fragmentReturnTransition);
+        mExitTransition = loadTransition(activity, a, mExitTransition, null,
+                com.android.internal.R.styleable.Fragment_fragmentExitTransition);
+        mReenterTransition = loadTransition(activity, a, mReenterTransition, USE_DEFAULT_TRANSITION,
+                com.android.internal.R.styleable.Fragment_fragmentReenterTransition);
+        mSharedElementEnterTransition = loadTransition(activity, a, mSharedElementEnterTransition,
+                null, com.android.internal.R.styleable.Fragment_fragmentSharedElementEnterTransition);
+        mSharedElementReturnTransition = loadTransition(activity, a, mSharedElementReturnTransition,
+                USE_DEFAULT_TRANSITION,
+                com.android.internal.R.styleable.Fragment_fragmentSharedElementReturnTransition);
+        if (mAllowEnterTransitionOverlap == null) {
+            mAllowEnterTransitionOverlap = a.getBoolean(
+                    com.android.internal.R.styleable.Fragment_fragmentAllowEnterTransitionOverlap, true);
+        }
+        if (mAllowReturnTransitionOverlap == null) {
+            mAllowReturnTransitionOverlap = a.getBoolean(
+                    com.android.internal.R.styleable.Fragment_fragmentAllowReturnTransitionOverlap, true);
+        }
+        a.recycle();
     }
-    
+
     /**
      * Called when a fragment is first attached to its activity.
      * {@link #onCreate(Bundle)} will be called after this.
@@ -1178,25 +1221,25 @@
     public void onAttach(Activity activity) {
         mCalled = true;
     }
-    
+
     /**
      * Called when a fragment loads an animation.
      */
     public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
         return null;
     }
-    
+
     /**
      * Called to do initial creation of a fragment.  This is called after
      * {@link #onAttach(Activity)} and before
      * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
-     * 
+     *
      * <p>Note that this can be called while the fragment's activity is
      * still in the process of being created.  As such, you can not rely
      * on things like the activity's content view hierarchy being initialized
      * at this point.  If you want to do work once the activity itself is
      * created, see {@link #onActivityCreated(Bundle)}.
-     * 
+     *
      * @param savedInstanceState If the fragment is being re-created from
      * a previous saved state, this is the state.
      */
@@ -1209,10 +1252,10 @@
      * This is optional, and non-graphical fragments can return null (which
      * is the default implementation).  This will be called between
      * {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}.
-     * 
+     *
      * <p>If you return a View from here, you will later be called in
      * {@link #onDestroyView} when the view is being released.
-     * 
+     *
      * @param inflater The LayoutInflater object that can be used to inflate
      * any views in the fragment,
      * @param container If non-null, this is the parent view that the fragment's
@@ -1220,7 +1263,7 @@
      * but this can be used to generate the LayoutParams of the view.
      * @param savedInstanceState If non-null, this fragment is being re-constructed
      * from a previous saved state as given here.
-     * 
+     *
      * @return Return the View for the fragment's UI, or null.
      */
     @Nullable
@@ -1241,18 +1284,18 @@
      */
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
     }
-    
+
     /**
      * Get the root view for the fragment's layout (the one returned by {@link #onCreateView}),
      * if provided.
-     * 
+     *
      * @return The fragment's root view, or null if it has no layout.
      */
     @Nullable
     public View getView() {
         return mView;
     }
-    
+
     /**
      * Called when the fragment's activity has been created and this
      * fragment's view hierarchy instantiated.  It can be used to do final
@@ -1292,7 +1335,7 @@
      */
     public void onStart() {
         mCalled = true;
-        
+
         if (!mLoadersStarted) {
             mLoadersStarted = true;
             if (!mCheckedForLoaderManager) {
@@ -1304,7 +1347,7 @@
             }
         }
     }
-    
+
     /**
      * Called when the fragment is visible to the user and actively running.
      * This is generally
@@ -1314,7 +1357,7 @@
     public void onResume() {
         mCalled = true;
     }
-    
+
     /**
      * Called to ask the fragment to save its current dynamic state, so it
      * can later be reconstructed in a new instance of its process is
@@ -1336,11 +1379,11 @@
      */
     public void onSaveInstanceState(Bundle outState) {
     }
-    
+
     public void onConfigurationChanged(Configuration newConfig) {
         mCalled = true;
     }
-    
+
     /**
      * Called when the Fragment is no longer resumed.  This is generally
      * tied to {@link Activity#onPause() Activity.onPause} of the containing
@@ -1349,7 +1392,7 @@
     public void onPause() {
         mCalled = true;
     }
-    
+
     /**
      * Called when the Fragment is no longer started.  This is generally
      * tied to {@link Activity#onStop() Activity.onStop} of the containing
@@ -1358,11 +1401,11 @@
     public void onStop() {
         mCalled = true;
     }
-    
+
     public void onLowMemory() {
         mCalled = true;
     }
-    
+
     public void onTrimMemory(int level) {
         mCalled = true;
     }
@@ -1379,7 +1422,7 @@
     public void onDestroyView() {
         mCalled = true;
     }
-    
+
     /**
      * Called when the fragment is no longer in use.  This is called
      * after {@link #onStop()} and before {@link #onDetach()}.
@@ -1434,16 +1477,16 @@
     public void onDetach() {
         mCalled = true;
     }
-    
+
     /**
      * Initialize the contents of the Activity's standard options menu.  You
      * should place your menu items in to <var>menu</var>.  For this method
      * to be called, you must have first called {@link #setHasOptionsMenu}.  See
      * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu}
      * for more information.
-     * 
+     *
      * @param menu The options menu in which you place your items.
-     * 
+     *
      * @see #setHasOptionsMenu
      * @see #onPrepareOptionsMenu
      * @see #onOptionsItemSelected
@@ -1458,10 +1501,10 @@
      * dynamically modify the contents.  See
      * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu}
      * for more information.
-     * 
+     *
      * @param menu The options menu as last shown or first initialized by
      *             onCreateOptionsMenu().
-     * 
+     *
      * @see #setHasOptionsMenu
      * @see #onCreateOptionsMenu
      */
@@ -1477,7 +1520,7 @@
      */
     public void onDestroyOptionsMenu() {
     }
-    
+
     /**
      * This hook is called whenever an item in your options menu is selected.
      * The default implementation simply returns false to have the normal
@@ -1485,15 +1528,15 @@
      * its Handler as appropriate).  You can use this method for any items
      * for which you would like to do processing without those other
      * facilities.
-     * 
+     *
      * <p>Derived classes should call through to the base class for it to
      * perform the default menu handling.
-     * 
+     *
      * @param item The menu item that was selected.
-     * 
+     *
      * @return boolean Return false to allow normal menu processing to
      *         proceed, true to consume it here.
-     * 
+     *
      * @see #onCreateOptionsMenu
      */
     public boolean onOptionsItemSelected(MenuItem item) {
@@ -1503,13 +1546,13 @@
     /**
      * This hook is called whenever the options menu is being closed (either by the user canceling
      * the menu with the back/menu button, or when an item is selected).
-     *  
+     *
      * @param menu The options menu as last shown or first initialized by
      *             onCreateOptionsMenu().
      */
     public void onOptionsMenuClosed(Menu menu) {
     }
-    
+
     /**
      * Called when a context menu for the {@code view} is about to be shown.
      * Unlike {@link #onCreateOptionsMenu}, this will be called every
@@ -1537,25 +1580,25 @@
      * {@link OnCreateContextMenuListener} on the view to this fragment, so
      * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be
      * called when it is time to show the context menu.
-     * 
+     *
      * @see #unregisterForContextMenu(View)
      * @param view The view that should show a context menu.
      */
     public void registerForContextMenu(View view) {
         view.setOnCreateContextMenuListener(this);
     }
-    
+
     /**
      * Prevents a context menu to be shown for the given view. This method will
      * remove the {@link OnCreateContextMenuListener} on the view.
-     * 
+     *
      * @see #registerForContextMenu(View)
      * @param view The view that should stop showing a context menu.
      */
     public void unregisterForContextMenu(View view) {
         view.setOnCreateContextMenuListener(null);
     }
-    
+
     /**
      * This hook is called whenever an item in a context menu is selected. The
      * default implementation simply returns false to have the normal processing
@@ -1568,7 +1611,7 @@
      * <p>
      * Derived classes should call through to the base class for it to perform
      * the default menu handling.
-     * 
+     *
      * @param item The context menu item that was selected.
      * @return boolean Return false to allow normal context menu processing to
      *         proceed, true to consume it here.
@@ -1576,7 +1619,284 @@
     public boolean onContextItemSelected(MenuItem item) {
         return false;
     }
-    
+
+    /**
+     * When custom transitions are used with Fragments, the enter transition callback
+     * is called when this Fragment is attached or detached when not popping the back stack.
+     *
+     * @param callback Used to manipulate the shared element transitions on this Fragment
+     *                 when added not as a pop from the back stack.
+     */
+    public void setEnterSharedElementTransitionCallback(SharedElementCallback callback) {
+        if (callback == null) {
+            callback = SharedElementCallback.NULL_CALLBACK;
+        }
+        mEnterTransitionCallback = callback;
+    }
+
+    /**
+     * When custom transitions are used with Fragments, the exit transition callback
+     * is called when this Fragment is attached or detached when popping the back stack.
+     *
+     * @param callback Used to manipulate the shared element transitions on this Fragment
+     *                 when added as a pop from the back stack.
+     */
+    public void setExitSharedElementTransitionCallback(SharedElementCallback callback) {
+        if (callback == null) {
+            callback = SharedElementCallback.NULL_CALLBACK;
+        }
+        mExitTransitionCallback = callback;
+    }
+
+    /**
+     * Sets the Transition that will be used to move Views into the initial scene. The entering
+     * Views will be those that are regular Views or ViewGroups that have
+     * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+     * {@link android.transition.Visibility} as entering is governed by changing visibility from
+     * {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null,
+     * entering Views will remain unaffected.
+     *
+     * @param transition The Transition to use to move Views into the initial Scene.
+     * @attr ref android.R.styleable#Fragment_fragmentEnterTransition
+     */
+    public void setEnterTransition(Transition transition) {
+        mEnterTransition = transition;
+    }
+
+    /**
+     * Returns the Transition that will be used to move Views into the initial scene. The entering
+     * Views will be those that are regular Views or ViewGroups that have
+     * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+     * {@link android.transition.Visibility} as entering is governed by changing visibility from
+     * {@link View#INVISIBLE} to {@link View#VISIBLE}.
+     *
+     * @return the Transition to use to move Views into the initial Scene.
+     * @attr ref android.R.styleable#Fragment_fragmentEnterTransition
+     */
+    public Transition getEnterTransition() {
+        return mEnterTransition;
+    }
+
+    /**
+     * Sets the Transition that will be used to move Views out of the scene when the Fragment is
+     * preparing to be removed, hidden, or detached because of popping the back stack. The exiting
+     * Views will be those that are regular Views or ViewGroups that have
+     * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+     * {@link android.transition.Visibility} as entering is governed by changing visibility from
+     * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null,
+     * entering Views will remain unaffected. If nothing is set, the default will be to
+     * use the same value as set in {@link #setEnterTransition(android.transition.Transition)}.
+     *
+     * @param transition The Transition to use to move Views out of the Scene when the Fragment
+     *                   is preparing to close.
+     * @attr ref android.R.styleable#Fragment_fragmentExitTransition
+     */
+    public void setReturnTransition(Transition transition) {
+        mReturnTransition = transition;
+    }
+
+    /**
+     * Returns the Transition that will be used to move Views out of the scene when the Fragment is
+     * preparing to be removed, hidden, or detached because of popping the back stack. The exiting
+     * Views will be those that are regular Views or ViewGroups that have
+     * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+     * {@link android.transition.Visibility} as entering is governed by changing visibility from
+     * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null,
+     * entering Views will remain unaffected.
+     *
+     * @return the Transition to use to move Views out of the Scene when the Fragment
+     *         is preparing to close.
+     * @attr ref android.R.styleable#Fragment_fragmentExitTransition
+     */
+    public Transition getReturnTransition() {
+        return mReturnTransition == USE_DEFAULT_TRANSITION ? getEnterTransition()
+                : mReturnTransition;
+    }
+
+    /**
+     * Sets the Transition that will be used to move Views out of the scene when the
+     * fragment is removed, hidden, or detached when not popping the back stack.
+     * The exiting Views will be those that are regular Views or ViewGroups that
+     * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+     * {@link android.transition.Visibility} as exiting is governed by changing visibility
+     * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
+     * remain unaffected.
+     *
+     * @param transition The Transition to use to move Views out of the Scene when the Fragment
+     *                   is being closed not due to popping the back stack.
+     * @attr ref android.R.styleable#Fragment_fragmentExitTransition
+     */
+    public void setExitTransition(Transition transition) {
+        mExitTransition = transition;
+    }
+
+    /**
+     * Returns the Transition that will be used to move Views out of the scene when the
+     * fragment is removed, hidden, or detached when not popping the back stack.
+     * The exiting Views will be those that are regular Views or ViewGroups that
+     * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+     * {@link android.transition.Visibility} as exiting is governed by changing visibility
+     * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
+     * remain unaffected.
+     *
+     * @return the Transition to use to move Views out of the Scene when the Fragment
+     *         is being closed not due to popping the back stack.
+     * @attr ref android.R.styleable#Fragment_fragmentExitTransition
+     */
+    public Transition getExitTransition() {
+        return mExitTransition;
+    }
+
+    /**
+     * Sets the Transition that will be used to move Views in to the scene when returning due
+     * to popping a back stack. The entering Views will be those that are regular Views
+     * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions
+     * will extend {@link android.transition.Visibility} as exiting is governed by changing
+     * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null,
+     * the views will remain unaffected. If nothing is set, the default will be to use the same
+     * transition as {@link #setExitTransition(android.transition.Transition)}.
+     *
+     * @param transition The Transition to use to move Views into the scene when reentering from a
+     *                   previously-started Activity.
+     * @attr ref android.R.styleable#Fragment_fragmentReenterTransition
+     */
+    public void setReenterTransition(Transition transition) {
+        mReenterTransition = transition;
+    }
+
+    /**
+     * Returns the Transition that will be used to move Views in to the scene when returning due
+     * to popping a back stack. The entering Views will be those that are regular Views
+     * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions
+     * will extend {@link android.transition.Visibility} as exiting is governed by changing
+     * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null,
+     * the views will remain unaffected. If nothing is set, the default will be to use the same
+     * transition as {@link #setExitTransition(android.transition.Transition)}.
+     *
+     * @return the Transition to use to move Views into the scene when reentering from a
+     *                   previously-started Activity.
+     * @attr ref android.R.styleable#Fragment_fragmentReenterTransition
+     */
+    public Transition getReenterTransition() {
+        return mReenterTransition == USE_DEFAULT_TRANSITION ? getExitTransition()
+                : mReenterTransition;
+    }
+
+    /**
+     * Sets the Transition that will be used for shared elements transferred into the content
+     * Scene. Typical Transitions will affect size and location, such as
+     * {@link android.transition.ChangeBounds}. A null
+     * value will cause transferred shared elements to blink to the final position.
+     *
+     * @param transition The Transition to use for shared elements transferred into the content
+     *                   Scene.
+     * @attr ref android.R.styleable#Fragment_fragmentSharedElementEnterTransition
+     */
+    public void setSharedElementEnterTransition(Transition transition) {
+        mSharedElementEnterTransition = transition;
+    }
+
+    /**
+     * Returns the Transition that will be used for shared elements transferred into the content
+     * Scene. Typical Transitions will affect size and location, such as
+     * {@link android.transition.ChangeBounds}. A null
+     * value will cause transferred shared elements to blink to the final position.
+     *
+     * @return The Transition to use for shared elements transferred into the content
+     *                   Scene.
+     * @attr ref android.R.styleable#Fragment_fragmentSharedElementEnterTransition
+     */
+    public Transition getSharedElementEnterTransition() {
+        return mSharedElementEnterTransition;
+    }
+
+    /**
+     * Sets the Transition that will be used for shared elements transferred back during a
+     * pop of the back stack. This Transition acts in the leaving Fragment.
+     * Typical Transitions will affect size and location, such as
+     * {@link android.transition.ChangeBounds}. A null
+     * value will cause transferred shared elements to blink to the final position.
+     * If no value is set, the default will be to use the same value as
+     * {@link #setSharedElementEnterTransition(android.transition.Transition)}.
+     *
+     * @param transition The Transition to use for shared elements transferred out of the content
+     *                   Scene.
+     * @attr ref android.R.styleable#Fragment_fragmentSharedElementReturnTransition
+     */
+    public void setSharedElementReturnTransition(Transition transition) {
+        mSharedElementReturnTransition = transition;
+    }
+
+    /**
+     * Return the Transition that will be used for shared elements transferred back during a
+     * pop of the back stack. This Transition acts in the leaving Fragment.
+     * Typical Transitions will affect size and location, such as
+     * {@link android.transition.ChangeBounds}. A null
+     * value will cause transferred shared elements to blink to the final position.
+     * If no value is set, the default will be to use the same value as
+     * {@link #setSharedElementEnterTransition(android.transition.Transition)}.
+     *
+     * @return The Transition to use for shared elements transferred out of the content
+     *                   Scene.
+     * @attr ref android.R.styleable#Fragment_fragmentSharedElementReturnTransition
+     */
+    public Transition getSharedElementReturnTransition() {
+        return mSharedElementReturnTransition == USE_DEFAULT_TRANSITION ?
+                getSharedElementEnterTransition() : mSharedElementReturnTransition;
+    }
+
+    /**
+     * Sets whether the the exit transition and enter transition overlap or not.
+     * When true, the enter transition will start as soon as possible. When false, the
+     * enter transition will wait until the exit transition completes before starting.
+     *
+     * @param allow true to start the enter transition when possible or false to
+     *              wait until the exiting transition completes.
+     * @attr ref android.R.styleable#Fragment_fragmentAllowEnterTransitionOverlap
+     */
+    public void setAllowEnterTransitionOverlap(boolean allow) {
+        mAllowEnterTransitionOverlap = allow;
+    }
+
+    /**
+     * Returns whether the the exit transition and enter transition overlap or not.
+     * When true, the enter transition will start as soon as possible. When false, the
+     * enter transition will wait until the exit transition completes before starting.
+     *
+     * @return true when the enter transition should start as soon as possible or false to
+     * when it should wait until the exiting transition completes.
+     * @attr ref android.R.styleable#Fragment_fragmentAllowEnterTransitionOverlap
+     */
+    public boolean getAllowEnterTransitionOverlap() {
+        return (mAllowEnterTransitionOverlap == null) ? true : mAllowEnterTransitionOverlap;
+    }
+
+    /**
+     * Sets whether the the return transition and reenter transition overlap or not.
+     * When true, the reenter transition will start as soon as possible. When false, the
+     * reenter transition will wait until the return transition completes before starting.
+     *
+     * @param allow true to start the reenter transition when possible or false to wait until the
+     *              return transition completes.
+     * @attr ref android.R.styleable#Fragment_fragmentAllowReturnTransitionOverlap
+     */
+    public void setAllowReturnTransitionOverlap(boolean allow) {
+        mAllowReturnTransitionOverlap = allow;
+    }
+
+    /**
+     * Returns whether the the return transition and reenter transition overlap or not.
+     * When true, the reenter transition will start as soon as possible. When false, the
+     * reenter transition will wait until the return transition completes before starting.
+     *
+     * @return true to start the reenter transition when possible or false to wait until the
+     *         return transition completes.
+     * @attr ref android.R.styleable#Fragment_fragmentAllowReturnTransitionOverlap
+     */
+    public boolean getAllowReturnTransitionOverlap() {
+        return (mAllowReturnTransitionOverlap == null) ? true : mAllowReturnTransitionOverlap;
+    }
+
     /**
      * Print the Fragments's state into the given stream.
      *
@@ -1588,53 +1908,53 @@
      */
     public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
         writer.print(prefix); writer.print("mFragmentId=#");
-                writer.print(Integer.toHexString(mFragmentId));
-                writer.print(" mContainerId=#");
-                writer.print(Integer.toHexString(mContainerId));
-                writer.print(" mTag="); writer.println(mTag);
+        writer.print(Integer.toHexString(mFragmentId));
+        writer.print(" mContainerId=#");
+        writer.print(Integer.toHexString(mContainerId));
+        writer.print(" mTag="); writer.println(mTag);
         writer.print(prefix); writer.print("mState="); writer.print(mState);
-                writer.print(" mIndex="); writer.print(mIndex);
-                writer.print(" mWho="); writer.print(mWho);
-                writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
+        writer.print(" mIndex="); writer.print(mIndex);
+        writer.print(" mWho="); writer.print(mWho);
+        writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
         writer.print(prefix); writer.print("mAdded="); writer.print(mAdded);
-                writer.print(" mRemoving="); writer.print(mRemoving);
-                writer.print(" mResumed="); writer.print(mResumed);
-                writer.print(" mFromLayout="); writer.print(mFromLayout);
-                writer.print(" mInLayout="); writer.println(mInLayout);
+        writer.print(" mRemoving="); writer.print(mRemoving);
+        writer.print(" mResumed="); writer.print(mResumed);
+        writer.print(" mFromLayout="); writer.print(mFromLayout);
+        writer.print(" mInLayout="); writer.println(mInLayout);
         writer.print(prefix); writer.print("mHidden="); writer.print(mHidden);
-                writer.print(" mDetached="); writer.print(mDetached);
-                writer.print(" mMenuVisible="); writer.print(mMenuVisible);
-                writer.print(" mHasMenu="); writer.println(mHasMenu);
+        writer.print(" mDetached="); writer.print(mDetached);
+        writer.print(" mMenuVisible="); writer.print(mMenuVisible);
+        writer.print(" mHasMenu="); writer.println(mHasMenu);
         writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance);
-                writer.print(" mRetaining="); writer.print(mRetaining);
-                writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint);
+        writer.print(" mRetaining="); writer.print(mRetaining);
+        writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint);
         if (mFragmentManager != null) {
             writer.print(prefix); writer.print("mFragmentManager=");
-                    writer.println(mFragmentManager);
+            writer.println(mFragmentManager);
         }
         if (mActivity != null) {
             writer.print(prefix); writer.print("mActivity=");
-                    writer.println(mActivity);
+            writer.println(mActivity);
         }
         if (mParentFragment != null) {
             writer.print(prefix); writer.print("mParentFragment=");
-                    writer.println(mParentFragment);
+            writer.println(mParentFragment);
         }
         if (mArguments != null) {
             writer.print(prefix); writer.print("mArguments="); writer.println(mArguments);
         }
         if (mSavedFragmentState != null) {
             writer.print(prefix); writer.print("mSavedFragmentState=");
-                    writer.println(mSavedFragmentState);
+            writer.println(mSavedFragmentState);
         }
         if (mSavedViewState != null) {
             writer.print(prefix); writer.print("mSavedViewState=");
-                    writer.println(mSavedViewState);
+            writer.println(mSavedViewState);
         }
         if (mTarget != null) {
             writer.print(prefix); writer.print("mTarget="); writer.print(mTarget);
-                    writer.print(" mTargetRequestCode=");
-                    writer.println(mTargetRequestCode);
+            writer.print(" mTargetRequestCode=");
+            writer.println(mTargetRequestCode);
         }
         if (mNextAnim != 0) {
             writer.print(prefix); writer.print("mNextAnim="); writer.println(mNextAnim);
@@ -1648,7 +1968,7 @@
         if (mAnimatingAway != null) {
             writer.print(prefix); writer.print("mAnimatingAway="); writer.println(mAnimatingAway);
             writer.print(prefix); writer.print("mStateAfterAnimating=");
-                    writer.println(mStateAfterAnimating);
+            writer.println(mStateAfterAnimating);
         }
         if (mLoaderManager != null) {
             writer.print(prefix); writer.println("Loader Manager:");
@@ -1886,7 +2206,7 @@
             throw new SuperNotCalledException("Fragment " + this
                     + " did not call through to super.onStop()");
         }
-        
+
         if (mLoadersStarted) {
             mLoadersStarted = false;
             if (!mCheckedForLoaderManager) {
@@ -1929,4 +2249,23 @@
                     + " did not call through to super.onDestroy()");
         }
     }
+
+    private static Transition loadTransition(Context context, TypedArray typedArray,
+            Transition currentValue, Transition defaultValue, int id) {
+        if (currentValue != defaultValue) {
+            return currentValue;
+        }
+        int transitionId = typedArray.getResourceId(id, 0);
+        Transition transition = defaultValue;
+        if (transitionId != 0 && transitionId != com.android.internal.R.transition.no_transition) {
+            TransitionInflater inflater = TransitionInflater.from(context);
+            transition = inflater.inflateTransition(transitionId);
+            if (transition instanceof TransitionSet &&
+                    ((TransitionSet)transition).getTransitionCount() == 0) {
+                transition = null;
+            }
+        }
+        return transition;
+    }
+
 }
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 1df1d42..ef69fdd 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1497,7 +1497,10 @@
                 return false;
             }
             final BackStackRecord bss = mBackStack.remove(last);
-            bss.popFromBackStack(true, null);
+            SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
+            SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
+            bss.calculateBackFragments(firstOutFragments, lastInFragments);
+            bss.popFromBackStack(true, null, firstOutFragments, lastInFragments);
             reportBackStackChanged();
         } else {
             int index = -1;
@@ -1541,10 +1544,16 @@
                 states.add(mBackStack.remove(i));
             }
             final int LAST = states.size()-1;
+            SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
+            SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
+            for (int i=0; i<=LAST; i++) {
+                states.get(i).calculateBackFragments(firstOutFragments, lastInFragments);
+            }
             BackStackRecord.TransitionState state = null;
             for (int i=0; i<=LAST; i++) {
                 if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
-                state = states.get(i).popFromBackStack(i == LAST, state);
+                state = states.get(i).popFromBackStack(i == LAST, state,
+                        firstOutFragments, lastInFragments);
             }
             reportBackStackChanged();
         }
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 1077bac..25cd3cc 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -172,19 +172,16 @@
     public abstract FragmentTransaction setTransition(int transit);
 
     /**
-     * Set a {@link android.transition.Transition} resource id to use with this transaction.
-     * <var>transitionId</var> will be played for fragments when going forward and when popping
-     * the back stack.
-     * @param sceneRootId The ID of the element acting as the scene root for the transition.
-     *                    This should be a ViewGroup containing all Fragments in the transaction.
-     * @param transitionId The resource ID for the Transition used during the Fragment transaction.
+     * TODO: remove from API
+     * @hide
      */
-    public abstract FragmentTransaction setCustomTransition(int sceneRootId, int transitionId);
+    public FragmentTransaction setCustomTransition(int sceneRootId, int transitionId) {
+        return this;
+    }
 
     /**
-     * Used with {@link #setCustomTransition(int, int)} to map a View from a removed or hidden
-     * Fragment to a View from a shown or added Fragment.
-     * <var>sharedElement</var> must have a unique transitionName in the View hierarchy.
+     * Used with to map a View from a removed or hidden Fragment to a View from a shown
+     * or added Fragment.
      * @param sharedElement A View in a disappearing Fragment to match with a View in an
      *                      appearing Fragment.
      * @param name The transitionName for a View in an appearing Fragment to match to the shared
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index dbd180f..7d4512b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -48,6 +48,9 @@
     void setPackagePriority(String pkg, int uid, int priority);
     int getPackagePriority(String pkg, int uid);
 
+    void setPackageVisibilityOverride(String pkg, int uid, int visibility);
+    int getPackageVisibilityOverride(String pkg, int uid);
+
     // TODO: Remove this when callers have been migrated to the equivalent
     // INotificationListener method.
     StatusBarNotification[] getActiveNotifications(String callingPkg);
@@ -68,6 +71,7 @@
 
     ComponentName getEffectsSuppressor();
     boolean matchesCallFilter(in Bundle extras);
+    boolean matchesCallFilterAsUser(in Bundle extras, int userId);
 
     ZenModeConfig getZenModeConfig();
     boolean setZenModeConfig(in ZenModeConfig config);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 800734a..1083943 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -37,7 +38,6 @@
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.MathUtils;
@@ -129,6 +129,14 @@
     public static final int DEFAULT_LIGHTS = 4;
 
     /**
+     * Maximum length of CharSequences accepted by Builder and friends.
+     *
+     * <p>
+     * Avoids spamming the system with overly large strings such as full e-mails.
+     */
+    private static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024;
+
+    /**
      * A timestamp related to this notification, in milliseconds since the epoch.
      *
      * Default value: {@link System#currentTimeMillis() Now}.
@@ -816,13 +824,6 @@
     public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
 
     /**
-     * {@link #extras} key: the user that built the notification.
-     *
-     * @hide
-     */
-    public static final String EXTRA_ORIGINATING_USERID = "android.originatingUserId";
-
-    /**
      * Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be
      * displayed in the heads up space.
      *
@@ -1423,6 +1424,7 @@
             extras.remove(Notification.EXTRA_LARGE_ICON);
             extras.remove(Notification.EXTRA_LARGE_ICON_BIG);
             extras.remove(Notification.EXTRA_PICTURE);
+            extras.remove(Notification.EXTRA_BIG_TEXT);
             // Prevent light notifications from being rebuilt.
             extras.remove(Builder.EXTRA_NEEDS_REBUILD);
         }
@@ -1434,6 +1436,10 @@
      * @hide
      */
     public static CharSequence safeCharSequence(CharSequence cs) {
+        if (cs == null) return cs;
+        if (cs.length() > MAX_CHARSEQUENCE_LENGTH) {
+            cs = cs.subSequence(0, MAX_CHARSEQUENCE_LENGTH);
+        }
         if (cs instanceof Parcelable) {
             Log.e(TAG, "warning: " + cs.getClass().getCanonicalName()
                     + " instance is a custom Parcelable and not allowed in Notification");
@@ -1800,10 +1806,12 @@
                 = "android.rebuild.hudViewActionCount";
 
         /**
-         * The package name of the context used to create the notification via a Builder.
+         * The ApplicationInfo of the package that created the notification, used to create
+         * a context to rebuild the notification via a Builder.
+         * @hide
          */
-        private static final String EXTRA_REBUILD_CONTEXT_PACKAGE =
-                "android.rebuild.contextPackage";
+        private static final String EXTRA_REBUILD_CONTEXT_APPLICATION_INFO =
+                "android.rebuild.applicationInfo";
 
         // Whether to enable stripping (at post time) & rebuilding (at listener receive time) of
         // memory intensive resources.
@@ -1854,11 +1862,6 @@
         private int mColor = COLOR_DEFAULT;
 
         /**
-         * The user that built the notification originally.
-         */
-        private int mOriginatingUserId;
-
-        /**
          * Contains extras related to rebuilding during the build phase.
          */
         private Bundle mRebuildBundle = new Bundle();
@@ -1916,7 +1919,7 @@
             mPeople = new ArrayList<String>();
 
             mColorUtil = context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.L ?
-                    NotificationColorUtil.getInstance() : null;
+                    NotificationColorUtil.getInstance(mContext) : null;
         }
 
         /**
@@ -2577,8 +2580,8 @@
         private Drawable getProfileBadgeDrawable() {
             // Note: This assumes that the current user can read the profile badge of the
             // originating user.
-            UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-            return userManager.getBadgeForUser(new UserHandle(mOriginatingUserId), 0);
+            return mContext.getPackageManager().getUserBadgeForDensity(
+                    new UserHandle(mContext.getUserId()), 0);
         }
 
         private Bitmap getProfileBadge() {
@@ -2657,8 +2660,7 @@
          * @param hasProgress whether the progress bar should be shown and set
          */
         private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
-            RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(),
-                    mOriginatingUserId, resId);
+            RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
 
             resetStandardTemplate(contentView);
 
@@ -2889,7 +2891,7 @@
         }
 
         private void processLegacyAction(Action action, RemoteViews button) {
-            if (!isLegacy() || mColorUtil.isGrayscale(mContext, action.icon)) {
+            if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, action.icon)) {
                 button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0,
                         mContext.getResources().getColor(R.color.notification_action_color_filter),
                         PorterDuff.Mode.MULTIPLY);
@@ -2908,7 +2910,7 @@
          * Apply any necessary background to smallIcons being used in the largeIcon spot.
          */
         private void processSmallIconAsLarge(int largeIconId, RemoteViews contentView) {
-            if (!isLegacy() || mColorUtil.isGrayscale(mContext, largeIconId)) {
+            if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, largeIconId)) {
                 applyLargeIconBackground(contentView);
             }
         }
@@ -2919,7 +2921,7 @@
          */
         // TODO: also check bounds, transparency, that sort of thing.
         private void processLargeLegacyIcon(Bitmap largeIcon, RemoteViews contentView) {
-            if (isLegacy() && mColorUtil.isGrayscale(largeIcon)) {
+            if (isLegacy() && mColorUtil.isGrayscaleIcon(largeIcon)) {
                 applyLargeIconBackground(contentView);
             } else {
                 removeLargeIconBackground(contentView);
@@ -2955,7 +2957,7 @@
          */
         private void processSmallRightIcon(int smallIconDrawableId,
                 RemoteViews contentView) {
-            if (!isLegacy() || mColorUtil.isGrayscale(mContext, smallIconDrawableId)) {
+            if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, smallIconDrawableId)) {
                 contentView.setDrawableParameters(R.id.right_icon, false, -1,
                         0xFFFFFFFF,
                         PorterDuff.Mode.SRC_ATOP, -1);
@@ -3050,8 +3052,8 @@
          */
         public void populateExtras(Bundle extras) {
             // Store original information used in the construction of this object
-            extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId);
-            extras.putString(EXTRA_REBUILD_CONTEXT_PACKAGE, mContext.getPackageName());
+            extras.putParcelable(EXTRA_REBUILD_CONTEXT_APPLICATION_INFO,
+                    mContext.getApplicationInfo());
             extras.putCharSequence(EXTRA_TITLE, mContentTitle);
             extras.putCharSequence(EXTRA_TEXT, mContentText);
             extras.putCharSequence(EXTRA_SUB_TEXT, mSubText);
@@ -3139,13 +3141,14 @@
             extras.remove(EXTRA_NEEDS_REBUILD);
 
             // Re-create notification context so we can access app resources.
-            String packageName = extras.getString(EXTRA_REBUILD_CONTEXT_PACKAGE);
+            ApplicationInfo applicationInfo = extras.getParcelable(
+                    EXTRA_REBUILD_CONTEXT_APPLICATION_INFO);
             Context builderContext;
             try {
-                builderContext = context.createPackageContext(packageName,
+                builderContext = context.createApplicationContext(applicationInfo,
                         Context.CONTEXT_RESTRICTED);
             } catch (NameNotFoundException e) {
-                Log.e(TAG, "Package name " + packageName + " not found");
+                Log.e(TAG, "ApplicationInfo " + applicationInfo + " not found");
                 builderContext = context;  // try with our context
             }
 
@@ -3280,7 +3283,6 @@
 
             // Extras.
             Bundle extras = n.extras;
-            mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID);
             mContentTitle = extras.getCharSequence(EXTRA_TITLE);
             mContentText = extras.getCharSequence(EXTRA_TEXT);
             mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
@@ -3313,7 +3315,6 @@
          * object.
          */
         public Notification build() {
-            mOriginatingUserId = mContext.getUserId();
             mHasThreeLines = hasThreeLines();
 
             Notification n = buildUnstyled();
@@ -4813,8 +4814,8 @@
             super(parcel);
         }
 
-        public BuilderRemoteViews(String packageName, int userId, int layoutId) {
-            super(packageName, userId, layoutId);
+        public BuilderRemoteViews(ApplicationInfo appInfo, int layoutId) {
+            super(appInfo, layoutId);
         }
 
         @Override
diff --git a/core/java/android/app/SharedElementListener.java b/core/java/android/app/SharedElementCallback.java
similarity index 64%
rename from core/java/android/app/SharedElementListener.java
rename to core/java/android/app/SharedElementCallback.java
index f36d05f..82d8e5b 100644
--- a/core/java/android/app/SharedElementListener.java
+++ b/core/java/android/app/SharedElementCallback.java
@@ -22,7 +22,6 @@
 import android.graphics.Matrix;
 import android.graphics.RectF;
 import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
 import android.os.Parcelable;
 import android.view.View;
 
@@ -31,28 +30,23 @@
 
 /**
  * Listener provided in
- * {@link Activity#setEnterSharedElementListener(SharedElementListener)} and
- * {@link Activity#setExitSharedElementListener(SharedElementListener)}
- * to monitor the Activity transitions. The events can be used to customize Activity
- * Transition behavior.
+ * {@link Activity#setEnterSharedElementCallback(SharedElementCallback)} and
+ * {@link Activity#setExitSharedElementCallback(SharedElementCallback)} as well as
+ * {@link Fragment#setEnterSharedElementTransitionCallback(SharedElementCallback)} and
+ * {@link Fragment#setExitSharedElementTransitionCallback(SharedElementCallback)}
+ * to monitor the Shared element transitions. The events can be used to customize Activity
+ * and Fragment Transition behavior.
  */
-public abstract class SharedElementListener {
+public abstract class SharedElementCallback {
     private Matrix mTempMatrix;
 
-    static final SharedElementListener NULL_LISTENER = new SharedElementListener() {
+    static final SharedElementCallback NULL_CALLBACK = new SharedElementCallback() {
     };
 
     /**
-     * Called to allow the listener to customize the start state of the shared element when
-     * transferring in shared element state.
-     * <p>
-     *     The shared element will start at the size and position of the shared element
-     *     in the launching Activity or Fragment. It will also transfer ImageView scaleType
-     *     and imageMatrix if the shared elements in the calling and called Activities are
-     *     ImageViews. Some applications may want to make additional changes, such as
-     *     changing the clip bounds, scaling, or rotation if the shared element end state
-     *     does not map well to the start state.
-     * </p>
+     * Called immediately after the start state is set for the shared element.
+     * The shared element will start at the size and position of the shared element
+     * in the launching Activity or Fragment.
      *
      * @param sharedElementNames The names of the shared elements that were accepted into
      *                           the View hierarchy.
@@ -60,20 +54,21 @@
      * @param sharedElementSnapshots The Views containing snap shots of the shared element
      *                               from the launching Window. These elements will not
      *                               be part of the scene, but will be positioned relative
-     *                               to the Window decor View.
+     *                               to the Window decor View. This list is null for Fragment
+     *                               Transitions.
      */
-    public void setSharedElementStart(List<String> sharedElementNames,
+    public void onSharedElementStart(List<String> sharedElementNames,
             List<View> sharedElements, List<View> sharedElementSnapshots) {}
 
     /**
-     * Called to allow the listener to customize the end state of the shared element when
-     * transferring in shared element state.
+     * Called after the end state is set for the shared element, but before the end state
+     * is captured by the shared element transition.
      * <p>
      *     Any customization done in
-     *     {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)}
+     *     {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)}
      *     may need to be modified to the final state of the shared element if it is not
      *     automatically corrected by layout. For example, rotation or scale will not
-     *     be affected by layout and if changed in {@link #setSharedElementStart(java.util.List,
+     *     be affected by layout and if changed in {@link #onSharedElementStart(java.util.List,
      *     java.util.List, java.util.List)}, it will also have to be set here again to correct
      *     the end state.
      * </p>
@@ -84,24 +79,27 @@
      * @param sharedElementSnapshots The Views containing snap shots of the shared element
      *                               from the launching Window. These elements will not
      *                               be part of the scene, but will be positioned relative
-     *                               to the Window decor View.
+     *                               to the Window decor View. This list will be null for
+     *                               Fragment Transitions.
      */
-    public void setSharedElementEnd(List<String> sharedElementNames,
+    public void onSharedElementEnd(List<String> sharedElementNames,
             List<View> sharedElements, List<View> sharedElementSnapshots) {}
 
     /**
-     * Called after {@link #remapSharedElements(java.util.List, java.util.Map)} when
+     * Called after {@link #onMapSharedElements(java.util.List, java.util.Map)} when
      * transferring shared elements in. Any shared elements that have no mapping will be in
      * <var>rejectedSharedElements</var>. The elements remaining in
      * <var>rejectedSharedElements</var> will be transitioned out of the Scene. If a
      * View is removed from <var>rejectedSharedElements</var>, it must be handled by the
-     * <code>SharedElementListener</code>.
+     * <code>SharedElementCallback</code>.
      * <p>
      * Views in rejectedSharedElements will have their position and size set to the
      * position of the calling shared element, relative to the Window decor View and contain
      * snapshots of the View from the calling Activity or Fragment. This
      * view may be safely added to the decor View's overlay to remain in position.
      * </p>
+     * <p>This method is not called for Fragment Transitions. All rejected shared elements
+     * will be handled by the exit transition.</p>
      *
      * @param rejectedSharedElements Views containing visual information of shared elements
      *                               that are not part of the entering scene. These Views
@@ -109,25 +107,27 @@
      *                               View removed from this list will not be transitioned
      *                               automatically.
      */
-    public void handleRejectedSharedElements(List<View> rejectedSharedElements) {}
+    public void onRejectSharedElements(List<View> rejectedSharedElements) {}
 
     /**
-     * Lets the ActivityTransitionListener adjust the mapping of shared element names to
+     * Lets the SharedElementCallback adjust the mapping of shared element names to
      * Views.
      *
      * @param names The names of all shared elements transferred from the calling Activity
-     *              to the started Activity.
+     *              or Fragment in the order they were provided.
      * @param sharedElements The mapping of shared element names to Views. The best guess
      *                       will be filled into sharedElements based on the transitionNames.
      */
-    public void remapSharedElements(List<String> names, Map<String, View> sharedElements) {}
+    public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {}
 
     /**
      * Creates a snapshot of a shared element to be used by the remote Activity and reconstituted
-     * with {@link #createSnapshotView(android.content.Context, android.os.Parcelable)}. A
+     * with {@link #onCreateSnapshotView(android.content.Context, android.os.Parcelable)}. A
      * null return value will mean that the remote Activity will have a null snapshot View in
-     * {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)} and
-     * {@link #setSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
+     * {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} and
+     * {@link #onSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
+     *
+     * <p>This is not called for Fragment Transitions.</p>
      *
      * @param sharedElement The shared element View to create a snapshot for.
      * @param viewToGlobalMatrix A matrix containing a transform from the view to the screen
@@ -135,11 +135,11 @@
      * @param screenBounds The bounds of shared element in screen coordinate space. This is
      *                     the bounds of the view with the viewToGlobalMatrix applied.
      * @return A snapshot to send to the remote Activity to be reconstituted with
-     * {@link #createSnapshotView(android.content.Context, android.os.Parcelable)} and passed
-     * into {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)} and
-     * {@link #setSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
+     * {@link #onCreateSnapshotView(android.content.Context, android.os.Parcelable)} and passed
+     * into {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} and
+     * {@link #onSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
      */
-    public Parcelable captureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,
+    public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,
             RectF screenBounds) {
         int bitmapWidth = Math.round(screenBounds.width());
         int bitmapHeight = Math.round(screenBounds.height());
@@ -160,20 +160,22 @@
 
     /**
      * Reconstitutes a snapshot View from a Parcelable returned in
-     * {@link #captureSharedElementSnapshot(android.view.View, android.graphics.Matrix,
-     * android.graphics.RectF)} to be used in {@link #setSharedElementStart(java.util.List,
-     * java.util.List, java.util.List)} and {@link #setSharedElementEnd(java.util.List,
+     * {@link #onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix,
+     * android.graphics.RectF)} to be used in {@link #onSharedElementStart(java.util.List,
+     * java.util.List, java.util.List)} and {@link #onSharedElementEnd(java.util.List,
      * java.util.List, java.util.List)}. The returned View will be sized and positioned after
      * this call so that it is ready to be added to the decor View's overlay.
      *
+     * <p>This is not called for Fragment Transitions.</p>
+     *
      * @param context The Context used to create the snapshot View.
-     * @param snapshot The Parcelable returned by {@link #captureSharedElementSnapshot(
+     * @param snapshot The Parcelable returned by {@link #onCaptureSharedElementSnapshot(
      * android.view.View, android.graphics.Matrix, android.graphics.RectF)}.
-     * @return A View to be sent in {@link #setSharedElementStart(java.util.List, java.util.List,
-     * java.util.List)} and {@link #setSharedElementEnd(java.util.List, java.util.List,
+     * @return A View to be sent in {@link #onSharedElementStart(java.util.List, java.util.List,
+     * java.util.List)} and {@link #onSharedElementEnd(java.util.List, java.util.List,
      * java.util.List)}. A null value will produce a null snapshot value for those two methods.
      */
-    public View createSnapshotView(Context context, Parcelable snapshot) {
+    public View onCreateSnapshotView(Context context, Parcelable snapshot) {
         View view = null;
         if (snapshot instanceof Bitmap) {
             Bitmap bitmap = (Bitmap) snapshot;
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 15def09..e2f175c 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -177,7 +177,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_LOCK_TASK_ENTERING
-            = "android.app.action.ACTION_LOCK_TASK_ENTERING";
+            = "android.app.action.LOCK_TASK_ENTERING";
 
     /**
      * Action sent to a device administrator to notify that the device is exiting
@@ -190,7 +190,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_LOCK_TASK_EXITING
-            = "android.app.action.ACTION_LOCK_TASK_EXITING";
+            = "android.app.action.LOCK_TASK_EXITING";
 
     /**
      * A boolean describing whether the device is currently entering or exiting
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 69b1139..112fc82 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -115,6 +115,19 @@
         = "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
 
     /**
+     * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
+     * a mobile device management application that starts managed profile provisioning to pass data
+     * to itself on the managed profile when provisioning completes. The mobile device management
+     * application sends this extra in an intent with the action
+     * {@link #ACTION_PROVISION_MANAGED_PROFILE} and receives it in
+     * {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with the action
+     * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is not changed
+     * during the managed profile provisioning.
+     */
+    public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE =
+            "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
+
+    /**
      * A String extra holding the package name of the mobile device management application that
      * will be set as the profile owner or device owner.
      *
@@ -135,21 +148,15 @@
      * <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
      */
     public static final String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME
-        = "android.app.extra.DEFAULT_MANAGED_PROFILE_NAME";
+        = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
 
     /**
-     * A String extra that, holds the email address of the account which a managed profile is
-     * created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
-     * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}.
-     *
-     * <p> If the {@link #ACTION_PROVISION_MANAGED_PROFILE} intent that starts managed provisioning
-     * contains this extra, it is forwarded in the
-     * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} intent to the mobile
-     * device management application that was set as the profile owner during provisioning.
-     * It is usually used to avoid that the user has to enter their email address twice.
+     * A bundle key, used in the bundle extra {@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}. The
+     * corresponding value holds the email address of the account which the managed profile is
+     * created for.
      */
-    public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS
-        = "android.app.extra.ManagedProfileEmailAddress";
+    public static final String KEY_PROVISIONING_EMAIL_ADDRESS
+        = "android.app.key.PROVISIONING_EMAIL_ADDRESS";
 
     /**
      * A String extra holding the time zone {@link android.app.AlarmManager} that the device
@@ -159,7 +166,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_TIME_ZONE
-        = "android.app.extra.TIME_ZONE";
+        = "android.app.extra.PROVISIONING_TIME_ZONE";
 
     /**
      * A Long extra holding the wall clock time (in milliseconds) to be set on the device's
@@ -169,7 +176,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_LOCAL_TIME
-        = "android.app.extra.LOCAL_TIME";
+        = "android.app.extra.PROVISIONING_LOCAL_TIME";
 
     /**
      * A String extra holding the {@link java.util.Locale} that the device will be set to.
@@ -179,7 +186,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_LOCALE
-        = "android.app.extra.LOCALE";
+        = "android.app.extra.PROVISIONING_LOCALE";
 
     /**
      * A String extra holding the ssid of the wifi network that should be used during nfc device
@@ -189,7 +196,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_WIFI_SSID
-        = "android.app.extra.WIFI_SSID";
+        = "android.app.extra.PROVISIONING_WIFI_SSID";
 
     /**
      * A boolean extra indicating whether the wifi network in {@link #EXTRA_PROVISIONING_WIFI_SSID}
@@ -199,7 +206,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_WIFI_HIDDEN
-        = "android.app.extra.WIFI_HIDDEN";
+        = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
 
     /**
      * A String extra indicating the security type of the wifi network in
@@ -209,7 +216,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE
-        = "android.app.extra.WIFI_SECURITY_TYPE";
+        = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
 
     /**
      * A String extra holding the password of the wifi network in
@@ -219,7 +226,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_WIFI_PASSWORD
-        = "android.app.extra.WIFI_PASSWORD";
+        = "android.app.extra.PROVISIONING_WIFI_PASSWORD";
 
     /**
      * A String extra holding the proxy host for the wifi network in
@@ -229,7 +236,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_WIFI_PROXY_HOST
-        = "android.app.extra.WIFI_PROXY_HOST";
+        = "android.app.extra.PROVISIONING_WIFI_PROXY_HOST";
 
     /**
      * An int extra holding the proxy port for the wifi network in
@@ -239,7 +246,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_WIFI_PROXY_PORT
-        = "android.app.extra.WIFI_PROXY_PORT";
+        = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
 
     /**
      * A String extra holding the proxy bypass for the wifi network in
@@ -249,7 +256,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS
-        = "android.app.extra.WIFI_PROXY_BYPASS_HOSTS";
+        = "android.app.extra.PROVISIONING_WIFI_PROXY_BYPASS";
 
     /**
      * A String extra holding the proxy auto-config (PAC) URL for the wifi network in
@@ -259,7 +266,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_WIFI_PAC_URL
-        = "android.app.extra.WIFI_PAC_URL";
+        = "android.app.extra.PROVISIONING_WIFI_PAC_URL";
 
     /**
      * A String extra holding a url that specifies the download location of the device admin
@@ -269,7 +276,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION
-        = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
+        = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
 
     /**
      * A String extra holding a http cookie header which should be used in the http request to the
@@ -279,7 +286,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER
-        = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
+        = "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
@@ -291,7 +298,7 @@
      * provisioning via an Nfc bump.
      */
     public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
-        = "android.app.extra.DEVICE_ADMIN_PACKAGE_CHECKSUM";
+        = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
 
     /**
      * This MIME type is used for starting the Device Owner provisioning.
@@ -1773,16 +1780,24 @@
      * If a user has installed any certificates by other means than device policy these will be
      * included too.
      *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return a List of byte[] arrays, each encoding one user CA certificate.
      */
-    public List<byte[]> getInstalledCaCerts() {
-        final TrustedCertificateStore certStore = new TrustedCertificateStore();
+    public List<byte[]> getInstalledCaCerts(ComponentName admin) {
         List<byte[]> certs = new ArrayList<byte[]>();
-        for (String alias : certStore.userAliases()) {
+        if (mService != null) {
             try {
-                certs.add(certStore.getCertificate(alias).getEncoded());
-            } catch (CertificateException ce) {
-                Log.w(TAG, "Could not encode certificate: " + alias, ce);
+                mService.enforceCanManageCaCerts(admin);
+                final TrustedCertificateStore certStore = new TrustedCertificateStore();
+                for (String alias : certStore.userAliases()) {
+                    try {
+                        certs.add(certStore.getCertificate(alias).getEncoded());
+                    } catch (CertificateException ce) {
+                        Log.w(TAG, "Could not encode certificate: " + alias, ce);
+                    }
+                }
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed talking with device policy service", re);
             }
         }
         return certs;
@@ -1809,13 +1824,19 @@
     /**
      * Returns whether this certificate is installed as a trusted CA.
      *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param certBuffer encoded form of the certificate to look up.
      */
-    public boolean hasCaCertInstalled(byte[] certBuffer) {
-        try {
-            return getCaCertAlias(certBuffer) != null;
-        } catch (CertificateException ce) {
-            Log.w(TAG, "Could not parse certificate", ce);
+    public boolean hasCaCertInstalled(ComponentName admin, byte[] certBuffer) {
+        if (mService != null) {
+            try {
+                mService.enforceCanManageCaCerts(admin);
+                return getCaCertAlias(certBuffer) != null;
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed talking with device policy service", re);
+            } catch (CertificateException ce) {
+                Log.w(TAG, "Could not parse certificate", ce);
+            }
         }
         return false;
     }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c984cf9..57d8b95 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -124,6 +124,7 @@
 
     boolean installCaCert(in ComponentName admin, in byte[] certBuffer);
     void uninstallCaCert(in ComponentName admin, in String alias);
+    void enforceCanManageCaCerts(in ComponentName admin);
 
     void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
     void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index ca7022d..89efeb2 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -21,14 +21,24 @@
 import android.content.Context;
 
 /**
- * Class for scheduling various types of jobs with the scheduling framework on the device.
+ * This is an API for scheduling various types of jobs against the framework that will be executed
+ * in your application's own process.
+ * <p>
  * See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run
- * and how to construct them.
+ * and how to construct them. You will construct these JobInfo objects and pass them to the
+ * JobScheduler with {@link #schedule(JobInfo)}. When the criteria declared are met, the
+ * system will execute this job on your application's {@link android.app.job.JobService}.
+ * You identify which JobService is meant to execute the logic for your job when you create the
+ * JobInfo with
+ * {@link android.app.job.JobInfo.Builder#JobInfo.Builder(int,android.content.ComponentName)}.
+ * </p>
+ * <p>
  * The framework will be intelligent about when you receive your callbacks, and attempt to batch
  * and defer them as much as possible. Typically if you don't specify a deadline on your job, it
  * can be run at any moment depending on the current state of the JobScheduler's internal queue,
  * however it might be deferred as long as until the next time the device is connected to a power
  * source.
+ * </p>
  * <p>You do not
  * instantiate this class directly; instead, retrieve it through
  * {@link android.content.Context#getSystemService
diff --git a/core/java/android/app/usage/ConfigurationStats.java b/core/java/android/app/usage/ConfigurationStats.java
new file mode 100644
index 0000000..080216c
--- /dev/null
+++ b/core/java/android/app/usage/ConfigurationStats.java
@@ -0,0 +1,161 @@
+/**
+ * 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.usage;
+
+import android.content.res.Configuration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents the usage statistics of a device {@link android.content.res.Configuration} for a
+ * specific time range.
+ */
+public final class ConfigurationStats implements Parcelable {
+
+    /**
+     * {@hide}
+     */
+    public Configuration mConfiguration;
+
+    /**
+     * {@hide}
+     */
+    public long mBeginTimeStamp;
+
+    /**
+     * {@hide}
+     */
+    public long mEndTimeStamp;
+
+    /**
+     * {@hide}
+     */
+    public long mLastTimeActive;
+
+    /**
+     * {@hide}
+     */
+    public long mTotalTimeActive;
+
+    /**
+     * {@hide}
+     */
+    public int mActivationCount;
+
+    /**
+     * {@hide}
+     */
+    public ConfigurationStats() {
+    }
+
+    public ConfigurationStats(ConfigurationStats stats) {
+        mConfiguration = stats.mConfiguration;
+        mBeginTimeStamp = stats.mBeginTimeStamp;
+        mEndTimeStamp = stats.mEndTimeStamp;
+        mLastTimeActive = stats.mLastTimeActive;
+        mTotalTimeActive = stats.mTotalTimeActive;
+        mActivationCount = stats.mActivationCount;
+    }
+
+    public Configuration getConfiguration() {
+        return mConfiguration;
+    }
+
+    /**
+     * Get the beginning of the time range this {@link ConfigurationStats} represents,
+     * measured in milliseconds since the epoch.
+     * <p/>
+     * See {@link System#currentTimeMillis()}.
+     */
+    public long getFirstTimeStamp() {
+        return mBeginTimeStamp;
+    }
+
+    /**
+     * Get the end of the time range this {@link ConfigurationStats} represents,
+     * measured in milliseconds since the epoch.
+     * <p/>
+     * See {@link System#currentTimeMillis()}.
+     */
+    public long getLastTimeStamp() {
+        return mEndTimeStamp;
+    }
+
+    /**
+     * Get the last time this configuration was active, measured in milliseconds since the epoch.
+     * <p/>
+     * See {@link System#currentTimeMillis()}.
+     */
+    public long getLastTimeActive() {
+        return mLastTimeActive;
+    }
+
+    /**
+     * Get the total time this configuration was active, measured in milliseconds.
+     */
+    public long getTotalTimeActive() {
+        return mTotalTimeActive;
+    }
+
+    /**
+     * Get the number of times this configuration was active.
+     */
+    public int getActivationCount() {
+        return mActivationCount;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (mConfiguration != null) {
+            dest.writeInt(1);
+            mConfiguration.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+
+        dest.writeLong(mBeginTimeStamp);
+        dest.writeLong(mEndTimeStamp);
+        dest.writeLong(mLastTimeActive);
+        dest.writeLong(mTotalTimeActive);
+        dest.writeInt(mActivationCount);
+    }
+
+    public static final Creator<ConfigurationStats> CREATOR = new Creator<ConfigurationStats>() {
+        @Override
+        public ConfigurationStats createFromParcel(Parcel source) {
+            ConfigurationStats stats = new ConfigurationStats();
+            if (source.readInt() != 0) {
+                stats.mConfiguration = Configuration.CREATOR.createFromParcel(source);
+            }
+            stats.mBeginTimeStamp = source.readLong();
+            stats.mEndTimeStamp = source.readLong();
+            stats.mLastTimeActive = source.readLong();
+            stats.mTotalTimeActive = source.readLong();
+            stats.mActivationCount = source.readInt();
+            return stats;
+        }
+
+        @Override
+        public ConfigurationStats[] newArray(int size) {
+            return new ConfigurationStats[size];
+        }
+    };
+}
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 3b09888..4ed1489 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -27,5 +27,7 @@
 interface IUsageStatsManager {
     ParceledListSlice queryUsageStats(int bucketType, long beginTime, long endTime,
             String callingPackage);
+    ParceledListSlice queryConfigurationStats(int bucketType, long beginTime, long endTime,
+            String callingPackage);
     UsageEvents queryEvents(long beginTime, long endTime, String callingPackage);
 }
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index fb80de2..1a947ec 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -16,6 +16,7 @@
 package android.app.usage;
 
 import android.content.ComponentName;
+import android.content.res.Configuration;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -63,6 +64,11 @@
         public static final int CONTINUE_PREVIOUS_DAY = 4;
 
         /**
+         * An event type denoting that the device configuration has changed.
+         */
+        public static final int CONFIGURATION_CHANGE = 5;
+
+        /**
          * {@hide}
          */
         public String mPackage;
@@ -83,6 +89,12 @@
         public int mEventType;
 
         /**
+         * Only present for {@link #CONFIGURATION_CHANGE} event types.
+         * {@hide}
+         */
+        public Configuration mConfiguration;
+
+        /**
          * TODO(adamlesinski): Removed before release.
          * {@hide}
          */
@@ -123,6 +135,14 @@
         public int getEventType() {
             return mEventType;
         }
+
+        /**
+         * Returns a {@link Configuration} for this event if the event is of type
+         * {@link #CONFIGURATION_CHANGE}, otherwise it returns null.
+         */
+        public Configuration getConfiguration() {
+            return mConfiguration;
+        }
     }
 
     // Only used when creating the resulting events. Not used for reading/unparceling.
@@ -201,23 +221,9 @@
             return false;
         }
 
-        final int packageIndex = mParcel.readInt();
-        if (packageIndex >= 0) {
-            eventOut.mPackage = mStringPool[packageIndex];
-        } else {
-            eventOut.mPackage = null;
-        }
+        readEventFromParcel(mParcel, eventOut);
 
-        final int classIndex = mParcel.readInt();
-        if (classIndex >= 0) {
-            eventOut.mClass = mStringPool[classIndex];
-        } else {
-            eventOut.mClass = null;
-        }
-        eventOut.mEventType = mParcel.readInt();
-        eventOut.mTimeStamp = mParcel.readLong();
         mIndex++;
-
         if (mIndex >= mEventCount) {
             mParcel.recycle();
             mParcel = null;
@@ -235,11 +241,6 @@
         }
     }
 
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
     private int findStringIndex(String str) {
         final int index = Arrays.binarySearch(mStringPool, str);
         if (index < 0) {
@@ -248,6 +249,66 @@
         return index;
     }
 
+    /**
+     * Writes a single event to the parcel. Modify this when updating {@link Event}.
+     */
+    private void writeEventToParcel(Event event, Parcel p, int flags) {
+        final int packageIndex;
+        if (event.mPackage != null) {
+            packageIndex = findStringIndex(event.mPackage);
+        } else {
+            packageIndex = -1;
+        }
+
+        final int classIndex;
+        if (event.mClass != null) {
+            classIndex = findStringIndex(event.mClass);
+        } else {
+            classIndex = -1;
+        }
+        p.writeInt(packageIndex);
+        p.writeInt(classIndex);
+        p.writeInt(event.mEventType);
+        p.writeLong(event.mTimeStamp);
+
+        if (event.mEventType == Event.CONFIGURATION_CHANGE) {
+            event.mConfiguration.writeToParcel(p, flags);
+        }
+    }
+
+    /**
+     * Reads a single event from the parcel. Modify this when updating {@link Event}.
+     */
+    private void readEventFromParcel(Parcel p, Event eventOut) {
+        final int packageIndex = p.readInt();
+        if (packageIndex >= 0) {
+            eventOut.mPackage = mStringPool[packageIndex];
+        } else {
+            eventOut.mPackage = null;
+        }
+
+        final int classIndex = p.readInt();
+        if (classIndex >= 0) {
+            eventOut.mClass = mStringPool[classIndex];
+        } else {
+            eventOut.mClass = null;
+        }
+        eventOut.mEventType = p.readInt();
+        eventOut.mTimeStamp = p.readLong();
+
+        // Extract the configuration for configuration change events.
+        if (eventOut.mEventType == Event.CONFIGURATION_CHANGE) {
+            eventOut.mConfiguration = Configuration.CREATOR.createFromParcel(p);
+        } else {
+            eventOut.mConfiguration = null;
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mEventCount);
@@ -262,25 +323,9 @@
                     p.setDataPosition(0);
                     for (int i = 0; i < mEventCount; i++) {
                         final Event event = mEventsToWrite.get(i);
-
-                        final int packageIndex;
-                        if (event.mPackage != null) {
-                            packageIndex = findStringIndex(event.mPackage);
-                        } else {
-                            packageIndex = -1;
-                        }
-
-                        final int classIndex;
-                        if (event.mClass != null) {
-                            classIndex = findStringIndex(event.mClass);
-                        } else {
-                            classIndex = -1;
-                        }
-                        p.writeInt(packageIndex);
-                        p.writeInt(classIndex);
-                        p.writeInt(event.getEventType());
-                        p.writeLong(event.getTimeStamp());
+                        writeEventToParcel(event, p, flags);
                     }
+
                     final int listByteLength = p.dataPosition();
 
                     // Write the total length of the data.
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 5830fcf..bc6099a 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -125,9 +125,9 @@
      * @see #INTERVAL_YEARLY
      * @see #INTERVAL_BEST
      */
-    @SuppressWarnings("unchecked")
     public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime) {
         try {
+            @SuppressWarnings("unchecked")
             ParceledListSlice<UsageStats> slice = mService.queryUsageStats(intervalType, beginTime,
                     endTime, mContext.getOpPackageName());
             if (slice != null) {
@@ -136,7 +136,32 @@
         } catch (RemoteException e) {
             // fallthrough and return null.
         }
-        return Collections.EMPTY_LIST;
+        return Collections.emptyList();
+    }
+
+    /**
+     * Gets the hardware configurations the device was in for the given time range, aggregated by
+     * the specified interval. The results are ordered as in
+     * {@link #queryUsageStats(int, long, long)}.
+     *
+     * @param intervalType The time interval by which the stats are aggregated.
+     * @param beginTime The inclusive beginning of the range of stats to include in the results.
+     * @param endTime The exclusive end of the range of stats to include in the results.
+     * @return A list of {@link ConfigurationStats} or null if none are available.
+     */
+    public List<ConfigurationStats> queryConfigurations(int intervalType, long beginTime,
+            long endTime) {
+        try {
+            @SuppressWarnings("unchecked")
+            ParceledListSlice<ConfigurationStats> slice = mService.queryConfigurationStats(
+                    intervalType, beginTime, endTime, mContext.getOpPackageName());
+            if (slice != null) {
+                return slice.getList();
+            }
+        } catch (RemoteException e) {
+            // fallthrough and return the empty list.
+        }
+        return Collections.emptyList();
     }
 
     /**
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 119d705..083a48a 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -17,6 +17,7 @@
 package android.app.usage;
 
 import android.content.ComponentName;
+import android.content.res.Configuration;
 
 /**
  * UsageStatsManager local system service interface.
@@ -28,14 +29,19 @@
     /**
      * Reports an event to the UsageStatsManager.
      *
-     * @param component The component for which this event ocurred.
+     * @param component The component for which this event occurred.
      * @param userId The user id to which the component belongs to.
-     * @param timeStamp The time at which this event ocurred.
-     * @param eventType The event that occured. Valid values can be found at
+     * @param eventType The event that occurred. Valid values can be found at
      * {@link UsageEvents}
      */
-    public abstract void reportEvent(ComponentName component, int userId,
-            long timeStamp, int eventType);
+    public abstract void reportEvent(ComponentName component, int userId, int eventType);
+
+    /**
+     * Reports a configuration change to the UsageStatsManager.
+     *
+     * @param config The new device configuration.
+     */
+    public abstract void reportConfigurationChange(Configuration config, int userId);
 
     /**
      * Prepares the UsageStatsService for shutdown.
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index bd45c7e..00248cc 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -188,7 +188,7 @@
      * this widget. Can have the value {@link
      * AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
      * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD} or {@link
-     * AppWidgetProviderInfo#WIDGET_CATEGORY_RECENTS}.
+     * AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX}.
      */
     public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
 
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 02f70c8..b4d79b4 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -61,9 +61,9 @@
     public static final int WIDGET_CATEGORY_KEYGUARD = 2;
 
     /**
-     * Indicates that the widget can be displayed within recents.
+     * Indicates that the widget can be displayed within a space reserved for the search box.
      */
-    public static final int WIDGET_CATEGORY_RECENTS = 4;
+    public static final int WIDGET_CATEGORY_SEARCHBOX = 4;
 
     /**
      * Identity of this AppWidget component.  This component should be a {@link
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index b98e5ae..36997e5 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -375,6 +375,14 @@
             } // else ASSERT(mPort == channel)
             ret = 0;
         } catch (IOException e) {
+            if (mPfd != null) {
+                try {
+                    mPfd.close();
+                } catch (IOException e1) {
+                    Log.e(TAG, "bindListen, close mPfd: " + e1);
+                }
+                mPfd = null;
+            }
             Log.e(TAG, "bindListen, fail to get port number, exception: " + e);
             return -1;
         }
diff --git a/core/java/android/content/AbstractRestrictionsProvider.java b/core/java/android/content/AbstractRestrictionsProvider.java
deleted file mode 100644
index 262980e..0000000
--- a/core/java/android/content/AbstractRestrictionsProvider.java
+++ /dev/null
@@ -1,85 +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.content;
-
-import android.app.admin.DevicePolicyManager;
-import android.os.IBinder;
-import android.os.PersistableBundle;
-
-/**
- * @hide
- * Abstract implementation of a Restrictions Provider BroadcastReceiver. To implement a
- * Restrictions Provider, extend from this class and implement the abstract methods.
- * Export this receiver in the manifest. A profile owner device admin can then register this
- * component as a Restrictions Provider using
- * {@link DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)}.
- * <p>
- * The function of a Restrictions Provider is to transport permission requests from apps on this
- * device to an administrator (most likely on a remote device or computer) and deliver back
- * responses. The response should be sent back to the app via
- * {@link RestrictionsManager#notifyPermissionResponse(String, PersistableBundle)}.
- *
- * @see RestrictionsManager
- * TODO: STOPSHIP: Remove before L ships, after clients have switched over
- * to android.service.restrictions.RestrictionsReceiver. Bug: 17006805
- */
-public abstract class AbstractRestrictionsProvider extends BroadcastReceiver {
-
-    private static final String TAG = "AbstractRestrictionsProvider";
-
-    /**
-     * An asynchronous permission request made by an application for an operation that requires
-     * authorization by a local or remote administrator other than the user. The Restrictions
-     * Provider should transfer the request to the administrator and deliver back a response, when
-     * available. The calling application is aware that the response could take an indefinite
-     * amount of time.
-     * <p>
-     * If the request bundle contains the key {@link RestrictionsManager#REQUEST_KEY_NEW_REQUEST},
-     * then a new request must be sent. Otherwise the provider can look up any previous response
-     * to the same requestId and return the cached response.
-     *
-     * @param packageName the application requesting permission.
-     * @param requestType the type of request, which determines the content and presentation of
-     * the request data.
-     * @param request the request data bundle containing at a minimum a request id.
-     *
-     * @see RestrictionsManager#REQUEST_TYPE_APPROVAL
-     * @see RestrictionsManager#REQUEST_TYPE_LOCAL_APPROVAL
-     * @see RestrictionsManager#REQUEST_KEY_ID
-     */
-    public abstract void requestPermission(Context context,
-            String packageName, String requestType, String requestId, PersistableBundle request);
-
-    /**
-     * Intercept standard Restrictions Provider broadcasts.  Implementations
-     * should not override this method; it is better to implement the
-     * convenience callbacks for each action.
-     */
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        String action = intent.getAction();
-
-        if (RestrictionsManager.ACTION_REQUEST_PERMISSION.equals(action)) {
-            String packageName = intent.getStringExtra(RestrictionsManager.EXTRA_PACKAGE_NAME);
-            String requestType = intent.getStringExtra(RestrictionsManager.EXTRA_REQUEST_TYPE);
-            String requestId = intent.getStringExtra(RestrictionsManager.EXTRA_REQUEST_ID);
-            PersistableBundle request = (PersistableBundle)
-                    intent.getParcelableExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE);
-            requestPermission(context, packageName, requestType, requestId, request);
-        }
-    }
-}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b825c94..51a58d1 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3363,7 +3363,7 @@
      * profiles - {@link #ACTION_MANAGED_PROFILE_ADDED} and {@link #ACTION_MANAGED_PROFILE_REMOVED}.
      */
     public static final String EXTRA_USER =
-            "android.intent.extra.user";
+            "android.intent.extra.USER";
 
     /**
      * Extra used in the response from a BroadcastReceiver that handles
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 0cff08b..ee23fcd 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -18,16 +18,10 @@
 
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Bitmap.Config;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.DisplayMetrics;
@@ -39,11 +33,9 @@
  * and badged icon for the activity.
  */
 public class LauncherActivityInfo {
-    private static final boolean DEBUG = false;
     private static final String TAG = "LauncherActivityInfo";
 
     private final PackageManager mPm;
-    private final UserManager mUm;
 
     private ActivityInfo mActivityInfo;
     private ComponentName mComponentName;
@@ -68,7 +60,6 @@
 
     LauncherActivityInfo(Context context) {
         mPm = context.getPackageManager();
-        mUm = UserManager.get(context);
     }
 
     /**
@@ -179,7 +170,7 @@
         }
 
         if (originalIcon instanceof BitmapDrawable) {
-            return mUm.getBadgedIconForUser(originalIcon, mUser);
+            return mPm.getUserBadgedIcon(originalIcon, mUser);
         } else {
             Log.e(TAG, "Unable to create badged icon for " + mActivityInfo);
         }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1b15ff5..e87adda 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -31,6 +31,7 @@
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
@@ -2882,6 +2883,79 @@
             throws NameNotFoundException;
 
     /**
+     * If the target user is a managed profile of the calling user or the caller
+     * is itself a managed profile, then this returns a badged copy of the given
+     * icon to be able to distinguish it from the original icon. For badging an
+     * arbitrary drawable use {@link #getUserBadgedDrawableForDensity(
+     * android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}.
+     * <p>
+     * If the original drawable is a BitmapDrawable and the backing bitmap is
+     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
+     * is performed in place and the original drawable is returned.
+     * </p>
+     *
+     * @param icon The icon to badge.
+     * @param user The target user.
+     * @return A drawable that combines the original icon and a badge as
+     *         determined by the system.
+     */
+    public abstract Drawable getUserBadgedIcon(Drawable icon, UserHandle user);
+
+    /**
+     * If the target user is a managed profile of the calling user or the caller
+     * is itself a managed profile, then this returns a badged copy of the given
+     * drawable allowing the user to distinguish it from the original drawable.
+     * The caller can specify the location in the bounds of the drawable to be
+     * badged where the badge should be applied as well as the density of the
+     * badge to be used.
+     * <p>
+     * If the original drawable is a BitmapDrawable and the backing bitmap is
+     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+     * is performed in place and the original drawable is returned.
+     * </p>
+     *
+     * @param drawable The drawable to badge.
+     * @param user The target user.
+     * @param badgeLocation Where in the bounds of the badged drawable to place
+     *         the badge. If not provided, the badge is applied on top of the entire
+     *         drawable being badged.
+     * @param badgeDensity The optional desired density for the badge as per
+     *         {@link android.util.DisplayMetrics#densityDpi}. If not provided,
+     *         the density of the display is used.
+     * @return A drawable that combines the original drawable and a badge as
+     *         determined by the system.
+     */
+    public abstract Drawable getUserBadgedDrawableForDensity(Drawable drawable,
+            UserHandle user, Rect badgeLocation, int badgeDensity);
+
+    /**
+     * If the target user is a managed profile of the calling user or the caller
+     * is itself a managed profile, then this returns a drawable to use as a small
+     * icon to include in a view to distinguish it from the original icon.
+     *
+     * @param user The target user.
+     * @param density The optional desired density for the badge as per
+     *         {@link android.util.DisplayMetrics#densityDpi}. If not provided
+     *         the density of the current display is used.
+     * @return the drawable or null if no drawable is required.
+     * @hide
+     */
+    public abstract Drawable getUserBadgeForDensity(UserHandle user, int density);
+
+    /**
+     * If the target user is a managed profile of the calling user or the caller
+     * is itself a managed profile, then this returns a copy of the label with
+     * badging for accessibility services like talkback. E.g. passing in "Email"
+     * and it might return "Work Email" for Email in the work profile.
+     *
+     * @param label The label to change.
+     * @param user The target user.
+     * @return A label that combines the original label and a badge as
+     *         determined by the system.
+     */
+    public abstract CharSequence getUserBadgedLabel(CharSequence label, UserHandle user);
+
+    /**
      * Retrieve text from a package.  This is a low-level API used by
      * the various package manager info structures (such as
      * {@link ComponentInfo} to implement retrieval of their associated
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index e63fd07..27bbb24 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -16,6 +16,12 @@
 
 package android.content.res;
 
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
 import android.content.pm.ActivityInfo;
 import android.os.Build;
 import android.os.Parcel;
@@ -23,7 +29,7 @@
 import android.text.TextUtils;
 import android.view.View;
 
-import java.text.Format;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Locale;
 
@@ -1353,8 +1359,6 @@
      * Returns a string representation of the configuration that can be parsed
      * by build tools (like AAPT).
      *
-     *
-     *
      * @hide
      */
     public static String resourceQualifierString(Configuration config) {
@@ -1568,4 +1572,229 @@
         parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
         return TextUtils.join("-", parts);
     }
+
+    /**
+     * Generate a delta Configuration between <code>base</code> and <code>change</code>. The
+     * resulting delta can be used with {@link #updateFrom(Configuration)}.
+     * <p />
+     * Caveat: If the any of the Configuration's members becomes undefined, then
+     * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member.
+     *
+     * This is fine for device configurations as no member is ever undefined.
+     * {@hide}
+     */
+    public static Configuration generateDelta(Configuration base, Configuration change) {
+        final Configuration delta = new Configuration();
+        if (base.fontScale != change.fontScale) {
+            delta.fontScale = change.fontScale;
+        }
+
+        if (base.mcc != change.mcc) {
+            delta.mcc = change.mcc;
+        }
+
+        if (base.mnc != change.mnc) {
+            delta.mnc = change.mnc;
+        }
+
+        if ((base.locale == null && change.locale != null) ||
+                (base.locale != null && !base.locale.equals(change.locale)))  {
+            delta.locale = change.locale;
+        }
+
+        if (base.touchscreen != change.touchscreen) {
+            delta.touchscreen = change.touchscreen;
+        }
+
+        if (base.keyboard != change.keyboard) {
+            delta.keyboard = change.keyboard;
+        }
+
+        if (base.keyboardHidden != change.keyboardHidden) {
+            delta.keyboardHidden = change.keyboardHidden;
+        }
+
+        if (base.navigation != change.navigation) {
+            delta.navigation = change.navigation;
+        }
+
+        if (base.navigationHidden != change.navigationHidden) {
+            delta.navigationHidden = change.navigationHidden;
+        }
+
+        if (base.orientation != change.orientation) {
+            delta.orientation = change.orientation;
+        }
+
+        if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
+                (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
+            delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
+        }
+
+        if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) !=
+                (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
+            delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
+        }
+
+        if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) !=
+                (change.screenLayout & SCREENLAYOUT_LONG_MASK)) {
+            delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK;
+        }
+
+        if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
+            delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
+        }
+
+        if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) {
+            delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK;
+        }
+
+        if (base.screenWidthDp != change.screenWidthDp) {
+            delta.screenWidthDp = change.screenWidthDp;
+        }
+
+        if (base.screenHeightDp != change.screenHeightDp) {
+            delta.screenHeightDp = change.screenHeightDp;
+        }
+
+        if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) {
+            delta.smallestScreenWidthDp = change.smallestScreenWidthDp;
+        }
+
+        if (base.densityDpi != change.densityDpi) {
+            delta.densityDpi = change.densityDpi;
+        }
+        return delta;
+    }
+
+    private static final String XML_ATTR_FONT_SCALE = "fs";
+    private static final String XML_ATTR_MCC = "mcc";
+    private static final String XML_ATTR_MNC = "mnc";
+    private static final String XML_ATTR_LOCALE = "locale";
+    private static final String XML_ATTR_TOUCHSCREEN = "touch";
+    private static final String XML_ATTR_KEYBOARD = "key";
+    private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid";
+    private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid";
+    private static final String XML_ATTR_NAVIGATION = "nav";
+    private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
+    private static final String XML_ATTR_ORIENTATION = "ori";
+    private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
+    private static final String XML_ATTR_UI_MODE = "ui";
+    private static final String XML_ATTR_SCREEN_WIDTH = "width";
+    private static final String XML_ATTR_SCREEN_HEIGHT = "height";
+    private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
+    private static final String XML_ATTR_DENSITY = "density";
+
+    /**
+     * Reads the attributes corresponding to Configuration member fields from the Xml parser.
+     * The parser is expected to be on a tag which has Configuration attributes.
+     *
+     * @param parser The Xml parser from which to read attributes.
+     * @param configOut The Configuration to populate from the Xml attributes.
+     * {@hide}
+     */
+    public static void readXmlAttrs(XmlPullParser parser, Configuration configOut)
+            throws XmlPullParserException, IOException {
+        configOut.fontScale = Float.intBitsToFloat(
+                XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0));
+        configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0);
+        configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0);
+
+        final String localeStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALE);
+        if (localeStr != null) {
+            configOut.locale = Locale.forLanguageTag(localeStr);
+        }
+
+        configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN,
+                TOUCHSCREEN_UNDEFINED);
+        configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD,
+                KEYBOARD_UNDEFINED);
+        configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN,
+                KEYBOARDHIDDEN_UNDEFINED);
+        configOut.hardKeyboardHidden =
+                XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN,
+                        HARDKEYBOARDHIDDEN_UNDEFINED);
+        configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION,
+                NAVIGATION_UNDEFINED);
+        configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN,
+                NAVIGATIONHIDDEN_UNDEFINED);
+        configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION,
+                ORIENTATION_UNDEFINED);
+        configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
+                SCREENLAYOUT_UNDEFINED);
+        configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
+        configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
+                SCREEN_WIDTH_DP_UNDEFINED);
+        configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT,
+                SCREEN_HEIGHT_DP_UNDEFINED);
+        configOut.smallestScreenWidthDp =
+                XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH,
+                        SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
+        configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
+                DENSITY_DPI_UNDEFINED);
+    }
+
+
+    /**
+     * Writes the Configuration's member fields as attributes into the XmlSerializer.
+     * The serializer is expected to have already started a tag so that attributes can be
+     * immediately written.
+     *
+     * @param xml The serializer to which to write the attributes.
+     * @param config The Configuration whose member fields to write.
+     * {@hide}
+     */
+    public static void writeXmlAttrs(XmlSerializer xml, Configuration config) throws IOException {
+        XmlUtils.writeIntAttribute(xml, XML_ATTR_FONT_SCALE,
+                Float.floatToIntBits(config.fontScale));
+        if (config.mcc != 0) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_MCC, config.mcc);
+        }
+        if (config.mnc != 0) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc);
+        }
+        if (config.locale != null) {
+            XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALE, config.locale.toLanguageTag());
+        }
+        if (config.touchscreen != TOUCHSCREEN_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen);
+        }
+        if (config.keyboard != KEYBOARD_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD, config.keyboard);
+        }
+        if (config.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD_HIDDEN, config.keyboardHidden);
+        }
+        if (config.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_HARD_KEYBOARD_HIDDEN,
+                    config.hardKeyboardHidden);
+        }
+        if (config.navigation != NAVIGATION_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION, config.navigation);
+        }
+        if (config.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION_HIDDEN, config.navigationHidden);
+        }
+        if (config.orientation != ORIENTATION_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_ORIENTATION, config.orientation);
+        }
+        if (config.screenLayout != SCREENLAYOUT_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout);
+        }
+        if (config.uiMode != 0) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode);
+        }
+        if (config.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_WIDTH, config.screenWidthDp);
+        }
+        if (config.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_HEIGHT, config.screenHeightDp);
+        }
+        if (config.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_SMALLEST_WIDTH, config.smallestScreenWidthDp);
+        }
+        if (config.densityDpi != DENSITY_DPI_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
+        }
+    }
 }
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 6a9d565..097b430 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -216,6 +216,128 @@
      * <p>Configuring a session with an empty or null list will close the current session, if
      * any. This can be used to release the current session's target surfaces for another use.</p>
      *
+     * <p>While any of the sizes from {@link StreamConfigurationMap#getOutputSizes} can be used when
+     * a single output stream is configured, a given camera device may not be able to support all
+     * combination of sizes, formats, and targets when multiple outputs are configured at once.  The
+     * tables below list the maximum guaranteed resolutions for combinations of streams and targets,
+     * given the capabilities of the camera device.</p>
+     *
+     * <p>If an application tries to create a session using a set of targets that exceed the limits
+     * described in the below tables, one of three possibilities may occur. First, the session may
+     * be successfully created and work normally. Second, the session may be successfully created,
+     * but the camera device won't meet the frame rate guarantees as described in
+     * {@link StreamConfigurationMap#getOutputMinFrameDuration}. Or third, if the output set
+     * cannot be used at all, session creation will fail entirely, with
+     * {@link CameraCaptureSession.StateListener#onConfigureFailed} being invoked.</p>
+     *
+     * <p>For the type column, {@code PRIV} refers to any target whose available sizes are found
+     * using {@link StreamConfigurationMap#getOutputSizes(Class)} with no direct application-visible
+     * format, {@code YUV} refers to a target Surface using the
+     * {@link android.graphics.ImageFormat#YUV_420_888} format, {@code JPEG} refers to the
+     * {@link android.graphics.ImageFormat#JPEG} format, and {@code RAW} refers to the
+     * {@link android.graphics.ImageFormat#RAW_SENSOR} format.</p>
+     *
+     * <p>For the maximum size column, {@code PREVIEW} refers to the best size match to the
+     * device's screen resolution, or to 1080p ({@code 1920x1080}), whichever is
+     * smaller. {@code RECORD} refers to the camera device's maximum supported recording resolution,
+     * as determined by {@link android.media.CamcorderProfile}. And {@code MAXIMUM} refers to the
+     * camera device's maximum output resolution for that format or target from
+     * {@link StreamConfigurationMap#getOutputSizes}.</p>
+     *
+     * <p>To use these tables, determine the number and the formats/targets of outputs needed, and
+     * find the row(s) of the table with those targets. The sizes indicate the maximum set of sizes
+     * that can be used; it is guaranteed that for those targets, the listed sizes and anything
+     * smaller from the list given by {@link StreamConfigurationMap#getOutputSizes} can be
+     * successfully used to create a session.  For example, if a row indicates that a 8 megapixel
+     * (MP) YUV_420_888 output can be used together with a 2 MP {@code PRIV} output, then a session
+     * can be created with targets {@code [8 MP YUV, 2 MP PRIV]} or targets {@code [2 MP YUV, 2 MP
+     * PRIV]}; but a session with targets {@code [8 MP YUV, 4 MP PRIV]}, targets {@code [4 MP YUV, 4
+     * MP PRIV]}, or targets {@code [8 MP PRIV, 2 MP YUV]} would not be guaranteed to work, unless
+     * some other row of the table lists such a combination.</p>
+     *
+     * <style scoped>
+     *  #rb { border-right-width: thick; }
+     * </style>
+     * <p>Legacy devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+     * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) support at
+     * least the following stream combinations:
+     *
+     * <table>
+     * <tr><th colspan="7">LEGACY-level guaranteed configurations</th></tr>
+     * <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th>  <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
+     * <tr> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-viewfinder still image capture.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>In-application video/image processing.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>In-app processing plus still capture.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td colspan="2" id="rb"></td> <td>Standard recording.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td colspan="2" id="rb"></td> <td>Preview plus in-app processing.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Still capture plus in-app processing.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p>Limited-capability ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+     * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}) devices
+     * support at least the following stream combinations in addition to those for
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} devices:
+     *
+     * <table>
+     * <tr><th colspan="7">LIMITED-level additional guaranteed configurations</th></tr>
+     * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>High-resolution video recording with preview.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>High-resolution in-app video processing with preview.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>Two-input in-app video processing.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with video snapshot.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution in-app processing with video snapshot.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Two-input in-app processing with still capture.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p>FULL-capability ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+     * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
+     * support at least the following stream combinations in addition to those for
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+     *
+     * <table>
+     * <tr><th colspan="7">FULL-capability additional guaranteed configurations</th></tr>
+     * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution GPU processing with preview.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution in-app processing with preview.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution two-input in-app processsing.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Video recording with maximum-size video snapshot</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code 640x480}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Standard video recording plus maximum-resolution in-app processing.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code 640x480}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Preview plus two-input maximum-resolution in-app processing.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p>RAW-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
+     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}) devices additionally support
+     * at least the following stream combinations on both
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+     *
+     * <table>
+     * <tr><th colspan="7">RAW-capability additional guaranteed configurations</th></tr>
+     * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+     * <tr> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-preview DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Standard DNG capture.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>In-app processing plus DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Video recording with DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Preview with in-app processing and DNG capture.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Two-input in-app processing plus DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Still capture with simultaneous JPEG and DNG.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>In-app processing with simultaneous JPEG and DNG.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p>Since the capabilities of camera devices vary greatly, a given camera device may support
+     * target combinations with sizes outside of these guarantees, but this can only be tested for
+     * by attempting to create a session with such targets.</p>
+     *
      * @param outputs The new set of Surfaces that should be made available as
      *                targets for captured image data.
      * @param listener The listener to notify about the status of the new capture session.
diff --git a/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java b/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java
index d0a3a3f..d5ec71a 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java
@@ -114,21 +114,24 @@
                 currentAfRun = mAfRun;
             }
 
-            mCamera.setAutoFocusMoveCallback(new Camera.AutoFocusMoveCallback() {
+            Camera.AutoFocusMoveCallback afMoveCallback = new Camera.AutoFocusMoveCallback() {
                 @Override
                 public void onAutoFocusMoving(boolean start, Camera camera) {
                     synchronized (mLock) {
                         int latestAfRun = mAfRun;
 
                         if (VERBOSE) {
-                            Log.v(TAG, "onAutoFocusMoving - start " + start + " latest AF run " +
-                                    latestAfRun + ", last AF run " + currentAfRun);
+                            Log.v(TAG,
+                                    "onAutoFocusMoving - start " + start + " latest AF run " +
+                                            latestAfRun + ", last AF run " + currentAfRun
+                            );
                         }
 
                         if (currentAfRun != latestAfRun) {
                             Log.d(TAG,
                                     "onAutoFocusMoving - ignoring move callbacks from old af run"
-                                            + currentAfRun);
+                                            + currentAfRun
+                            );
                             return;
                         }
 
@@ -151,9 +154,19 @@
                         mAfState = newAfState;
                     }
                 }
-            });
+            };
+
+            // Only set move callback if we can call autofocus.
+            switch (afMode) {
+                case Parameters.FOCUS_MODE_AUTO:
+                case Parameters.FOCUS_MODE_MACRO:
+                case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
+                case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
+                    mCamera.setAutoFocusMoveCallback(afMoveCallback);
+            }
         }
 
+
         // AF Locking
         switch (afTrigger) {
             case CONTROL_AF_TRIGGER_START:
@@ -167,6 +180,7 @@
                     case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
                     case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
                         afStateAfterStart = CONTROL_AF_STATE_PASSIVE_SCAN;
+                        break;
                     default:
                         // EDOF, INFINITY
                         afStateAfterStart = CONTROL_AF_STATE_INACTIVE;
@@ -183,6 +197,11 @@
                             "new AF run is " + currentAfRun);
                 }
 
+                // Avoid calling autofocus unless we are in a state that supports calling this.
+                if (afStateAfterStart == CONTROL_AF_STATE_INACTIVE) {
+                    break;
+                }
+
                 mCamera.autoFocus(new Camera.AutoFocusCallback() {
                     @Override
                     public void onAutoFocus(boolean success, Camera camera) {
diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
index 4c4ad0d..42ee4fa 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
@@ -122,7 +122,10 @@
                         activeArray, zoomData, aeRegions, maxNumMeteringAreas,
                         /*regionName*/"AE");
 
-                params.setMeteringAreas(meteringAreaList);
+                // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
+                if (maxNumMeteringAreas > 0) {
+                    params.setMeteringAreas(meteringAreaList);
+                }
             }
 
             // afRegions
@@ -133,7 +136,10 @@
                         activeArray, zoomData, afRegions, maxNumFocusAreas,
                         /*regionName*/"AF");
 
-                params.setFocusAreas(focusAreaList);
+                // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
+                if (maxNumFocusAreas > 0) {
+                    params.setFocusAreas(focusAreaList);
+                }
             }
         }
 
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index c0b7967..5d226e3 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -142,7 +142,7 @@
      * or in {@link PixelFormat} (and there is no possibility of collision).</p>
      *
      * <p>Formats listed in this array are guaranteed to return true if queried with
-     * {@link #isOutputSupportedFor(int).</p>
+     * {@link #isOutputSupportedFor(int)}.</p>
      *
      * @return an array of integer format
      *
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 4b5ced9..30f3576 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -55,10 +55,29 @@
     public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1;
 
     /**
+     * Message used by TV to receive volume status from Audio Receiver. It should check volume value
+     * that is retrieved from extra value with the key {@link #EXTRA_MESSAGE_EXTRAM_PARAM1}. If the
+     * value is in range of [0,100], it is current volume of Audio Receiver. And there is another
+     * value, {@link #AVR_VOLUME_MUTED}, which is used to inform volume mute.
+     */
+    public static final int OSD_MESSAGE_AVR_VOLUME_CHANGED = 2;
+
+    /**
      * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the ID of
      * the message to display on screen.
      */
     public static final String EXTRA_MESSAGE_ID = "android.hardware.hdmi.extra.MESSAGE_ID";
+    /**
+     * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the extra value
+     * of the message.
+     */
+    public static final String EXTRA_MESSAGE_EXTRAM_PARAM1 =
+            "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1";
+
+    /**
+     * Volume value for mute state.
+     */
+    public static final int AVR_VOLUME_MUTED = 101;
 
     public static final int POWER_STATUS_UNKNOWN = -1;
     public static final int POWER_STATUS_ON = 0;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 4bfef41..70b402d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -685,6 +685,23 @@
     }
 
     /**
+     * Returns the {@link Network} object currently serving a given type, or
+     * null if the given type is not connected.
+     *
+     * <p>This method requires the caller to hold the permission
+     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+     *
+     * @hide
+     */
+    public Network getNetworkForType(int networkType) {
+        try {
+            return mService.getNetworkForType(networkType);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
      * Returns an array of all {@link Network} currently tracked by the
      * framework.
      *
@@ -1281,7 +1298,7 @@
     }
 
     /**
-     * Callback for use with {@link ConnectivityManager#registerDefaultNetworkActiveListener}
+     * Callback for use with {@link ConnectivityManager#addDefaultNetworkActiveListener}
      * to find out when the system default network has gone in to a high power state.
      */
     public interface OnNetworkActiveListener {
@@ -1323,7 +1340,7 @@
      *
      * @param l The listener to be told when the network is active.
      */
-    public void registerDefaultNetworkActiveListener(final OnNetworkActiveListener l) {
+    public void addDefaultNetworkActiveListener(final OnNetworkActiveListener l) {
         INetworkActivityListener rl = new INetworkActivityListener.Stub() {
             @Override
             public void onNetworkActive() throws RemoteException {
@@ -1340,11 +1357,11 @@
 
     /**
      * Remove network active listener previously registered with
-     * {@link #registerDefaultNetworkActiveListener}.
+     * {@link #addDefaultNetworkActiveListener}.
      *
      * @param l Previously registered listener.
      */
-    public void unregisterDefaultNetworkActiveListener(OnNetworkActiveListener l) {
+    public void removeDefaultNetworkActiveListener(OnNetworkActiveListener l) {
         INetworkActivityListener rl = mNetworkActivityListeners.get(l);
         if (rl == null) {
             throw new IllegalArgumentException("Listener not registered: " + l);
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index b2fc3be..974c4cd 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -48,6 +48,7 @@
     NetworkInfo getNetworkInfo(int networkType);
     NetworkInfo getNetworkInfoForNetwork(in Network network);
     NetworkInfo[] getAllNetworkInfo();
+    Network getNetworkForType(int networkType);
     Network[] getAllNetworks();
 
     NetworkInfo getProvisioningOrActiveNetworkInfo();
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index f9a25f9..c387055 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -274,7 +274,6 @@
 
     /**
      * Implement the Parcelable interface.
-     * @hide
      */
     public int describeContents() {
         return 0;
@@ -282,7 +281,6 @@
 
     /**
      * Implement the Parcelable interface.
-     * @hide
      */
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeByteArray(address.getAddress());
@@ -293,7 +291,6 @@
 
     /**
      * Implement the Parcelable interface.
-     * @hide
      */
     public static final Creator<LinkAddress> CREATOR =
         new Creator<LinkAddress>() {
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index d2a4728..e686be7 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -35,6 +35,7 @@
 import java.util.concurrent.atomic.AtomicReference;
 import javax.net.SocketFactory;
 
+import com.android.okhttp.ConnectionPool;
 import com.android.okhttp.HostResolver;
 import com.android.okhttp.OkHttpClient;
 
@@ -60,6 +61,17 @@
     private volatile OkHttpClient mOkHttpClient = null;
     private Object mLock = new Object();
 
+    // Default connection pool values. These are evaluated at startup, just
+    // like the OkHttp code. Also like the OkHttp code, we will throw parse
+    // exceptions at class loading time if the properties are set but are not
+    // valid integers.
+    private static final boolean httpKeepAlive =
+            Boolean.parseBoolean(System.getProperty("http.keepAlive", "true"));
+    private static final int httpMaxConnections =
+            httpKeepAlive ? Integer.parseInt(System.getProperty("http.maxConnections", "5")) : 0;
+    private static final long httpKeepAliveDurationMs =
+            Long.parseLong(System.getProperty("http.keepAliveDuration", "300000"));  // 5 minutes.
+
     /**
      * @hide
      */
@@ -183,6 +195,20 @@
         return mNetworkBoundSocketFactory;
     }
 
+    // TODO: This creates an OkHttpClient with its own connection pool for
+    // every Network object, instead of one for every NetId. This is
+    // suboptimal, because an app could potentially have more than one
+    // Network object for the same NetId, causing increased memory footprint
+    // and performance penalties due to lack of connection reuse (connection
+    // setup time, congestion window growth time, etc.).
+    //
+    // Instead, investigate only having one OkHttpClient for every NetId,
+    // perhaps by using a static HashMap of NetIds to OkHttpClient objects. The
+    // tricky part is deciding when to remove an OkHttpClient; a WeakHashMap
+    // shouldn't be used because whether a Network is referenced doesn't
+    // correlate with whether a new Network will be instantiated in the near
+    // future with the same NetID. A good solution would involve purging empty
+    // (or when all connections are timed out) ConnectionPools.
     private void maybeInitHttpClient() {
         if (mOkHttpClient == null) {
             synchronized (mLock) {
@@ -193,9 +219,12 @@
                             return Network.this.getAllByName(host);
                         }
                     };
+                    ConnectionPool pool = new ConnectionPool(httpMaxConnections,
+                                                             httpKeepAliveDurationMs);
                     mOkHttpClient = new OkHttpClient()
                             .setSocketFactory(getSocketFactory())
-                            .setHostResolver(hostResolver);
+                            .setHostResolver(hostResolver)
+                            .setConnectionPool(pool);
                 }
             }
         }
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index d279412..7664c95 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -128,14 +128,6 @@
     private boolean mIsAvailable;
 
     /**
-     * @param type network type
-     * @deprecated
-     * @hide because this constructor was only meant for internal use (and
-     * has now been superseded by the package-private constructor below).
-     */
-    public NetworkInfo(int type) {}
-
-    /**
      * @hide
      */
     public NetworkInfo(int type, int subtype, String typeName, String subtypeName) {
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 83bdfaa..5a09b46 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -52,6 +52,9 @@
      * @hide
      */
     public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId) {
+        if (nc == null) {
+            throw new NullPointerException();
+        }
         requestId = rId;
         networkCapabilities = nc;
         this.legacyType = legacyType;
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index 7ea6bae..1534e2c 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -334,10 +334,6 @@
         dest.writeStringArray(mParsedExclusionList);
     }
 
-    /**
-     * Implement the Parcelable interface.
-     * @hide
-     */
     public static final Creator<ProxyInfo> CREATOR =
         new Creator<ProxyInfo>() {
             public ProxyInfo createFromParcel(Parcel in) {
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index b0e0b49..1e0dc53 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -541,7 +541,7 @@
          * Intent.</li>
          * </ul>
          */
-        public static final int L = CUR_DEVELOPMENT;
+        public static final int L = 21;
     }
     
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 6d4a302..b3e28ea 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -19,6 +19,7 @@
 
 import android.net.InterfaceConfiguration;
 import android.net.INetworkManagementEventObserver;
+import android.net.Network;
 import android.net.NetworkStats;
 import android.net.RouteInfo;
 import android.net.UidRange;
@@ -164,10 +165,10 @@
     /**
      * Sets the list of DNS forwarders (in order of priority)
      */
-    void setDnsForwarders(in String[] dns);
+    void setDnsForwarders(in Network network, in String[] dns);
 
     /**
-     * Returns the list of DNS fowarders (in order of priority)
+     * Returns the list of DNS forwarders (in order of priority)
      */
     String[] getDnsForwarders();
 
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 5ce9d5c..0ff5f6a 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -234,6 +234,7 @@
      * @return user id of the current process
      * @hide
      */
+    @SystemApi
     public static final int myUserId() {
         return getUserId(Process.myUid());
     }
@@ -253,7 +254,11 @@
         mHandle = h;
     }
 
-    /** @hide */
+    /**
+     * Returns the userId stored in this UserHandle.
+     * @hide
+     */
+    @SystemApi
     public int getIdentifier() {
         return mHandle;
     }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index f793667..ec77a5e 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -15,16 +15,14 @@
  */
 package android.os;
 
+import android.annotation.SystemApi;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.content.Context;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Bitmap.Config;
 import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.provider.Settings;
 import android.util.Log;
@@ -424,6 +422,19 @@
     }
 
     /**
+     * Checks if the calling app is running in a managed profile.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     *
+     * @return whether the caller is in a managed profile.
+     * @hide
+     */
+    @SystemApi
+    public boolean isManagedProfile() {
+        UserInfo user = getUserInfo(UserHandle.myUserId());
+        return user != null ? user.isManagedProfile() : false;
+    }
+
+    /**
      * Return whether the given user is actively running.  This means that
      * the user is in the "started" state, not "stopped" -- it is currently
      * allowed to run code through scheduled alarms, receiving broadcasts,
@@ -646,6 +657,7 @@
             try {
                 Bundle guestRestrictions = mService.getDefaultGuestRestrictions();
                 guestRestrictions.putBoolean(DISALLOW_SMS, true);
+                guestRestrictions.putBoolean(DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
                 mService.setUserRestrictions(guestRestrictions, guest.id);
             } catch (RemoteException re) {
                 Log.w(TAG, "Could not update guest restrictions");
@@ -823,46 +835,10 @@
      * @param user The target user.
      * @return A drawable that combines the original icon and a badge as
      *         determined by the system.
+     * @removed
      */
     public Drawable getBadgedIconForUser(Drawable icon, UserHandle user) {
-        final int badgeResId = getBadgeResIdForUser(user.getIdentifier());
-        if (badgeResId == 0) {
-            return icon;
-        }
-        Drawable badgeIcon = mContext.getPackageManager()
-                .getDrawable("system", badgeResId, null);
-        return getBadgedDrawable(icon, badgeIcon, null, true);
-    }
-
-    /**
-     * If the target user is a managed profile of the calling user or the caller
-     * is itself a managed profile, then this returns a badged copy of the given
-     * icon to be able to distinguish it from the original icon.
-     * <p>
-     * If the original drawable is not a BitmapDrawable, then the original
-     * drawable is returned.
-     * </p>
-     *
-     * @param icon The icon to badge.
-     * @param user The target user.
-     * @return A drawable that combines the original icon and a badge as
-     *         determined by the system.
-     *
-     * @deprecation Use {@link #getBadgedIconForUser(
-     *     android.graphics.drawable.Drawable, UserHandle)}
-     *
-     * @hide
-     */
-    @Deprecated
-    public Drawable getBadgedDrawableForUser(Drawable icon, UserHandle user) {
-        int badgeResId = getBadgeResIdForUser(user.getIdentifier());
-        if (badgeResId == 0) {
-            return icon;
-        } else {
-            Drawable badgeIcon = mContext.getPackageManager()
-                    .getDrawable("system", badgeResId, null);
-            return getBadgedDrawable(icon, badgeIcon, null, false);
-        }
+        return mContext.getPackageManager().getUserBadgedIcon(icon, user);
     }
 
     /**
@@ -888,14 +864,12 @@
      *         the density of the display is used.
      * @return A drawable that combines the original drawable and a badge as
      *         determined by the system.
+     * @removed
      */
     public Drawable getBadgedDrawableForUser(Drawable badgedDrawable, UserHandle user,
             Rect badgeLocation, int badgeDensity) {
-        Drawable badgeDrawable = getBadgeForUser(user, badgeDensity);
-        if (badgeDrawable == null) {
-            return badgedDrawable;
-        }
-        return getBadgedDrawable(badgedDrawable, badgeDrawable, badgeLocation, true);
+        return mContext.getPackageManager().getUserBadgedDrawableForDensity(badgedDrawable, user,
+                badgeLocation, badgeDensity);
     }
 
     /**
@@ -908,114 +882,10 @@
      * @param user The target user.
      * @return A label that combines the original label and a badge as
      *         determined by the system.
+     * @removed
      */
     public CharSequence getBadgedLabelForUser(CharSequence label, UserHandle user) {
-        UserInfo userInfo = getUserIfProfile(user.getIdentifier());
-        if (userInfo != null && userInfo.isManagedProfile()) {
-            return Resources.getSystem().getString(
-                    R.string.managed_profile_label_badge, label);
-        }
-        return label;
-    }
-
-    /**
-     * If the target user is a managed profile of the calling user or the caller
-     * is itself a managed profile, then this returns a drawable to use as a small
-     * icon to include in a view to distinguish it from the original icon.
-     *
-     * @param user The target user.
-     * @param density The optional desired density for the badge as per
-     *         {@link android.util.DisplayMetrics#densityDpi}. If not provided
-     *         the density of the current display is used.
-     * @return the drawable or null if no drawable is required.
-     * @hide
-     */
-    public Drawable getBadgeForUser(UserHandle user, int density) {
-        UserInfo userInfo = getUserIfProfile(user.getIdentifier());
-        if (userInfo != null && userInfo.isManagedProfile()) {
-            if (density <= 0) {
-                density = mContext.getResources().getDisplayMetrics().densityDpi;
-            }
-            return Resources.getSystem().getDrawableForDensity(
-                    com.android.internal.R.drawable.ic_corp_badge, density);
-        }
-        return null;
-    }
-
-    private int getBadgeResIdForUser(int userHandle) {
-        // Return the framework-provided badge.
-        UserInfo userInfo = getUserIfProfile(userHandle);
-        if (userInfo != null && userInfo.isManagedProfile()) {
-            return com.android.internal.R.drawable.ic_corp_icon_badge;
-        }
-        return 0;
-    }
-
-    /**
-     * @return UserInfo for userHandle if it exists and is a profile of the current
-     *         user or null.
-     */
-    private UserInfo getUserIfProfile(int userHandle) {
-        List<UserInfo> userProfiles = getProfiles(getUserHandle());
-        for (UserInfo user : userProfiles) {
-            if (user.id == userHandle) {
-                return user;
-            }
-        }
-        return null;
-    }
-
-    private Drawable getBadgedDrawable(Drawable badgedDrawable, Drawable badgeDrawable,
-            Rect badgeLocation, boolean tryBadgeInPlace) {
-        final int badgedWidth = badgedDrawable.getIntrinsicWidth();
-        final int badgedHeight = badgedDrawable.getIntrinsicHeight();
-        final boolean canBadgeInPlace = tryBadgeInPlace
-                && (badgedDrawable instanceof BitmapDrawable)
-                && ((BitmapDrawable) badgedDrawable).getBitmap().isMutable();
-
-        final Bitmap bitmap;
-        if (canBadgeInPlace) {
-            bitmap = ((BitmapDrawable) badgedDrawable).getBitmap();
-        } else {
-            bitmap = Bitmap.createBitmap(badgedWidth, badgedHeight, Config.ARGB_8888);
-        }
-        Canvas canvas = new Canvas(bitmap);
-
-        if (!canBadgeInPlace) {
-            badgedDrawable.setBounds(0, 0, badgedWidth, badgedHeight);
-            badgedDrawable.draw(canvas);
-        }
-
-        if (badgeLocation != null) {
-            if (badgeLocation.left < 0 || badgeLocation.top < 0
-                    || badgeLocation.width() > badgedWidth || badgeLocation.height() > badgedHeight) {
-                throw new IllegalArgumentException("Badge location " + badgeLocation
-                        + " not in badged drawable bounds "
-                        + new Rect(0, 0, badgedWidth, badgedHeight));
-            }
-            badgeDrawable.setBounds(0, 0, badgeLocation.width(), badgeLocation.height());
-
-            canvas.save();
-            canvas.translate(badgeLocation.left, badgeLocation.top);
-            badgeDrawable.draw(canvas);
-            canvas.restore();
-        } else {
-            badgeDrawable.setBounds(0, 0, badgedWidth, badgedHeight);
-            badgeDrawable.draw(canvas);
-        }
-
-        if (!canBadgeInPlace) {
-            BitmapDrawable mergedDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
-
-            if (badgedDrawable instanceof BitmapDrawable) {
-                BitmapDrawable bitmapDrawable = (BitmapDrawable) badgedDrawable;
-                mergedDrawable.setTargetDensity(bitmapDrawable.getBitmap().getDensity());
-            }
-
-            return mergedDrawable;
-        }
-
-        return badgedDrawable;
+        return mContext.getPackageManager().getUserBadgedLabel(label, user);
     }
 
     /**
diff --git a/core/java/android/preference/CheckBoxPreference.java b/core/java/android/preference/CheckBoxPreference.java
index 1ce98b8..fee3f0f 100644
--- a/core/java/android/preference/CheckBoxPreference.java
+++ b/core/java/android/preference/CheckBoxPreference.java
@@ -66,7 +66,6 @@
         View checkboxView = view.findViewById(com.android.internal.R.id.checkbox);
         if (checkboxView != null && checkboxView instanceof Checkable) {
             ((Checkable) checkboxView).setChecked(mChecked);
-            sendAccessibilityEvent(checkboxView);
         }
 
         syncSummaryView(view);
diff --git a/core/java/android/preference/SwitchPreference.java b/core/java/android/preference/SwitchPreference.java
index 46be928..53b5aad 100644
--- a/core/java/android/preference/SwitchPreference.java
+++ b/core/java/android/preference/SwitchPreference.java
@@ -130,8 +130,6 @@
 
             ((Checkable) checkableView).setChecked(mChecked);
 
-            sendAccessibilityEvent(checkableView);
-
             if (checkableView instanceof Switch) {
                 final Switch switchView = (Switch) checkableView;
                 switchView.setTextOn(mSwitchOn);
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index 6f8be1f..3823b27 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -24,8 +24,6 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
 import android.widget.TextView;
 
 /**
@@ -39,7 +37,6 @@
     private CharSequence mSummaryOff;
     boolean mChecked;
     private boolean mCheckedSet;
-    private boolean mSendClickAccessibilityEvent;
     private boolean mDisableDependentsState;
 
     public TwoStatePreference(
@@ -63,15 +60,10 @@
     protected void onClick() {
         super.onClick();
 
-        boolean newValue = !isChecked();
-
-        mSendClickAccessibilityEvent = true;
-
-        if (!callChangeListener(newValue)) {
-            return;
+        final boolean newValue = !isChecked();
+        if (callChangeListener(newValue)) {
+            setChecked(newValue);
         }
-
-        setChecked(newValue);
     }
 
     /**
@@ -196,21 +188,6 @@
                 : (Boolean) defaultValue);
     }
 
-    void sendAccessibilityEvent(View view) {
-        // Since the view is still not attached we create, populate,
-        // and send the event directly since we do not know when it
-        // will be attached and posting commands is not as clean.
-        AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(getContext());
-        if (mSendClickAccessibilityEvent && accessibilityManager.isEnabled()) {
-            AccessibilityEvent event = AccessibilityEvent.obtain();
-            event.setEventType(AccessibilityEvent.TYPE_VIEW_CLICKED);
-            view.onInitializeAccessibilityEvent(event);
-            view.dispatchPopulateAccessibilityEvent(event);
-            accessibilityManager.sendAccessibilityEvent(event);
-        }
-        mSendClickAccessibilityEvent = false;
-    }
-
     /**
      * Sync a summary view contained within view's subhierarchy with the correct summary text.
      * @param view View where a summary should be located
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 0202f91..5fa1cc9 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -116,8 +116,8 @@
          * </pre>
          * </p>
          */
-        public static final String EXTRA_CALL_TYPE_FILTER
-                = "android.provider.extra.call_type_filter";
+        public static final String EXTRA_CALL_TYPE_FILTER =
+                "android.provider.extra.CALL_TYPE_FILTER";
 
         /**
          * Content uri used to access call log entries, including voicemail records. You must have
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 27473e3..18a9eb1 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1125,7 +1125,7 @@
          * import android.provider.ContactsContract.Contacts;
          *
          * Uri uri = Contacts.CONTENT_URI.buildUpon()
-         *          .appendQueryParameter(Contacts.ADDRESS_BOOK_INDEX_EXTRAS, "true")
+         *          .appendQueryParameter(Contacts.EXTRA_ADDRESS_BOOK_INDEX, "true")
          *          .build();
          * Cursor cursor = getContentResolver().query(uri,
          *          new String[] {Contacts.DISPLAY_NAME},
@@ -1140,21 +1140,24 @@
          * </pre>
          * </p>
          */
-        public static final String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
+        public static final String EXTRA_ADDRESS_BOOK_INDEX =
+                "android.provider.extra.ADDRESS_BOOK_INDEX";
 
         /**
          * The array of address book index titles, which are returned in the
          * same order as the data in the cursor.
          * <p>TYPE: String[]</p>
          */
-        public static final String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+        public static final String EXTRA_ADDRESS_BOOK_INDEX_TITLES =
+                "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
 
         /**
          * The array of group counts for the corresponding group.  Contains the same number
          * of elements as the EXTRA_ADDRESS_BOOK_INDEX_TITLES array.
          * <p>TYPE: int[]</p>
          */
-        public static final String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
+        public static final String EXTRA_ADDRESS_BOOK_INDEX_COUNTS =
+                "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
     }
 
     /**
@@ -8111,7 +8114,7 @@
          * for the provided {@link Contacts} entry.
          */
         public static final String ACTION_QUICK_CONTACT =
-                "com.android.contacts.action.QUICK_CONTACT";
+                "android.provider.action.QUICK_CONTACT";
 
         /**
          * Extra used to specify pivot dialog location in screen coordinates.
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index cb0bcf2..2ca8098 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -26,6 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -101,6 +102,7 @@
      *     <li>{@link Notification#EXTRA_LARGE_ICON extras[EXTRA_LARGE_ICON]}</li>
      *     <li>{@link Notification#EXTRA_LARGE_ICON_BIG extras[EXTRA_LARGE_ICON_BIG]}</li>
      *     <li>{@link Notification#EXTRA_PICTURE extras[EXTRA_PICTURE]}</li>
+     *     <li>{@link Notification#EXTRA_BIG_TEXT extras[EXTRA_BIG_TEXT]}</li>
      * </ol>
      *
      * @hide
@@ -692,10 +694,15 @@
      * current {@link RankingMap}.
      */
     public static class Ranking {
+        /** Value signifying that the user has not expressed a per-app visibility override value.
+         * @hide */
+        public static final int VISIBILITY_NO_OVERRIDE = -1000;
+
         private String mKey;
         private int mRank = -1;
         private boolean mIsAmbient;
         private boolean mMatchesInterruptionFilter;
+        private int mVisibilityOverride;
 
         public Ranking() {}
 
@@ -725,6 +732,17 @@
         }
 
         /**
+         * Returns the user specificed visibility for the package that posted
+         * this notification, or
+         * {@link NotificationListenerService.Ranking#VISIBILITY_NO_OVERRIDE} if
+         * no such preference has been expressed.
+         * @hide
+         */
+        public int getVisibilityOverride() {
+            return mVisibilityOverride;
+        }
+
+        /**
          * Returns whether the notification meets the user's interruption
          * filter.
          *
@@ -743,11 +761,12 @@
         }
 
         private void populate(String key, int rank, boolean isAmbient,
-                boolean matchesInterruptionFilter) {
+                boolean matchesInterruptionFilter, int visibilityOverride) {
             mKey = key;
             mRank = rank;
             mIsAmbient = isAmbient;
             mMatchesInterruptionFilter = matchesInterruptionFilter;
+            mVisibilityOverride = visibilityOverride;
         }
     }
 
@@ -763,6 +782,7 @@
         private final NotificationRankingUpdate mRankingUpdate;
         private ArrayMap<String,Integer> mRanks;
         private ArraySet<Object> mIntercepted;
+        private ArrayMap<String, Integer> mVisibilityOverrides;
 
         private RankingMap(NotificationRankingUpdate rankingUpdate) {
             mRankingUpdate = rankingUpdate;
@@ -787,7 +807,8 @@
          */
         public boolean getRanking(String key, Ranking outRanking) {
             int rank = getRank(key);
-            outRanking.populate(key, rank, isAmbient(key), !isIntercepted(key));
+            outRanking.populate(key, rank, isAmbient(key), !isIntercepted(key),
+                    getVisibilityOverride(key));
             return rank >= 0;
         }
 
@@ -819,6 +840,19 @@
             return mIntercepted.contains(key);
         }
 
+        private int getVisibilityOverride(String key) {
+            synchronized (this) {
+                if (mVisibilityOverrides == null) {
+                    buildVisibilityOverridesLocked();
+                }
+            }
+            Integer overide = mVisibilityOverrides.get(key);
+            if (overide == null) {
+                return Ranking.VISIBILITY_NO_OVERRIDE;
+            }
+            return overide.intValue();
+        }
+
         // Locked by 'this'
         private void buildRanksLocked() {
             String[] orderedKeys = mRankingUpdate.getOrderedKeys();
@@ -836,6 +870,15 @@
             Collections.addAll(mIntercepted, dndInterceptedKeys);
         }
 
+        // Locked by 'this'
+        private void buildVisibilityOverridesLocked() {
+            Bundle visibilityBundle = mRankingUpdate.getVisibilityOverrides();
+            mVisibilityOverrides = new ArrayMap<>(visibilityBundle.size());
+            for (String key: visibilityBundle.keySet()) {
+               mVisibilityOverrides.put(key, visibilityBundle.getInt(key));
+            }
+        }
+
         // ----------- Parcelable
 
         @Override
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index 26af38b..6fba900 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -15,6 +15,7 @@
  */
 package android.service.notification;
 
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -26,18 +27,21 @@
     private final String[] mKeys;
     private final String[] mInterceptedKeys;
     private final int mFirstAmbientIndex;
+    private final Bundle mVisibilityOverrides;
 
     public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
-                                     int firstAmbientIndex) {
+            Bundle visibilityOverrides, int firstAmbientIndex) {
         mKeys = keys;
         mFirstAmbientIndex = firstAmbientIndex;
         mInterceptedKeys = interceptedKeys;
+        mVisibilityOverrides = visibilityOverrides;
     }
 
     public NotificationRankingUpdate(Parcel in) {
         mKeys = in.readStringArray();
         mFirstAmbientIndex = in.readInt();
         mInterceptedKeys = in.readStringArray();
+        mVisibilityOverrides = in.readBundle();
     }
 
     @Override
@@ -50,6 +54,7 @@
         out.writeStringArray(mKeys);
         out.writeInt(mFirstAmbientIndex);
         out.writeStringArray(mInterceptedKeys);
+        out.writeBundle(mVisibilityOverrides);
     }
 
     public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -74,4 +79,8 @@
     public String[] getInterceptedKeys() {
         return mInterceptedKeys;
     }
+
+    public Bundle getVisibilityOverrides() {
+        return mVisibilityOverrides;
+    }
 }
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 519bc28..4de5f41 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -450,7 +450,7 @@
      * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
      * Starting re-enrollment is only valid if the keyphrase is un-enrolled,
      * i.e. {@link #STATE_KEYPHRASE_UNENROLLED},
-     * otherwise {@link #createIntentToReEnroll()} should be preferred.
+     * otherwise {@link #createReEnrollIntent()} should be preferred.
      *
      * @return An {@link Intent} to start enrollment for the given keyphrase.
      * @throws UnsupportedOperationException if managing they keyphrase isn't supported.
@@ -460,6 +460,19 @@
      *         This may happen if another detector has been instantiated or the
      *         {@link VoiceInteractionService} hosting this detector has been shut down.
      */
+    public Intent createEnrollIntent() {
+        if (DBG) Slog.d(TAG, "createEnrollIntent");
+        synchronized (mLock) {
+            return getManageIntentLocked(MANAGE_ACTION_ENROLL);
+        }
+    }
+
+    /**
+     * FIXME: Remove once the prebuilts are updated.
+     *
+     * @hide
+     */
+    @Deprecated
     public Intent createIntentToEnroll() {
         if (DBG) Slog.d(TAG, "createIntentToEnroll");
         synchronized (mLock) {
@@ -481,6 +494,19 @@
      *         This may happen if another detector has been instantiated or the
      *         {@link VoiceInteractionService} hosting this detector has been shut down.
      */
+    public Intent createUnEnrollIntent() {
+        if (DBG) Slog.d(TAG, "createUnEnrollIntent");
+        synchronized (mLock) {
+            return getManageIntentLocked(MANAGE_ACTION_UN_ENROLL);
+        }
+    }
+
+    /**
+     * FIXME: Remove once the prebuilts are updated.
+     *
+     * @hide
+     */
+    @Deprecated
     public Intent createIntentToUnEnroll() {
         if (DBG) Slog.d(TAG, "createIntentToUnEnroll");
         synchronized (mLock) {
@@ -502,6 +528,19 @@
      *         This may happen if another detector has been instantiated or the
      *         {@link VoiceInteractionService} hosting this detector has been shut down.
      */
+    public Intent createReEnrollIntent() {
+        if (DBG) Slog.d(TAG, "createReEnrollIntent");
+        synchronized (mLock) {
+            return getManageIntentLocked(MANAGE_ACTION_RE_ENROLL);
+        }
+    }
+
+    /**
+     * FIXME: Remove once the prebuilts are updated.
+     *
+     * @hide
+     */
+    @Deprecated
     public Intent createIntentToReEnroll() {
         if (DBG) Slog.d(TAG, "createIntentToReEnroll");
         synchronized (mLock) {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 7dce348..2b53c48 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -727,10 +727,9 @@
         int[] runs = dirs.mDirections;
         int lineStart = getLineStart(line);
         for (int i = 0; i < runs.length; i += 2) {
-            int start = lineStart + (runs[i] & RUN_LENGTH_MASK);
-            // No need to test the end as an offset after the last run should return the value
-            // corresponding of the last run
-            if (offset >= start) {
+            int start = lineStart + runs[i];
+            int limit = start + (runs[i+1] & RUN_LENGTH_MASK);
+            if (offset >= start && offset < limit) {
                 int level = (runs[i+1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK;
                 return ((level & 1) != 0);
             }
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 679e2cc..3222dbf 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -116,7 +116,8 @@
 
     /**
      * Move the cursor to the buffer offset physically above the current
-     * offset, or return false if the cursor is already on the top line.
+     * offset, to the beginning if it is on the top line but not at the
+     * start, or return false if the cursor is already on the top line.
      */
     public static boolean moveUp(Spannable text, Layout layout) {
         int start = getSelectionStart(text);
@@ -149,6 +150,9 @@
 
                 setSelection(text, move);
                 return true;
+            } else if (end != 0) {
+                setSelection(text, 0);
+                return true;
             }
         }
 
@@ -157,7 +161,9 @@
 
     /**
      * Move the cursor to the buffer offset physically below the current
-     * offset, or return false if the cursor is already on the bottom line.
+     * offset, to the end of the buffer if it is on the bottom line but
+     * not at the end, or return false if the cursor is already at the
+     * end of the buffer.
      */
     public static boolean moveDown(Spannable text, Layout layout) {
         int start = getSelectionStart(text);
@@ -190,6 +196,9 @@
 
                 setSelection(text, move);
                 return true;
+            } else if (end != text.length()) {
+                setSelection(text, text.length());
+                return true;
             }
         }
 
diff --git a/core/java/android/transition/ArcMotion.java b/core/java/android/transition/ArcMotion.java
index a27063d..f95fb49 100644
--- a/core/java/android/transition/ArcMotion.java
+++ b/core/java/android/transition/ArcMotion.java
@@ -41,9 +41,9 @@
  * {@code
  * &lt;changeBounds>
  *   &lt;arcMotion android:minimumHorizontalAngle="15"
- *     android:minimumVerticalAngle="0" android:maximumAngle="90"/>
- * &lt;/changeBounds>
- * }
+ *              android:minimumVerticalAngle="0"
+ *              android:maximumAngle="90"/>
+ * &lt;/changeBounds>}
  * </pre>
  */
 public class ArcMotion extends PathMotion {
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index d579f54..1b8d57c 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -45,6 +45,10 @@
     private static final String PROPNAME_TRANSFORMS = "android:changeTransform:transforms";
     private static final String PROPNAME_PARENT = "android:changeTransform:parent";
     private static final String PROPNAME_PARENT_MATRIX = "android:changeTransform:parentMatrix";
+    private static final String PROPNAME_INTERMEDIATE_PARENT_MATRIX =
+            "android:changeTransform:intermediateParentMatrix";
+    private static final String PROPNAME_INTERMEDIATE_MATRIX =
+            "android:changeTransform:intermediateMatrix";
 
     private static final String[] sTransitionProperties = {
             PROPNAME_MATRIX,
@@ -95,6 +99,7 @@
      * @return <code>true</code> when a changed parent should execute the transition
      * inside the scene root's overlay or <code>false</code> if a parent change only
      * affects the transform of the transitioning view.
+     * @attr ref android.R.styleable#ChangeTransform_reparentWithOverlay
      */
     public boolean getReparentWithOverlay() {
         return mUseOverlay;
@@ -116,6 +121,7 @@
      * @return <code>true</code> when a changed parent should execute the transition
      * inside the scene root's overlay or <code>false</code> if a parent change only
      * affects the transform of the transitioning view.
+     * @attr ref android.R.styleable#ChangeTransform_reparentWithOverlay
      */
     public void setReparentWithOverlay(boolean reparentWithOverlay) {
         mUseOverlay = reparentWithOverlay;
@@ -128,6 +134,7 @@
      * view will be tracked. Default is true.
      *
      * @return whether parent changes will be tracked by the ChangeTransform.
+     * @attr ref android.R.styleable#ChangeTransform_reparent
      */
     public boolean getReparent() {
         return mReparent;
@@ -141,6 +148,7 @@
      *
      * @param reparent Set to true to track parent changes or false to only track changes
      *                 of the transitioning view without considering the parent change.
+     * @attr ref android.R.styleable#ChangeTransform_reparent
      */
     public void setReparent(boolean reparent) {
         mReparent = reparent;
@@ -172,6 +180,10 @@
             parent.transformMatrixToGlobal(parentMatrix);
             parentMatrix.preTranslate(-parent.getScrollX(), -parent.getScrollY());
             transitionValues.values.put(PROPNAME_PARENT_MATRIX, parentMatrix);
+            transitionValues.values.put(PROPNAME_INTERMEDIATE_MATRIX,
+                    view.getTag(R.id.transitionTransform));
+            transitionValues.values.put(PROPNAME_INTERMEDIATE_PARENT_MATRIX,
+                    view.getTag(R.id.parentMatrix));
         }
         return;
     }
@@ -199,12 +211,13 @@
         ViewGroup endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
         boolean handleParentChange = mReparent && !parentsMatch(startParent, endParent);
 
-        Matrix startMatrix = (Matrix) startValues.view.getTag(R.id.transitionTransform);
+        Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_INTERMEDIATE_MATRIX);
         if (startMatrix != null) {
             startValues.values.put(PROPNAME_MATRIX, startMatrix);
         }
 
-        Matrix startParentMatrix = (Matrix) startValues.view.getTag(R.id.parentMatrix);
+        Matrix startParentMatrix = (Matrix)
+                startValues.values.get(PROPNAME_INTERMEDIATE_PARENT_MATRIX);
         if (startParentMatrix != null) {
             startValues.values.put(PROPNAME_PARENT_MATRIX, startParentMatrix);
         }
@@ -250,9 +263,11 @@
         ObjectAnimator animator = ObjectAnimator.ofObject(view, ANIMATION_MATRIX_PROPERTY,
                 new TransitionUtils.MatrixEvaluator(), startMatrix, endMatrix);
 
+        final Matrix finalEndMatrix = endMatrix;
+
         AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
             private boolean mIsCanceled;
-            private Matrix mTempMatrix;
+            private Matrix mTempMatrix = new Matrix();
 
             @Override
             public void onAnimationCancel(Animator animation) {
@@ -262,8 +277,7 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 if (!mIsCanceled) {
-                    view.setTagInternal(R.id.transitionTransform, null);
-                    view.setTagInternal(R.id.parentMatrix, null);
+                    setCurrentMatrix(finalEndMatrix);
                 }
                 ANIMATION_MATRIX_PROPERTY.set(view, null);
                 transforms.restore(view);
@@ -273,19 +287,19 @@
             public void onAnimationPause(Animator animation) {
                 ValueAnimator animator = (ValueAnimator) animation;
                 Matrix currentMatrix = (Matrix) animator.getAnimatedValue();
-                if (mTempMatrix == null) {
-                    mTempMatrix = new Matrix(currentMatrix);
-                } else {
-                    mTempMatrix.set(currentMatrix);
-                }
-                view.setTagInternal(R.id.transitionTransform, mTempMatrix);
-                transforms.restore(view);
+                setCurrentMatrix(currentMatrix);
             }
 
             @Override
             public void onAnimationResume(Animator animation) {
                 setIdentityTransforms(view);
             }
+
+            private void setCurrentMatrix(Matrix currentMatrix) {
+                mTempMatrix.set(currentMatrix);
+                view.setTagInternal(R.id.transitionTransform, mTempMatrix);
+                transforms.restore(view);
+            }
         };
 
         animator.addListener(listener);
@@ -423,6 +437,8 @@
         public void onTransitionEnd(Transition transition) {
             transition.removeListener(this);
             GhostView.removeGhost(mView);
+            mView.setTagInternal(R.id.transitionTransform, null);
+            mView.setTagInternal(R.id.parentMatrix, null);
         }
 
         @Override
diff --git a/core/java/android/transition/PatternMotion.java b/core/java/android/transition/PatternPathMotion.java
similarity index 68%
rename from core/java/android/transition/PatternMotion.java
rename to core/java/android/transition/PatternPathMotion.java
index e4045b4..a609df6 100644
--- a/core/java/android/transition/PatternMotion.java
+++ b/core/java/android/transition/PatternPathMotion.java
@@ -34,36 +34,35 @@
  * <pre>
  * {@code
  * &lt;changeBounds>
- *     &lt;patternMotion android:pathData="M0 0 L0 100 L100 100"/>
- * &lt;/changeBounds>
- * }
+ *     &lt;patternPathMotion android:patternPathData="M0 0 L0 100 L100 100"/>
+ * &lt;/changeBounds>}
  * </pre>
  */
-public class PatternMotion extends PathMotion {
+public class PatternPathMotion extends PathMotion {
 
-    private Path mOriginalPattern;
+    private Path mOriginalPatternPath;
 
-    private final Path mPattern = new Path();
+    private final Path mPatternPath = new Path();
 
     private final Matrix mTempMatrix = new Matrix();
 
     /**
-     * Constructs a PatternMotion with a straight-line pattern.
+     * Constructs a PatternPathMotion with a straight-line pattern.
      */
-    public PatternMotion() {
-        mPattern.lineTo(1, 0);
-        mOriginalPattern = mPattern;
+    public PatternPathMotion() {
+        mPatternPath.lineTo(1, 0);
+        mOriginalPatternPath = mPatternPath;
     }
 
-    public PatternMotion(Context context, AttributeSet attrs) {
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PatternMotion);
+    public PatternPathMotion(Context context, AttributeSet attrs) {
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PatternPathMotion);
         try {
-            String pathData = a.getString(R.styleable.PatternMotion_pathData);
+            String pathData = a.getString(R.styleable.PatternPathMotion_patternPathData);
             if (pathData == null) {
-                throw new RuntimeException("pathData must be supplied for patternMotion");
+                throw new RuntimeException("pathData must be supplied for patternPathMotion");
             }
             Path pattern = PathParser.createPathFromPathData(pathData);
-            setPattern(pattern);
+            setPatternPath(pattern);
         } finally {
             a.recycle();
         }
@@ -71,14 +70,15 @@
     }
 
     /**
-     * Creates a PatternMotion with the Path defining a pattern of motion between two coordinates.
-     * The pattern will be translated, rotated, and scaled to fit between the start and end points.
-     * The pattern must not be empty and must have the end point differ from the start point.
+     * Creates a PatternPathMotion with the Path defining a pattern of motion between two
+     * coordinates. The pattern will be translated, rotated, and scaled to fit between the start
+     * and end points. The pattern must not be empty and must have the end point differ from the
+     * start point.
      *
-     * @param pattern A Path to be used as a pattern for two-dimensional motion.
+     * @param patternPath A Path to be used as a pattern for two-dimensional motion.
      */
-    public PatternMotion(Path pattern) {
-        setPattern(pattern);
+    public PatternPathMotion(Path patternPath) {
+        setPatternPath(patternPath);
     }
 
     /**
@@ -87,10 +87,10 @@
      * The pattern must not be empty and must have the end point differ from the start point.
      *
      * @return the Path defining a pattern of motion between two coordinates.
-     * @attr ref android.R.styleable#PatternMotion_pathData
+     * @attr ref android.R.styleable#PatternPathMotion_patternPathData
      */
-    public Path getPattern() {
-        return mOriginalPattern;
+    public Path getPatternPath() {
+        return mOriginalPatternPath;
     }
 
     /**
@@ -98,11 +98,11 @@
      * The pattern will be translated, rotated, and scaled to fit between the start and end points.
      * The pattern must not be empty and must have the end point differ from the start point.
      *
-     * @param pattern A Path to be used as a pattern for two-dimensional motion.
-     * @attr ref android.R.styleable#PatternMotion_pathData
+     * @param patternPath A Path to be used as a pattern for two-dimensional motion.
+     * @attr ref android.R.styleable#PatternPathMotion_patternPathData
      */
-    public void setPattern(Path pattern) {
-        PathMeasure pathMeasure = new PathMeasure(pattern, false);
+    public void setPatternPath(Path patternPath) {
+        PathMeasure pathMeasure = new PathMeasure(patternPath, false);
         float length = pathMeasure.getLength();
         float[] pos = new float[2];
         pathMeasure.getPosTan(length, pos, null);
@@ -124,8 +124,8 @@
         mTempMatrix.postScale(scale, scale);
         double angle = Math.atan2(dy, dx);
         mTempMatrix.postRotate((float) Math.toDegrees(-angle));
-        pattern.transform(mTempMatrix, mPattern);
-        mOriginalPattern = pattern;
+        patternPath.transform(mTempMatrix, mPatternPath);
+        mOriginalPatternPath = patternPath;
     }
 
     @Override
@@ -139,7 +139,7 @@
         mTempMatrix.postRotate((float) Math.toDegrees(angle));
         mTempMatrix.postTranslate(startX, startY);
         Path path = new Path();
-        mPattern.transform(mTempMatrix, path);
+        mPatternPath.transform(mTempMatrix, path);
         return path;
     }
 
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index bd52e71..0d1b568 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1989,8 +1989,33 @@
      *     by extending PathMotion and implementing
      *     {@link android.transition.PathMotion#getPath(float, float, float, float)}.
      * </p>
+     * <p>
+     *     When describing in XML, use a nested XML tag for the path motion. It can be one of
+     *     the built-in tags <code>arcMotion</code> or <code>patternPathMotion</code> or it can
+     *     be a custom PathMotion using <code>pathMotion</code> with the <code>class</code>
+     *     attributed with the fully-described class name. For example:</p>
+     * <pre>
+     * {@code
+     * &lt;changeBounds>
+     *     &lt;pathMotion class="my.app.transition.MyPathMotion"/>
+     * &lt;/changeBounds>
+     * }
+     * </pre>
+     * <p>or</p>
+     * <pre>
+     * {@code
+     * &lt;changeBounds>
+     *   &lt;arcMotion android:minimumHorizontalAngle="15"
+     *     android:minimumVerticalAngle="0" android:maximumAngle="90"/>
+     * &lt;/changeBounds>
+     * }
+     * </pre>
+     *
      * @param pathMotion Algorithm object to use for determining how to interpolate in two
      *                   dimensions. If null, a straight-path algorithm will be used.
+     * @see android.transition.ArcMotion
+     * @see PatternPathMotion
+     * @see android.transition.PathMotion
      */
     public void setPathMotion(PathMotion pathMotion) {
         if (pathMotion == null) {
@@ -2004,7 +2029,31 @@
      * Returns the algorithm object used to interpolate along two dimensions. This is typically
      * used to determine the View motion between two points.
      *
+     * <p>
+     *     When describing in XML, use a nested XML tag for the path motion. It can be one of
+     *     the built-in tags <code>arcMotion</code> or <code>patternPathMotion</code> or it can
+     *     be a custom PathMotion using <code>pathMotion</code> with the <code>class</code>
+     *     attributed with the fully-described class name. For example:</p>
+     * <pre>
+     * {@code
+     * &lt;changeBounds>
+     *     &lt;pathMotion class="my.app.transition.MyPathMotion"/>
+     * &lt;/changeBounds>}
+     * </pre>
+     * <p>or</p>
+     * <pre>
+     * {@code
+     * &lt;changeBounds>
+     *   &lt;arcMotion android:minimumHorizontalAngle="15"
+     *              android:minimumVerticalAngle="0"
+     *              android:maximumAngle="90"/>
+     * &lt;/changeBounds>}
+     * </pre>
+     *
      * @return The algorithm object used to interpolate along two dimensions.
+     * @see android.transition.ArcMotion
+     * @see PatternPathMotion
+     * @see android.transition.PathMotion
      */
     public PathMotion getPathMotion() {
         return mPathMotion;
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 760ffe1..9009d6a 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -171,8 +171,8 @@
                 parent.setPathMotion(new ArcMotion(mContext, attrs));
             } else if ("pathMotion".equals(name)) {
                 parent.setPathMotion((PathMotion)createCustom(attrs, PathMotion.class, "pathMotion"));
-            } else if ("patternMotion".equals(name)) {
-                parent.setPathMotion(new PatternMotion(mContext, attrs));
+            } else if ("patternPathMotion".equals(name)) {
+                parent.setPathMotion(new PatternPathMotion(mContext, attrs));
             } else {
                 throw new RuntimeException("Unknown scene name: " + parser.getName());
             }
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index ce3cc2f..7bd6287 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -182,11 +182,15 @@
 
         final ViewGroup sceneRoot = scene.getSceneRoot();
 
-        Transition transitionClone = transition.clone();
-        transitionClone.setSceneRoot(sceneRoot);
+        Transition transitionClone = null;
+        if (transition != null) {
+            transitionClone = transition.clone();
+            transitionClone.setSceneRoot(sceneRoot);
+        }
 
         Scene oldScene = Scene.getCurrentScene(sceneRoot);
-        if (oldScene != null && oldScene.isCreatedFromLayoutResource()) {
+        if (oldScene != null && transitionClone != null &&
+                oldScene.isCreatedFromLayoutResource()) {
             transitionClone.setCanRemoveViews(true);
         }
 
diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java
index b0c9e9a..a84ecd1 100644
--- a/core/java/android/transition/TransitionUtils.java
+++ b/core/java/android/transition/TransitionUtils.java
@@ -40,6 +40,33 @@
         }
     }
 
+    public static Transition mergeTransitions(Transition... transitions) {
+        int count = 0;
+        int nonNullIndex = -1;
+        for (int i = 0; i < transitions.length; i++) {
+            if (transitions[i] != null) {
+                count++;
+                nonNullIndex = i;
+            }
+        }
+
+        if (count == 0) {
+            return null;
+        }
+
+        if (count == 1) {
+            return transitions[nonNullIndex];
+        }
+
+        TransitionSet transitionSet = new TransitionSet();
+        for (int i = 0; i < transitions.length; i++) {
+            if (transitions[i] != null) {
+                transitionSet.addTransition(transitions[i]);
+            }
+        }
+        return transitionSet;
+    }
+
     public static class MatrixEvaluator implements TypeEvaluator<Matrix> {
 
         float[] mTempStartValues = new float[9];
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 477c994..a10dda3 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.Region;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -96,7 +97,7 @@
     }
 
     public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
-            long accessibilityNodeId, int interactionId,
+            long accessibilityNodeId, Region interactiveRegion, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
             long interrogatingTid, MagnificationSpec spec) {
         Message message = mHandler.obtainMessage();
@@ -109,6 +110,7 @@
         args.argi3 = interactionId;
         args.arg1 = callback;
         args.arg2 = spec;
+        args.arg3 = interactiveRegion;
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -133,6 +135,7 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
         final MagnificationSpec spec = (MagnificationSpec) args.arg2;
+        final Region interactiveRegion = (Region) args.arg3;
 
         args.recycle();
 
@@ -159,6 +162,7 @@
                 if (spec != null) {
                     spec.recycle();
                 }
+                adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
                 callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
                 infos.clear();
             } catch (RemoteException re) {
@@ -168,8 +172,9 @@
     }
 
     public void findAccessibilityNodeInfosByViewIdClientThread(long accessibilityNodeId,
-            String viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-            int flags, int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+            String viewId, Region interactiveRegion, int interactionId,
+            IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+            long interrogatingTid, MagnificationSpec spec) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID;
         message.arg1 = flags;
@@ -180,6 +185,7 @@
         args.arg1 = callback;
         args.arg2 = spec;
         args.arg3 = viewId;
+        args.arg4 = interactiveRegion;
 
         message.obj = args;
 
@@ -205,6 +211,7 @@
             (IAccessibilityInteractionConnectionCallback) args.arg1;
         final MagnificationSpec spec = (MagnificationSpec) args.arg2;
         final String viewId = (String) args.arg3;
+        final Region interactiveRegion = (Region) args.arg4;
 
         args.recycle();
 
@@ -241,6 +248,7 @@
                 if (spec != null) {
                     spec.recycle();
                 }
+                adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
                 callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -249,8 +257,9 @@
     }
 
     public void findAccessibilityNodeInfosByTextClientThread(long accessibilityNodeId,
-            String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
-            int flags, int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+            String text, Region interactiveRegion, int interactionId,
+            IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
+            long interrogatingTid, MagnificationSpec spec) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
         message.arg1 = flags;
@@ -262,6 +271,7 @@
         args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
         args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.argi3 = interactionId;
+        args.arg4 = interactiveRegion;
         message.obj = args;
 
         // If the interrogation is performed by the same thread as the main UI
@@ -287,6 +297,7 @@
         final int accessibilityViewId = args.argi1;
         final int virtualDescendantId = args.argi2;
         final int interactionId = args.argi3;
+        final Region interactiveRegion = (Region) args.arg4;
         args.recycle();
 
         List<AccessibilityNodeInfo> infos = null;
@@ -347,6 +358,7 @@
                 if (spec != null) {
                     spec.recycle();
                 }
+                adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
                 callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -354,7 +366,8 @@
         }
     }
 
-    public void findFocusClientThread(long accessibilityNodeId, int focusType, int interactionId,
+    public void findFocusClientThread(long accessibilityNodeId, int focusType,
+            Region interactiveRegion, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
             long interrogatingTid, MagnificationSpec spec) {
         Message message = mHandler.obtainMessage();
@@ -368,6 +381,7 @@
         args.argi3 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
         args.arg1 = callback;
         args.arg2 = spec;
+        args.arg3 = interactiveRegion;
 
         message.obj = args;
 
@@ -394,6 +408,7 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
         final MagnificationSpec spec = (MagnificationSpec) args.arg2;
+        final Region interactiveRegion = (Region) args.arg3;
         args.recycle();
 
         AccessibilityNodeInfo focused = null;
@@ -457,6 +472,7 @@
                 if (spec != null) {
                     spec.recycle();
                 }
+                adjustIsVisibleToUserIfNeeded(focused, interactiveRegion);
                 callback.setFindAccessibilityNodeInfoResult(focused, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -464,7 +480,8 @@
         }
     }
 
-    public void focusSearchClientThread(long accessibilityNodeId, int direction, int interactionId,
+    public void focusSearchClientThread(long accessibilityNodeId, int direction,
+            Region interactiveRegion, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
             long interrogatingTid, MagnificationSpec spec) {
         Message message = mHandler.obtainMessage();
@@ -477,6 +494,7 @@
         args.argi3 = interactionId;
         args.arg1 = callback;
         args.arg2 = spec;
+        args.arg3 = interactiveRegion;
 
         message.obj = args;
 
@@ -502,6 +520,7 @@
         final IAccessibilityInteractionConnectionCallback callback =
             (IAccessibilityInteractionConnectionCallback) args.arg1;
         final MagnificationSpec spec = (MagnificationSpec) args.arg2;
+        final Region interactiveRegion = (Region) args.arg3;
 
         args.recycle();
 
@@ -530,6 +549,7 @@
                 if (spec != null) {
                     spec.recycle();
                 }
+                adjustIsVisibleToUserIfNeeded(next, interactiveRegion);
                 callback.setFindAccessibilityNodeInfoResult(next, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -644,6 +664,30 @@
         }
     }
 
+    private void adjustIsVisibleToUserIfNeeded(List<AccessibilityNodeInfo> infos,
+            Region interactiveRegion) {
+        if (interactiveRegion == null || infos == null) {
+            return;
+        }
+        final int infoCount = infos.size();
+        for (int i = 0; i < infoCount; i++) {
+            AccessibilityNodeInfo info = infos.get(i);
+            adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
+        }
+    }
+
+    private void adjustIsVisibleToUserIfNeeded(AccessibilityNodeInfo info,
+            Region interactiveRegion) {
+        if (interactiveRegion == null || info == null) {
+            return;
+        }
+        Rect boundsInScreen = mTempRect;
+        info.getBoundsInScreen(boundsInScreen);
+        if (interactiveRegion.quickReject(boundsInScreen)) {
+            info.setVisibleToUser(false);
+        }
+    }
+
     private void applyAppScaleAndMagnificationSpecIfNeeded(AccessibilityNodeInfo info,
             MagnificationSpec spec) {
         if (info == null) {
diff --git a/core/java/android/view/FrameStats.java b/core/java/android/view/FrameStats.java
index 541b336..b3ac1db 100644
--- a/core/java/android/view/FrameStats.java
+++ b/core/java/android/view/FrameStats.java
@@ -28,7 +28,10 @@
      */
     public static final long UNDEFINED_TIME_NANO = -1;
 
+    /** @hide */
     protected long mRefreshPeriodNano;
+
+    /** @hide */
     protected long[] mFramesPresentedTimeNano;
 
     /**
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index ceea9f8..076f1e2 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -800,28 +800,6 @@
     }
 
     @Override
-    public void drawPicture(Picture picture, Rect dst) {
-        save();
-        translate(dst.left, dst.top);
-        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
-            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
-        }
-        drawPicture(picture);
-        restore();
-    }
-
-    @Override
-    public void drawPicture(Picture picture, RectF dst) {
-        save();
-        translate(dst.left, dst.top);
-        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
-            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
-        }
-        drawPicture(picture);
-        restore();
-    }
-
-    @Override
     public void drawPoint(float x, float y, Paint paint) {
         float[] point = getPointStorage();
         point[0] = x;
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 964b054..0701b53 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -660,8 +660,96 @@
     /** Key code constant: Voice Assist key.
      * Launches the global voice assist activity. Not delivered to applications. */
     public static final int KEYCODE_VOICE_ASSIST = 231;
+    /** Key code constant: Radio key.
+     * Toggles TV service / Radio service. */
+    public static final int KEYCODE_TV_RADIO_SERVICE = 232;
+    /** Key code constant: Teletext key.
+     * Displays Teletext service. */
+    public static final int KEYCODE_TV_TELETEXT = 233;
+    /** Key code constant: Number entry key.
+     * Initiates to enter multi-digit channel nubmber when each digit key is assigned
+     * for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC
+     * User Control Code. */
+    public static final int KEYCODE_TV_NUMBER_ENTRY = 234;
+    /** Key code constant: Analog Terrestrial key.
+     * Switches to analog terrestrial broadcast service. */
+    public static final int KEYCODE_TV_TERRESTRIAL_ANALOG = 235;
+    /** Key code constant: Digital Terrestrial key.
+     * Switches to digital terrestrial broadcast service. */
+    public static final int KEYCODE_TV_TERRESTRIAL_DIGITAL = 236;
+    /** Key code constant: Satellite key.
+     * Switches to digital satellite broadcast service. */
+    public static final int KEYCODE_TV_SATELLITE = 237;
+    /** Key code constant: BS key.
+     * Switches to BS digital satellite broadcasting service available in Japan. */
+    public static final int KEYCODE_TV_SATELLITE_BS = 238;
+    /** Key code constant: CS key.
+     * Switches to CS digital satellite broadcasting service available in Japan. */
+    public static final int KEYCODE_TV_SATELLITE_CS = 239;
+    /** Key code constant: BS/CS key.
+     * Toggles between BS and CS digital satellite services. */
+    public static final int KEYCODE_TV_SATELLITE_SERVICE = 240;
+    /** Key code constant: Toggle Network key.
+     * Toggles selecting broacast services. */
+    public static final int KEYCODE_TV_NETWORK = 241;
+    /** Key code constant: Antenna/Cable key.
+     * Toggles broadcast input source between antenna and cable. */
+    public static final int KEYCODE_TV_ANTENNA_CABLE = 242;
+    /** Key code constant: HDMI #1 key.
+     * Switches to HDMI input #1. */
+    public static final int KEYCODE_TV_INPUT_HDMI_1 = 243;
+    /** Key code constant: HDMI #2 key.
+     * Switches to HDMI input #2. */
+    public static final int KEYCODE_TV_INPUT_HDMI_2 = 244;
+    /** Key code constant: HDMI #3 key.
+     * Switches to HDMI input #3. */
+    public static final int KEYCODE_TV_INPUT_HDMI_3 = 245;
+    /** Key code constant: HDMI #4 key.
+     * Switches to HDMI input #4. */
+    public static final int KEYCODE_TV_INPUT_HDMI_4 = 246;
+    /** Key code constant: Composite #1 key.
+     * Switches to composite video input #1. */
+    public static final int KEYCODE_TV_INPUT_COMPOSITE_1 = 247;
+    /** Key code constant: Composite #2 key.
+     * Switches to composite video input #2. */
+    public static final int KEYCODE_TV_INPUT_COMPOSITE_2 = 248;
+    /** Key code constant: Component #1 key.
+     * Switches to component video input #1. */
+    public static final int KEYCODE_TV_INPUT_COMPONENT_1 = 249;
+    /** Key code constant: Component #2 key.
+     * Switches to component video input #2. */
+    public static final int KEYCODE_TV_INPUT_COMPONENT_2 = 250;
+    /** Key code constant: VGA #1 key.
+     * Switches to VGA (analog RGB) input #1. */
+    public static final int KEYCODE_TV_INPUT_VGA_1 = 251;
+    /** Key code constant: Audio description key.
+     * Toggles audio description off / on. */
+    public static final int KEYCODE_TV_AUDIO_DESCRIPTION = 252;
+    /** Key code constant: Audio description mixing volume up key.
+     * Louden audio description volume as compared with normal audio volume. */
+    public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253;
+    /** Key code constant: Audio description mixing volume down key.
+     * Lessen audio description volume as compared with normal audio volume. */
+    public static final int KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254;
+    /** Key code constant: Zoom mode key.
+     * Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.) */
+    public static final int KEYCODE_TV_ZOOM_MODE = 255;
+    /** Key code constant: Contents menu key.
+     * Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control
+     * Code */
+    public static final int KEYCODE_TV_CONTENTS_MENU = 256;
+    /** Key code constant: Media context menu key.
+     * Goes to the context menu of media contents. Corresponds to Media Context-sensitive
+     * Menu (0x11) of CEC User Control Code. */
+    public static final int KEYCODE_TV_MEDIA_CONTEXT_MENU = 257;
+    /** Key code constant: Timer programming key.
+     * Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of
+     * CEC User Control Code. */
+    public static final int KEYCODE_TV_TIMER_PROGRAMMING = 258;
+    /** Key code constant: Help key. */
+    public static final int KEYCODE_HELP = 259;
 
-    private static final int LAST_KEYCODE = KEYCODE_VOICE_ASSIST;
+    private static final int LAST_KEYCODE = KEYCODE_HELP;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 063a08d..7dcad68 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -149,9 +149,9 @@
      * Creates a custom pointer from the given bitmap and hotspot information.
      *
      * @param bitmap The bitmap for the icon.
-     * @param hotspotX The X offset of the pointer icon hotspot in the bitmap.
+     * @param hotSpotX The X offset of the pointer icon hotspot in the bitmap.
      *        Must be within the [0, bitmap.getWidth()) range.
-     * @param hotspotY The Y offset of the pointer icon hotspot in the bitmap.
+     * @param hotSpotY The Y offset of the pointer icon hotspot in the bitmap.
      *        Must be within the [0, bitmap.getHeight()) range.
      * @return A pointer icon for this bitmap.
      *
@@ -374,18 +374,18 @@
     }
 
     private void loadResource(Context context, Resources resources, int resourceId) {
-        XmlResourceParser parser = resources.getXml(resourceId);
+        final XmlResourceParser parser = resources.getXml(resourceId);
         final int bitmapRes;
         final float hotSpotX;
         final float hotSpotY;
         try {
             XmlUtils.beginDocument(parser, "pointer-icon");
 
-            TypedArray a = resources.obtainAttributes(
+            final TypedArray a = resources.obtainAttributes(
                     parser, com.android.internal.R.styleable.PointerIcon);
             bitmapRes = a.getResourceId(com.android.internal.R.styleable.PointerIcon_bitmap, 0);
-            hotSpotX = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0);
-            hotSpotY = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0);
+            hotSpotX = a.getDimension(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0);
+            hotSpotY = a.getDimension(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0);
             a.recycle();
         } catch (Exception ex) {
             throw new IllegalArgumentException("Exception parsing pointer icon resource.", ex);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index ca08ecc..5d2822d 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -126,7 +126,7 @@
     void destroy() {
         mInitialized = false;
         updateEnabledState(null);
-        nDestroyCanvasAndSurface(mNativeProxy);
+        nDestroy(mNativeProxy);
     }
 
     private void updateEnabledState(Surface surface) {
@@ -488,7 +488,7 @@
     private static native void nSetOpaque(long nativeProxy, boolean opaque);
     private static native int nSyncAndDrawFrame(long nativeProxy,
             long frameTimeNanos, long recordDuration, float density);
-    private static native void nDestroyCanvasAndSurface(long nativeProxy);
+    private static native void nDestroy(long nativeProxy);
     private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
 
     private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fce6f0b..92ad4e8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -444,16 +444,19 @@
  * <a name="Drawing"></a>
  * <h3>Drawing</h3>
  * <p>
- * Drawing is handled by walking the tree and rendering each view that
- * intersects the invalid region. Because the tree is traversed in-order,
- * this means that parents will draw before (i.e., behind) their children, with
- * siblings drawn in the order they appear in the tree.
- * If you set a background drawable for a View, then the View will draw it for you
- * before calling back to its <code>onDraw()</code> method.
+ * Drawing is handled by walking the tree and recording the drawing commands of
+ * any View that needs to update. After this, the drawing commands of the
+ * entire tree are issued to screen, clipped to the newly damaged area.
  * </p>
  *
  * <p>
- * Note that the framework will not draw views that are not in the invalid region.
+ * The tree is largely recorded and drawn in order, with parents drawn before
+ * (i.e., behind) their children, with siblings drawn in the order they appear
+ * in the tree. If you set a background drawable for a View, then the View will
+ * draw it before calling back to its <code>onDraw()</code> method. The child
+ * drawing order can be overridden with
+ * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
+ * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
  * </p>
  *
  * <p>
@@ -4908,36 +4911,11 @@
             }
 
             onFocusChanged(true, direction, previouslyFocusedRect);
-            manageFocusHotspot(true, oldFocus);
             refreshDrawableState();
         }
     }
 
     /**
-     * Forwards focus information to the background drawable, if necessary. When
-     * the view is gaining focus, <code>v</code> is the previous focus holder.
-     * When the view is losing focus, <code>v</code> is the next focus holder.
-     *
-     * @param focused whether this view is focused
-     * @param v previous or the next focus holder, or null if none
-     */
-    private void manageFocusHotspot(boolean focused, View v) {
-        final Rect r = new Rect();
-        if (v != null && mAttachInfo != null) {
-            v.getHotspotBounds(r);
-            final int[] location = mAttachInfo.mTmpLocation;
-            getLocationOnScreen(location);
-            r.offset(-location[0], -location[1]);
-        } else {
-            r.set(0, 0, mRight - mLeft, mBottom - mTop);
-        }
-
-        final float x = r.exactCenterX();
-        final float y = r.exactCenterY();
-        drawableHotspotChanged(x, y);
-    }
-
-    /**
      * Populates <code>outRect</code> with the hotspot bounds. By default,
      * the hotspot bounds are identical to the screen bounds.
      *
@@ -5060,8 +5038,6 @@
             }
 
             onFocusChanged(false, 0, null);
-
-            manageFocusHotspot(false, focused);
             refreshDrawableState();
 
             if (propagate && (!refocus || !rootViewRequestFocus())) {
@@ -10852,6 +10828,12 @@
     /**
      * Sets whether the View's Outline should be used to clip the contents of the View.
      * <p>
+     * Only a single non-rectangular clip can be applied on a View at any time.
+     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
+     * circular reveal} animation take priority over Outline clipping, and
+     * child Outline clipping takes priority over Outline clipping done by a
+     * parent.
+     * <p>
      * Note that this flag will only be respected if the View's Outline returns true from
      * {@link Outline#canClip()}.
      *
@@ -15118,10 +15100,12 @@
             bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
         }
 
+        canvas.save();
         canvas.translate(mScrollX, mScrollY);
+        canvas.clipRect(bounds, Region.Op.REPLACE);
         drawable.setBounds(bounds);
         drawable.draw(canvas);
-        canvas.translate(-mScrollX, -mScrollY);
+        canvas.restore();
     }
 
     /**
diff --git a/core/java/android/view/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java
index 7ced088..001cd01 100644
--- a/core/java/android/view/ViewAnimationUtils.java
+++ b/core/java/android/view/ViewAnimationUtils.java
@@ -27,9 +27,13 @@
     private ViewAnimationUtils() {}
     /**
      * Returns an Animator which can animate a clipping circle.
-     *
+     * <p>
      * Any shadow cast by the View will respect the circular clip from this animator.
-     *
+     * <p>
+     * Only a single non-rectangular clip can be applied on a View at any time.
+     * Views clipped by a circular reveal animation take priority over
+     * {@link View#setClipToOutline(boolean) View Outline clipping}.
+     * <p>
      * Note that the animation returned here is a one-shot animation. It cannot
      * be re-used, and once started it cannot be paused or resumed.
      *
@@ -39,7 +43,7 @@
      * @param startRadius The starting radius of the animating circle.
      * @param endRadius The ending radius of the animating circle.
      */
-    public static final Animator createCircularReveal(View view,
+    public static Animator createCircularReveal(View view,
             int centerX,  int centerY, float startRadius, float endRadius) {
         return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
     }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index adad082..974fe4e 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5034,6 +5034,9 @@
     /**
      * Tells the ViewGroup whether to draw its children in the order defined by the method
      * {@link #getChildDrawingOrder(int, int)}.
+     * <p>
+     * Note that {@link View#getZ() Z} reordering, done by {@link #dispatchDraw(Canvas)},
+     * will override custom child ordering done via this method.
      *
      * @param enabled true if the order of the children when drawing is determined by
      *        {@link #getChildDrawingOrder(int, int)}, false otherwise
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 49d925f..4299e2e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -6111,6 +6111,33 @@
                     }
                 }
             } break;
+
+
+            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());
+                            mAccessibilityFocusedVirtualView = provider.createAccessibilityNodeInfo(
+                                    virtualChildId);
+                        }
+                    }
+                }
+            } break;
         }
         mAccessibilityManager.sendAccessibilityEvent(event);
         return true;
@@ -6629,14 +6656,15 @@
 
         @Override
         public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+                Region interactiveRegion, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId,
-                            interactionId, callback, flags, interrogatingPid, interrogatingTid,
-                            spec);
+                            interactiveRegion, interactionId, callback, flags, interrogatingPid,
+                            interrogatingTid, spec);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -6669,15 +6697,15 @@
 
         @Override
         public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
-                String viewId, int interactionId,
+                String viewId, Region interactiveRegion, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfosByViewIdClientThread(accessibilityNodeId,
-                            viewId, interactionId, callback, flags, interrogatingPid,
-                            interrogatingTid, spec);
+                            viewId, interactiveRegion, interactionId, callback, flags,
+                            interrogatingPid, interrogatingTid, spec);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -6690,14 +6718,15 @@
 
         @Override
         public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
-                int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+                Region interactiveRegion, int interactionId,
+                IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfosByTextClientThread(accessibilityNodeId, text,
-                            interactionId, callback, flags, interrogatingPid, interrogatingTid,
-                            spec);
+                            interactiveRegion, interactionId, callback, flags, interrogatingPid,
+                            interrogatingTid, spec);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -6709,14 +6738,15 @@
         }
 
         @Override
-        public void findFocus(long accessibilityNodeId, int focusType, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, int flags,
+        public void findFocus(long accessibilityNodeId, int focusType, Region interactiveRegion,
+                int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
-                    .findFocusClientThread(accessibilityNodeId, focusType, interactionId, callback,
-                            flags, interrogatingPid, interrogatingTid, spec);
+                    .findFocusClientThread(accessibilityNodeId, focusType, interactiveRegion,
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid,
+                            spec);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
@@ -6728,14 +6758,15 @@
         }
 
         @Override
-        public void focusSearch(long accessibilityNodeId, int direction, int interactionId,
-                IAccessibilityInteractionConnectionCallback callback, int flags,
+        public void focusSearch(long accessibilityNodeId, int direction, Region interactiveRegion,
+                int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
                 int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
-                    .focusSearchClientThread(accessibilityNodeId, direction, interactionId,
-                            callback, flags, interrogatingPid, interrogatingTid, spec);
+                    .focusSearchClientThread(accessibilityNodeId, direction, interactiveRegion,
+                            interactionId, callback, flags, interrogatingPid, interrogatingTid,
+                            spec);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 9b6f200..ebc683a 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1430,7 +1430,9 @@
      * {@link android.transition.Visibility} as entering is governed by changing visibility from
      * {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null,
      * entering Views will remain unaffected.
+     *
      * @param transition The Transition to use to move Views into the initial Scene.
+     * @attr ref android.R.styleable#Window_windowEnterTransition
      */
     public void setEnterTransition(Transition transition) {}
 
@@ -1444,8 +1446,10 @@
      * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null,
      * entering Views will remain unaffected. If nothing is set, the default will be to
      * use the same value as set in {@link #setEnterTransition(android.transition.Transition)}.
+     *
      * @param transition The Transition to use to move Views out of the Scene when the Window
      *                   is preparing to close.
+     * @attr ref android.R.styleable#Window_windowReturnTransition
      */
     public void setReturnTransition(Transition transition) {}
 
@@ -1456,8 +1460,10 @@
      * {@link android.transition.Visibility} as exiting is governed by changing visibility
      * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
      * remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
      * @param transition The Transition to use to move Views out of the scene when calling a
      *                   new Activity.
+     * @attr ref android.R.styleable#Window_windowExitTransition
      */
     public void setExitTransition(Transition transition) {}
 
@@ -1470,8 +1476,10 @@
      * the views will remain unaffected. If nothing is set, the default will be to use the same
      * transition as {@link #setExitTransition(android.transition.Transition)}.
      * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
      * @param transition The Transition to use to move Views into the scene when reentering from a
      *                   previously-started Activity.
+     * @attr ref android.R.styleable#Window_windowReenterTransition
      */
     public void setReenterTransition(Transition transition) {}
 
@@ -1484,6 +1492,7 @@
      * entering Views will remain unaffected.  Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
      *
      * @return the Transition to use to move Views into the initial Scene.
+     * @attr ref android.R.styleable#Window_windowEnterTransition
      */
     public Transition getEnterTransition() { return null; }
 
@@ -1495,8 +1504,10 @@
      * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
      * {@link android.transition.Visibility} as entering is governed by changing visibility from
      * {@link View#VISIBLE} to {@link View#INVISIBLE}.
+     *
      * @return The Transition to use to move Views out of the Scene when the Window
      *         is preparing to close.
+     * @attr ref android.R.styleable#Window_windowReturnTransition
      */
     public Transition getReturnTransition() { return null; }
 
@@ -1507,8 +1518,10 @@
      * {@link android.transition.Visibility} as exiting is governed by changing visibility
      * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
      * remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
      * @return the Transition to use to move Views out of the scene when calling a
      * new Activity.
+     * @attr ref android.R.styleable#Window_windowExitTransition
      */
     public Transition getExitTransition() { return null; }
 
@@ -1519,8 +1532,10 @@
      * will extend {@link android.transition.Visibility} as exiting is governed by changing
      * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}.
      * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
      * @return The Transition to use to move Views into the scene when reentering from a
      *         previously-started Activity.
+     * @attr ref android.R.styleable#Window_windowReenterTransition
      */
     public Transition getReenterTransition() { return null; }
 
@@ -1530,8 +1545,10 @@
      * {@link android.transition.ChangeBounds}. A null
      * value will cause transferred shared elements to blink to the final position.
      * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
      * @param transition The Transition to use for shared elements transferred into the content
      *                   Scene.
+     * @attr ref android.R.styleable#Window_windowSharedElementEnterTransition
      */
     public void setSharedElementEnterTransition(Transition transition) {}
 
@@ -1543,22 +1560,28 @@
      * If no value is set, the default will be to use the same value as
      * {@link #setSharedElementEnterTransition(android.transition.Transition)}.
      * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
      * @param transition The Transition to use for shared elements transferred out of the content
      *                   Scene.
+     * @attr ref android.R.styleable#Window_windowSharedElementReturnTransition
      */
     public void setSharedElementReturnTransition(Transition transition) {}
 
     /**
      * Returns the Transition that will be used for shared elements transferred into the content
      * Scene. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
      * @return Transition to use for sharend elements transferred into the content Scene.
+     * @attr ref android.R.styleable#Window_windowSharedElementEnterTransition
      */
     public Transition getSharedElementEnterTransition() { return null; }
 
     /**
      * Returns the Transition that will be used for shared elements transferred back to a
      * calling Activity. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
      * @return Transition to use for sharend elements transferred into the content Scene.
+     * @attr ref android.R.styleable#Window_windowSharedElementReturnTransition
      */
     public Transition getSharedElementReturnTransition() { return null; }
 
@@ -1568,8 +1591,10 @@
      * must animate during the exit transition, this Transition should be used. Upon completion,
      * the shared elements may be transferred to the started Activity.
      * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
      * @param transition The Transition to use for shared elements in the launching Window
      *                   prior to transferring to the launched Activity's Window.
+     * @attr ref android.R.styleable#Window_windowSharedElementExitTransition
      */
     public void setSharedElementExitTransition(Transition transition) {}
 
@@ -1579,8 +1604,10 @@
      * is set, this will default to
      * {@link #setSharedElementExitTransition(android.transition.Transition)}.
      * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
      * @param transition The Transition to use for shared elements in the launching Window
      *                   after the shared element has returned to the Window.
+     * @attr ref android.R.styleable#Window_windowSharedElementReenterTransition
      */
     public void setSharedElementReenterTransition(Transition transition) {}
 
@@ -1591,6 +1618,7 @@
      *
      * @return the Transition to use for shared elements in the launching Window prior
      * to transferring to the launched Activity's Window.
+     * @attr ref android.R.styleable#Window_windowSharedElementExitTransition
      */
     public Transition getSharedElementExitTransition() { return null; }
 
@@ -1601,6 +1629,7 @@
      *
      * @return the Transition that will be used for shared elements reentering from a started
      * Activity after it has returned the shared element to it start location.
+     * @attr ref android.R.styleable#Window_windowSharedElementReenterTransition
      */
     public Transition getSharedElementReenterTransition() { return null; }
 
@@ -1610,8 +1639,10 @@
      * transition of the calling Activity. When true, the transition will start as soon as possible.
      * When false, the transition will wait until the remote exiting transition completes before
      * starting.
+     *
      * @param allow true to start the enter transition when possible or false to
      *              wait until the exiting transition completes.
+     * @attr ref android.R.styleable#Window_windowAllowEnterTransitionOverlap
      */
     public void setAllowEnterTransitionOverlap(boolean allow) {}
 
@@ -1621,8 +1652,10 @@
      * transition of the calling Activity. When true, the transition will start as soon as possible.
      * When false, the transition will wait until the remote exiting transition completes before
      * starting.
+     *
      * @return true when the enter transition should start as soon as possible or false to
      * when it should wait until the exiting transition completes.
+     * @attr ref android.R.styleable#Window_windowAllowEnterTransitionOverlap
      */
     public boolean getAllowEnterTransitionOverlap() { return true; }
 
@@ -1632,10 +1665,20 @@
      * transition of the called Activity when reentering after if finishes. When true,
      * the transition will start as soon as possible. When false, the transition will wait
      * until the called Activity's exiting transition completes before starting.
+     *
      * @param allow true to start the transition when possible or false to wait until the
      *              called Activity's exiting transition completes.
+     * @attr ref android.R.styleable#Window_windowAllowReturnTransitionOverlap
      */
-    public void setAllowExitTransitionOverlap(boolean allow) {}
+    public void setAllowReturnTransitionOverlap(boolean allow) {}
+
+    /**
+     * TODO: remove this.
+     * @hide
+     */
+    public void setAllowExitTransitionOverlap(boolean allow) {
+        setAllowReturnTransitionOverlap(allow);
+    }
 
     /**
      * Returns how the transition set in
@@ -1643,10 +1686,18 @@
      * transition of the called Activity when reentering after if finishes. When true,
      * the transition will start as soon as possible. When false, the transition will wait
      * until the called Activity's exiting transition completes before starting.
+     *
      * @return true when the transition should start when possible or false when it should wait
      * until the called Activity's exiting transition completes.
+     * @attr ref android.R.styleable#Window_windowAllowReturnTransitionOverlap
      */
-    public boolean getAllowExitTransitionOverlap() { return true; }
+    public boolean getAllowReturnTransitionOverlap() { return true; }
+
+    /**
+     * TODO: remove this.
+     * @hide
+     */
+    public boolean getAllowExitTransitionOverlap() { return getAllowReturnTransitionOverlap(); }
 
     /**
      * Returns the duration, in milliseconds, of the window background fade
@@ -1654,8 +1705,10 @@
      * <p>When executing the enter transition, the background starts transparent
      * and fades in. This requires {@link #FEATURE_CONTENT_TRANSITIONS}. The default is
      * 300 milliseconds.</p>
+     *
      * @return The duration of the window background fade to opaque during enter transition.
      * @see #getEnterTransition()
+     * @attr ref android.R.styleable#Window_windowTransitionBackgroundFadeDuration
      */
     public long getTransitionBackgroundFadeDuration() { return 0; }
 
@@ -1665,9 +1718,11 @@
      * <p>When executing the enter transition, the background starts transparent
      * and fades in. This requires {@link #FEATURE_CONTENT_TRANSITIONS}. The default is
      * 300 milliseconds.</p>
+     *
      * @param fadeDurationMillis The duration of the window background fade to or from opaque
      *                           during enter transition.
      * @see #setEnterTransition(android.transition.Transition)
+     * @attr ref android.R.styleable#Window_windowTransitionBackgroundFadeDuration
      */
     public void setTransitionBackgroundFadeDuration(long fadeDurationMillis) { }
 
@@ -1679,6 +1734,7 @@
      * @return <code>true</code> when shared elements should use an Overlay during
      * shared element transitions or <code>false</code> when they should animate as
      * part of the normal View hierarchy.
+     * @attr ref android.R.styleable#Window_windowSharedElementsUseOverlay
      */
     public boolean getSharedElementsUseOverlay() { return true; }
 
@@ -1689,6 +1745,7 @@
      * @param sharedElementsUseOverlay <code>true</code> indicates that shared elements should
      *                                 be transitioned with an Overlay or <code>false</code>
      *                                 to transition within the normal View hierarchy.
+     * @attr ref android.R.styleable#Window_windowSharedElementsUseOverlay
      */
     public void setSharedElementsUseOverlay(boolean sharedElementsUseOverlay) { }
 
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 053fdd0..b7b12a8 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -379,6 +379,10 @@
         public static final int LID_CLOSED = 0;
         public static final int LID_OPEN = 1;
 
+        public static final int CAMERA_LENS_COVER_ABSENT = -1;
+        public static final int CAMERA_LENS_UNCOVERED = 0;
+        public static final int CAMERA_LENS_COVERED = 1;
+
         /**
          * Ask the window manager to re-evaluate the system UI flags.
          */
@@ -399,6 +403,11 @@
         public int getLidState();
 
         /**
+         * Returns a code that descripbes whether the camera lens is covered or not.
+         */
+        public int getCameraLensCoverState();
+
+        /**
          * Switch the keyboard layout for the given device.
          * Direction should be +1 or -1 to go to the next or previous keyboard layout.
          */
@@ -951,7 +960,14 @@
      * @param lidOpen True if the lid is now open.
      */
     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
-    
+
+    /**
+     * Tell the policy that the camera lens has been covered or uncovered.
+     * @param whenNanos The time when the change occurred in uptime nanoseconds.
+     * @param lensCovered True if the lens is covered.
+     */
+    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
+
     /**
      * Tell the policy if anyone is requesting that keyguard not come on.
      *
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 8d15472..faf7789 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -16,6 +16,7 @@
 
 package android.view.accessibility;
 
+import android.graphics.Region;
 import android.os.Bundle;
 import android.view.MagnificationSpec;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -29,23 +30,23 @@
  */
 oneway interface IAccessibilityInteractionConnection {
 
-    void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
-        long interrogatingTid, in MagnificationSpec spec);
-
-    void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, String viewId,
+    void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, in Region bounds,
         int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
         int interrogatingPid, long interrogatingTid, in MagnificationSpec spec);
 
-    void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int interactionId,
+    void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, String viewId,
+        in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback,
+        int flags, int interrogatingPid, long interrogatingTid, in MagnificationSpec spec);
+
+    void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, in Region bounds,
+        int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
+        int interrogatingPid, long interrogatingTid, in MagnificationSpec spec);
+
+    void findFocus(long accessibilityNodeId, int focusType, in Region bounds, int interactionId,
         IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
         long interrogatingTid, in MagnificationSpec spec);
 
-    void findFocus(long accessibilityNodeId, int focusType, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
-        long interrogatingTid, in MagnificationSpec spec);
-
-    void focusSearch(long accessibilityNodeId, int direction, int interactionId,
+    void focusSearch(long accessibilityNodeId, int direction, in Region bounds, int interactionId,
         IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
         long interrogatingTid, in MagnificationSpec spec);
 
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 4d2f57a..20adfe4 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -431,7 +431,15 @@
     /**
      * The default implementation does nothing.
      */
-    public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+    public boolean requestCursorUpdates(int cursorUpdateMode) {
+        return false;
+    }
+
+    /**
+     * The default implementation does nothing.
+     * @removed
+     */
+    public final boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
         return false;
     }
 
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
index 0492824..fe0f5b9 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfo.java
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -45,9 +45,9 @@
     private final CharSequence mComposingText;
 
     /**
-     * {@code True} if the insertion marker is partially or entirely clipped by other UI elements.
+     * Flags of the insertion marker. See {@link #FLAG_HAS_VISIBLE_REGION} for example.
      */
-    private final boolean mInsertionMarkerClipped;
+    private final int mInsertionMarkerFlags;
     /**
      * Horizontal position of the insertion marker, in the local coordinates that will be
      * transformed with the transformation matrix when rendered on the screen. This should be
@@ -90,27 +90,47 @@
      */
     private final Matrix mMatrix;
 
+    /**
+     * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+     * insertion marker or character bounds have at least one visible region.
+     */
+    public static final int FLAG_HAS_VISIBLE_REGION = 0x01;
+
+    /**
+     * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+     * insertion marker or character bounds have at least one invisible (clipped) region.
+     */
+    public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
+
+    /**
+     * @removed
+     */
     public static final int CHARACTER_RECT_TYPE_MASK = 0x0f;
     /**
      * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor did not specify any type of this
      * character. Editor authors should not use this flag.
+     * @removed
      */
     public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0;
     /**
      * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely visible.
+     * @removed
      */
     public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1;
     /**
      * Type for {@link #CHARACTER_RECT_TYPE_MASK}: some area of the character is invisible.
+     * @removed
      */
     public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2;
     /**
      * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely invisible.
+     * @removed
      */
     public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3;
     /**
      * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor gave up to calculate the rectangle
      * for this character. Input method authors should ignore the returned rectangle.
+     * @removed
      */
     public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4;
 
@@ -119,7 +139,7 @@
         mSelectionEnd = source.readInt();
         mComposingTextStart = source.readInt();
         mComposingText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
-        mInsertionMarkerClipped = (source.readInt() != 0);
+        mInsertionMarkerFlags = source.readInt();
         mInsertionMarkerHorizontal = source.readFloat();
         mInsertionMarkerTop = source.readFloat();
         mInsertionMarkerBaseline = source.readFloat();
@@ -141,7 +161,7 @@
         dest.writeInt(mSelectionEnd);
         dest.writeInt(mComposingTextStart);
         TextUtils.writeToParcel(mComposingText, dest, flags);
-        dest.writeInt(mInsertionMarkerClipped ? 1 : 0);
+        dest.writeInt(mInsertionMarkerFlags);
         dest.writeFloat(mInsertionMarkerHorizontal);
         dest.writeFloat(mInsertionMarkerTop);
         dest.writeFloat(mInsertionMarkerBaseline);
@@ -159,7 +179,7 @@
                 + mInsertionMarkerBaseline + mInsertionMarkerBottom;
         int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
         hash *= 31;
-        hash += (mInsertionMarkerClipped ? 2 : 1);
+        hash += mInsertionMarkerFlags;
         hash *= 31;
         hash += mSelectionStart + mSelectionEnd + mComposingTextStart;
         hash *= 31;
@@ -204,7 +224,7 @@
                 || !Objects.equals(mComposingText, that.mComposingText)) {
             return false;
         }
-        if (mInsertionMarkerClipped != that.mInsertionMarkerClipped
+        if (mInsertionMarkerFlags != that.mInsertionMarkerFlags
                 || !areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal)
                 || !areSameFloatImpl(mInsertionMarkerTop, that.mInsertionMarkerTop)
                 || !areSameFloatImpl(mInsertionMarkerBaseline, that.mInsertionMarkerBaseline)
@@ -225,7 +245,7 @@
         return "SelectionInfo{mSelection=" + mSelectionStart + "," + mSelectionEnd
                 + " mComposingTextStart=" + mComposingTextStart
                 + " mComposingText=" + Objects.toString(mComposingText)
-                + " mInsertionMarkerClipped=" + mInsertionMarkerClipped
+                + " mInsertionMarkerFlags=" + mInsertionMarkerFlags
                 + " mInsertionMarkerHorizontal=" + mInsertionMarkerHorizontal
                 + " mInsertionMarkerTop=" + mInsertionMarkerTop
                 + " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
@@ -272,6 +292,20 @@
         private CharSequence mComposingText = null;
 
         /**
+         * @removed
+         */
+        public Builder setInsertionMarkerLocation(final float horizontalPosition,
+                final float lineTop, final float lineBaseline, final float lineBottom,
+                final boolean clipped){
+            mInsertionMarkerHorizontal = horizontalPosition;
+            mInsertionMarkerTop = lineTop;
+            mInsertionMarkerBaseline = lineBaseline;
+            mInsertionMarkerBottom = lineBottom;
+            mInsertionMarkerFlags = clipped ? FLAG_HAS_INVISIBLE_REGION : 0;
+            return this;
+        }
+
+        /**
          * Sets the location of the text insertion point (zero width cursor) as a rectangle in
          * local coordinates. Calling this can be skipped when there is no text insertion point;
          * however if there is an insertion point, editors must call this method.
@@ -288,24 +322,24 @@
          * @param lineBottom vertical position of the insertion marker, in the local coordinates
          * that will be transformed with the transformation matrix when rendered on the screen. This
          * should be calculated or compatible with {@link Layout#getLineBottom(int)}.
-         * @param clipped {@code true} is the insertion marker is partially or entierly clipped by
-         * other UI elements.
+         * @param flags flags of the insertion marker. See {@link #FLAG_HAS_VISIBLE_REGION} for
+         * example.
          */
         public Builder setInsertionMarkerLocation(final float horizontalPosition,
                 final float lineTop, final float lineBaseline, final float lineBottom,
-                final boolean clipped){
+                final int flags){
             mInsertionMarkerHorizontal = horizontalPosition;
             mInsertionMarkerTop = lineTop;
             mInsertionMarkerBaseline = lineBaseline;
             mInsertionMarkerBottom = lineBottom;
-            mInsertionMarkerClipped = clipped;
+            mInsertionMarkerFlags = flags;
             return this;
         }
         private float mInsertionMarkerHorizontal = Float.NaN;
         private float mInsertionMarkerTop = Float.NaN;
         private float mInsertionMarkerBaseline = Float.NaN;
         private float mInsertionMarkerBottom = Float.NaN;
-        private boolean mInsertionMarkerClipped = false;
+        private int mInsertionMarkerFlags = 0;
 
         /**
          * Adds the bounding box of the character specified with the index.
@@ -320,8 +354,8 @@
          * coordinates, that is, right edge for LTR text and left edge for RTL text.
          * @param trailingEdgeY y coordinate of the trailing edge of the character in local
          * coordinates.
-         * @param flags type and flags for this character. See
-         * {@link #CHARACTER_RECT_TYPE_FULLY_VISIBLE} for example.
+         * @param flags flags for this character rect. See {@link #FLAG_HAS_VISIBLE_REGION} for
+         * example.
          * @throws IllegalArgumentException If the index is a negative value, or not greater than
          * all of the previously called indices.
          */
@@ -331,11 +365,6 @@
             if (index < 0) {
                 throw new IllegalArgumentException("index must not be a negative integer.");
             }
-            final int type = flags & CHARACTER_RECT_TYPE_MASK;
-            if (type == CHARACTER_RECT_TYPE_UNSPECIFIED) {
-                throw new IllegalArgumentException("Type except for "
-                        + "CHARACTER_RECT_TYPE_UNSPECIFIED must be specified.");
-            }
             if (mCharacterRectBuilder == null) {
                 mCharacterRectBuilder = new SparseRectFArrayBuilder();
             }
@@ -388,7 +417,7 @@
             mSelectionEnd = -1;
             mComposingTextStart = -1;
             mComposingText = null;
-            mInsertionMarkerClipped = false;
+            mInsertionMarkerFlags = 0;
             mInsertionMarkerHorizontal = Float.NaN;
             mInsertionMarkerTop = Float.NaN;
             mInsertionMarkerBaseline = Float.NaN;
@@ -406,7 +435,7 @@
         mSelectionEnd = builder.mSelectionEnd;
         mComposingTextStart = builder.mComposingTextStart;
         mComposingText = builder.mComposingText;
-        mInsertionMarkerClipped = builder.mInsertionMarkerClipped;
+        mInsertionMarkerFlags = builder.mInsertionMarkerFlags;
         mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal;
         mInsertionMarkerTop = builder.mInsertionMarkerTop;
         mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
@@ -449,11 +478,20 @@
     }
 
     /**
+     * Returns the flag of the insertion marker.
+     * @return the flag of the insertion marker. {@code 0} if no flag is specified.
+     */
+    public int getInsertionMarkerFlags() {
+        return mInsertionMarkerFlags;
+    }
+
+    /**
      * Returns the visibility of the insertion marker.
      * @return {@code true} if the insertion marker is partially or entirely clipped.
+     * @removed
      */
     public boolean isInsertionMarkerClipped() {
-        return mInsertionMarkerClipped;
+        return (mInsertionMarkerFlags & FLAG_HAS_VISIBLE_REGION) != 0;
     }
 
     /**
@@ -522,17 +560,17 @@
     }
 
     /**
-     * Returns the flags associated with the character specified with the index.
+     * Returns the flags associated with the character rect specified with the index.
      * @param index index of the character in a Java chars.
-     * @return {@link #CHARACTER_RECT_TYPE_UNSPECIFIED} if no flag is specified.
+     * @return {@code 0} if no flag is specified.
      */
     // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
     // characters, and non-graphical chars.
     public int getCharacterRectFlags(final int index) {
         if (mCharacterRects == null) {
-            return CHARACTER_RECT_TYPE_UNSPECIFIED;
+            return 0;
         }
-        return mCharacterRects.getFlags(index, CHARACTER_RECT_TYPE_UNSPECIFIED);
+        return mCharacterRects.getFlags(index, 0);
     }
 
     /**
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index ca094c1..093fb2f 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -728,31 +728,47 @@
      * The editor is requested to call
      * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at
      * once, as soon as possible, regardless of cursor/anchor position changes. This flag can be
-     * used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}.
+     * used together with {@link #CURSOR_UPDATE_MONITOR}.
      */
-    public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1 << 0;
+    public static final int CURSOR_UPDATE_IMMEDIATE = 1 << 0;
 
     /**
      * The editor is requested to call
      * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}
      * whenever cursor/anchor position is changed. To disable monitoring, call
-     * {@link InputConnection#requestUpdateCursorAnchorInfo(int)} again with this flag off.
+     * {@link InputConnection#requestCursorUpdates(int)} again with this flag off.
      * <p>
-     * This flag can be used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE}.
+     * This flag can be used together with {@link #CURSOR_UPDATE_IMMEDIATE}.
      * </p>
      */
-    public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 1 << 1;
+    public static final int CURSOR_UPDATE_MONITOR = 1 << 1;
 
     /**
      * Called by the input method to ask the editor for calling back
      * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} to
      * notify cursor/anchor locations.
      *
-     * @param cursorUpdateMode {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE} and/or
-     * {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}
+     * @param cursorUpdateMode {@link #CURSOR_UPDATE_IMMEDIATE} and/or
+     * {@link #CURSOR_UPDATE_MONITOR}. Pass {@code 0} to disable the effect of
+     * {@link #CURSOR_UPDATE_MONITOR}.
      * @return {@code true} if the request is scheduled. {@code false} to indicate that when the
      * application will not call
      * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}.
      */
+    public boolean requestCursorUpdates(int cursorUpdateMode);
+
+    /**
+     * @removed
+     */
+    public static final int REQUEST_UPDATE_CURSOR_UPDATE_IMMEDIATE = 1 << 0;
+
+    /**
+     * @removed
+     */
+    public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 1 << 1;
+
+    /**
+     * @removed
+     */
     public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode);
 }
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index d95df25..87853de 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -126,7 +126,14 @@
         return mTarget.performPrivateCommand(action, data);
     }
 
-    public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
-        return mTarget.requestUpdateCursorAnchorInfo(cursorUpdateMode);
+    public boolean requestCursorUpdates(int cursorUpdateMode) {
+        return mTarget.requestCursorUpdates(cursorUpdateMode);
     }
- }
+
+    /**
+     * @removed
+     */
+    public final boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+        return mTarget.requestCursorUpdates(cursorUpdateMode);
+    }
+}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 0a472c7..b56378f 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1526,7 +1526,7 @@
      * Return true if the current input method wants to watch the location
      * of the input editor's cursor in its window.
      *
-     * @deprecated Use {@link InputConnection#requestUpdateCursorAnchorInfo(int)} instead.
+     * @deprecated Use {@link InputConnection#requestCursorUpdates(int)} instead.
      */
     @Deprecated
     public boolean isWatchingCursor(View view) {
@@ -1542,9 +1542,9 @@
     public boolean isCursorAnchorInfoEnabled() {
         synchronized (mH) {
             final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
-                    InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
+                    InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
             final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode &
-                    InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR) != 0;
+                    InputConnection.CURSOR_UPDATE_MONITOR) != 0;
             return isImmediate || isMonitoring;
         }
     }
@@ -1608,7 +1608,7 @@
             // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
             // not been changed from the previous call.
             final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
-                    InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
+                    InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
             if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
                 // TODO: Consider always emitting this message once we have addressed redundant
                 // calls of this method from android.widget.Editor.
@@ -1624,7 +1624,7 @@
                 mCursorAnchorInfo = cursorAnchorInfo;
                 // Clear immediate bit (if any).
                 mRequestUpdateCursorAnchorInfoMonitorMode &=
-                        ~InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE;
+                        ~InputConnection.CURSOR_UPDATE_IMMEDIATE;
             } catch (RemoteException e) {
                 Log.w(TAG, "IME died: " + mCurId, e);
             }
diff --git a/core/java/android/webkit/WebResourceRequest.java b/core/java/android/webkit/WebResourceRequest.java
index dc7c808..b46ac9a 100644
--- a/core/java/android/webkit/WebResourceRequest.java
+++ b/core/java/android/webkit/WebResourceRequest.java
@@ -41,7 +41,7 @@
     boolean isForMainFrame();
 
     /**
-     * Gets whether a gesture was associated with the request.
+     * Gets whether a gesture (such as a link click) was associated with the request.
      * <p>
      * <strong>IMPORTANT:</strong>
      * This should not be used to implement any form of security. It is possible for the content
@@ -49,6 +49,11 @@
      *
      * @return whether a gesture was associated with the request.
      */
+    boolean hasGesture();
+
+    /*
+     * @removed
+     */
     boolean hasUserGestureInsecure();
 
     /**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index e1f19ee..081bfdf 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1810,21 +1810,6 @@
     }
 
     /**
-     * Sets whether the application wants to opt out from using the Data Reduction Proxy
-     * service.
-     * Data reduction proxy can only be enabled by the user and will almost always be
-     * transparent to the application. In rare cases where using the proxy interferes
-     * with the app, the application developer can use this API to opt out from using the
-     * proxy. Note that this may increase network bandwidth usage.
-     *
-     * See <a href=http://developer.chrome.com/multidevice/data-compression>
-     * Data Compression Proxy</a>
-     */
-    public static void optOutDataReductionProxy() {
-        getFactory().getStatics().optOutDataReductionProxy();
-    }
-
-    /**
      * Gets the list of currently loaded plugins.
      *
      * @return the list of currently loaded plugins
@@ -1954,16 +1939,14 @@
      *
      * @param zoomFactor the zoom factor to apply. The zoom factor will be clamped to the Webview's
      * zoom limits. This value must be in the range 0.01 to 100.0 inclusive.
-     *
-     * @return false if no zoom changes, true otherwise.
      */
-    public boolean zoomBy(float zoomFactor) {
+    public void zoomBy(float zoomFactor) {
         checkThread();
         if (zoomFactor < 0.01)
             throw new IllegalArgumentException("zoomFactor must be greater than 0.01.");
         if (zoomFactor > 100.0)
             throw new IllegalArgumentException("zoomFactor must be less than 100.");
-        return mProvider.zoomBy(zoomFactor);
+        mProvider.zoomBy(zoomFactor);
     }
 
     /**
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 48f3ca3..20bb932 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -61,12 +61,6 @@
 
         /**
          * Implements the API method:
-         * {@link android.webkit.WebView#optOutDataReductionProxy() }
-         */
-        void optOutDataReductionProxy();
-
-        /**
-         * Implements the API method:
          * {@link android.webkit.WebView#setSlowWholeDocumentDrawEnabled(boolean) }
          */
         void enableSlowWholeDocumentDraw();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index eb93745..eef8554 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -5717,8 +5717,16 @@
         }
 
         @Override
+        public boolean requestCursorUpdates(int cursorUpdateMode) {
+            return getTarget().requestCursorUpdates(cursorUpdateMode);
+        }
+
+        /**
+         * @removed
+         */
+        @Override
         public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
-            return getTarget().requestUpdateCursorAnchorInfo(cursorUpdateMode);
+            return getTarget().requestCursorUpdates(cursorUpdateMode);
         }
     }
 
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 96abf51..6ca4a9e 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -29,6 +29,7 @@
 import com.android.internal.view.menu.ActionMenuItemView;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuPresenter;
 import com.android.internal.view.menu.MenuView;
 
 /**
@@ -53,6 +54,8 @@
 
     private boolean mReserveOverflow;
     private ActionMenuPresenter mPresenter;
+    private MenuPresenter.Callback mActionMenuPresenterCallback;
+    private MenuBuilder.Callback mMenuBuilderCallback;
     private boolean mFormatItems;
     private int mFormatItemsWidth;
     private int mMinCellSize;
@@ -608,7 +611,8 @@
             mMenu = new MenuBuilder(context);
             mMenu.setCallback(new MenuBuilderCallback());
             mPresenter = new ActionMenuPresenter(context);
-            mPresenter.setCallback(new ActionMenuPresenterCallback());
+            mPresenter.setCallback(mActionMenuPresenterCallback != null
+                    ? mActionMenuPresenterCallback : new ActionMenuPresenterCallback());
             mMenu.addMenuPresenter(mPresenter, mPopupContext);
             mPresenter.setMenuView(this);
         }
@@ -617,6 +621,15 @@
     }
 
     /**
+     * Must be called before the first call to getMenu()
+     * @hide
+     */
+    public void setMenuCallbacks(MenuPresenter.Callback pcb, MenuBuilder.Callback mcb) {
+        mActionMenuPresenterCallback = pcb;
+        mMenuBuilderCallback = mcb;
+    }
+
+    /**
      * Returns the current menu or null if one has not yet been configured.
      * @hide Internal use only for action bar integration
      */
@@ -719,6 +732,9 @@
 
         @Override
         public void onMenuModeChange(MenuBuilder menu) {
+            if (mMenuBuilderCallback != null) {
+                mMenuBuilderCallback.onMenuModeChange(menu);
+            }
         }
     }
 
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 1da22ca..b9f891c 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -297,10 +297,10 @@
     public boolean performItemClick(View view, int position, long id) {
         if (mOnItemClickListener != null) {
             playSoundEffect(SoundEffectConstants.CLICK);
+            mOnItemClickListener.onItemClick(this, view, position, id);
             if (view != null) {
                 view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
             }
-            mOnItemClickListener.onItemClick(this, view, position, id);
             return true;
         }
 
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 26c1f96..2729bd0 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -71,9 +71,9 @@
  * @attr ref android.R.styleable#DatePicker_minDate
  * @attr ref android.R.styleable#DatePicker_spinnersShown
  * @attr ref android.R.styleable#DatePicker_calendarViewShown
- * @attr ref android.R.styleable#DatePicker_dayOfWeekBackgroundColor
+ * @attr ref android.R.styleable#DatePicker_dayOfWeekBackground
  * @attr ref android.R.styleable#DatePicker_dayOfWeekTextAppearance
- * @attr ref android.R.styleable#DatePicker_headerBackgroundColor
+ * @attr ref android.R.styleable#DatePicker_headerBackground
  * @attr ref android.R.styleable#DatePicker_headerMonthTextAppearance
  * @attr ref android.R.styleable#DatePicker_headerDayOfMonthTextAppearance
  * @attr ref android.R.styleable#DatePicker_headerYearTextAppearance
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 7df1fa3..eed49bf 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -21,7 +21,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.graphics.Color;
+import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.format.DateFormat;
@@ -149,16 +149,12 @@
             mDayOfWeekView.setTextAppearance(context, dayOfWeekTextAppearanceResId);
         }
 
-        final int dayOfWeekBackgroundColor = a.getColor(
-                R.styleable.DatePicker_dayOfWeekBackgroundColor, Color.TRANSPARENT);
-        mDayOfWeekView.setBackgroundColor(dayOfWeekBackgroundColor);
+        mDayOfWeekView.setBackground(a.getDrawable(R.styleable.DatePicker_dayOfWeekBackground));
+
+        dateLayout.setBackground(a.getDrawable(R.styleable.DatePicker_headerBackground));
 
         final int headerSelectedTextColor = a.getColor(
                 R.styleable.DatePicker_headerSelectedTextColor, defaultHighlightColor);
-        final int headerBackgroundColor = a.getColor(R.styleable.DatePicker_headerBackgroundColor,
-                Color.TRANSPARENT);
-        dateLayout.setBackgroundColor(headerBackgroundColor);
-
         final int monthTextAppearanceResId = a.getResourceId(
                 R.styleable.DatePicker_headerMonthTextAppearance, -1);
         if (monthTextAppearanceResId != -1) {
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 57b8dcb..033b99a 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -52,12 +52,15 @@
     private static final String TAG = "EdgeEffect";
 
     // Time it will take the effect to fully recede in ms
-    private static final int RECEDE_TIME = 1000;
+    private static final int RECEDE_TIME = 600;
 
     // Time it will take before a pulled glow begins receding in ms
     private static final int PULL_TIME = 167;
 
-    private static final float MAX_ALPHA = 1.f;
+    // Time it will take in ms for a pulled glow to decay to partial strength before release
+    private static final int PULL_DECAY_TIME = 2000;
+
+    private static final float MAX_ALPHA = 0.5f;
 
     private static final float MAX_GLOW_SCALE = 2.f;
 
@@ -93,12 +96,9 @@
     private static final int STATE_RECEDE = 3;
     private static final int STATE_PULL_DECAY = 4;
 
-    // How much dragging should effect the height of the glow image.
-    // Number determined by user testing.
-    private static final int PULL_DISTANCE_GLOW_FACTOR = 7;
-    private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 1.1f;
+    private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 0.8f;
 
-    private static final int VELOCITY_GLOW_FACTOR = 12;
+    private static final int VELOCITY_GLOW_FACTOR = 6;
 
     private int mState = STATE_IDLE;
 
@@ -107,7 +107,7 @@
     private final Rect mBounds = new Rect();
     private final Paint mPaint = new Paint();
     private float mRadius;
-    private float mBaseGlowHeight;
+    private float mBaseGlowScale;
     private float mDisplacement = 0.5f;
     private float mTargetDisplacement = 0.5f;
 
@@ -138,8 +138,12 @@
         final float r = width * 0.75f / SIN;
         final float y = COS * r;
         final float h = r - y;
+        final float or = height * 0.75f / SIN;
+        final float oy = COS * or;
+        final float oh = or - oy;
+
         mRadius = r;
-        mBaseGlowHeight = h;
+        mBaseGlowScale = h > 0 ? Math.min(oh / h, 1.f) : 1.f;
 
         mBounds.set(mBounds.left, mBounds.top, width, (int) Math.min(height, h));
     }
@@ -319,13 +323,14 @@
         final float centerX = mBounds.centerX();
         final float centerY = mBounds.height() - mRadius;
 
-        canvas.scale(1.f, Math.min(mGlowScaleY, 1.f), centerX, 0);
+        canvas.scale(1.f, Math.min(mGlowScaleY, 1.f) * mBaseGlowScale, centerX, 0);
 
         final float displacement = Math.max(0, Math.min(mDisplacement, 1.f)) - 0.5f;
         float translateX = mBounds.width() * displacement / 2;
 
         canvas.clipRect(mBounds);
         canvas.translate(translateX, 0);
+        mPaint.setAlpha((int) (0xff * mGlowAlpha));
         canvas.drawCircle(centerX, centerY, mRadius, mPaint);
         canvas.restoreToCount(count);
 
@@ -372,7 +377,16 @@
                     mGlowScaleYFinish = 0.f;
                     break;
                 case STATE_PULL:
-                    // Hold in this state until explicitly released.
+                    mState = STATE_PULL_DECAY;
+                    mStartTime = AnimationUtils.currentAnimationTimeMillis();
+                    mDuration = PULL_DECAY_TIME;
+
+                    mGlowAlphaStart = mGlowAlpha;
+                    mGlowScaleYStart = mGlowScaleY;
+
+                    // After pull, the glow should fade to nothing.
+                    mGlowAlphaFinish = 0.f;
+                    mGlowScaleYFinish = 0.f;
                     break;
                 case STATE_PULL_DECAY:
                     mState = STATE_RECEDE;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 46b225d..22138d0 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3089,13 +3089,12 @@
                     final boolean isLeadingEdgeTopVisible = isPositionVisible(leadingEdgeX, top);
                     final boolean isTrailingEdgeBottomVisible =
                             isPositionVisible(trailingEdgeX, bottom);
-                    final int characterRectFlags;
-                    if (isLeadingEdgeTopVisible && isTrailingEdgeBottomVisible) {
-                        characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE;
-                    } else if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) {
-                        characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE;
-                    } else {
-                        characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE;
+                    int characterRectFlags = 0;
+                    if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) {
+                        characterRectFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+                    }
+                    if (!isLeadingEdgeTopVisible || !isTrailingEdgeBottomVisible) {
+                        characterRectFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
                     }
                     // Here offset is the index in Java chars.
                     // TODO: We must have a well-defined specification. For example, how
@@ -3117,11 +3116,19 @@
                         + viewportToContentVerticalOffset;
                 final float insertionMarkerBottom = layout.getLineBottom(line)
                         + viewportToContentVerticalOffset;
-                // Take TextView's padding and scroll into account.
-                final boolean isClipped = !isPositionVisible(insertionMarkerX, insertionMarkerTop)
-                        || !isPositionVisible(insertionMarkerX, insertionMarkerBottom);
+                final boolean isTopVisible =
+                        isPositionVisible(insertionMarkerX, insertionMarkerTop);
+                final boolean isBottomVisible =
+                        isPositionVisible(insertionMarkerX, insertionMarkerBottom);
+                int insertionMarkerFlags = 0;
+                if (isTopVisible || isBottomVisible) {
+                    insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+                }
+                if (!isTopVisible || !isBottomVisible) {
+                    insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+                }
                 builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop,
-                        insertionMarkerBaseline, insertionMarkerBottom, isClipped);
+                        insertionMarkerBaseline, insertionMarkerBottom, insertionMarkerFlags);
             }
 
             imm.updateCursorAnchorInfo(mTextView, builder.build());
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index adca4cc..d2f68d0 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -458,6 +458,7 @@
         a.recycle();
 
         setOnTouchListener(this);
+        setClickable(true);
 
         // Initial values
         final Calendar calendar = Calendar.getInstance(Locale.getDefault());
@@ -612,9 +613,9 @@
             mMinutesTexts[i] = String.format("%02d", MINUTES_NUMBERS[i]);
         }
 
-        String[] amPmTexts = new DateFormatSymbols().getAmPmStrings();
-        mAmPmText[AM] = amPmTexts[0];
-        mAmPmText[PM] = amPmTexts[1];
+        String[] amPmStrings = TimePickerClockDelegate.getAmPmStrings(mContext);
+        mAmPmText[AM] = amPmStrings[0];
+        mAmPmText[PM] = amPmStrings[1];
     }
 
     private void initData() {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 69d5f40..90e9c69 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -22,11 +22,13 @@
 import android.app.PendingIntent;
 import android.appwidget.AppWidgetHostView;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
@@ -1653,8 +1655,10 @@
      *
      * @param application The application whose content is shown by the views.
      * @param layoutId The id of the layout resource.
+     *
+     * @hide
      */
-    private RemoteViews(ApplicationInfo application, int layoutId) {
+    protected RemoteViews(ApplicationInfo application, int layoutId) {
         mApplication = application;
         mLayoutId = layoutId;
         mBitmapCache = new BitmapCache();
@@ -2515,15 +2519,29 @@
         RemoteViews rvToApply = getRemoteViewsToApply(context);
 
         View result;
-
-        Context c = prepareContext(context);
+        // RemoteViews may be built by an application installed in another
+        // user. So build a context that loads resources from that user but
+        // still returns the current users userId so settings like data / time formats
+        // are loaded without requiring cross user persmissions.
+        final Context contextForResources = getContextForResources(context);
+        Context inflationContext = new ContextWrapper(context) {
+            @Override
+            public Resources getResources() {
+                return contextForResources.getResources();
+            }
+            @Override
+            public Resources.Theme getTheme() {
+                return contextForResources.getTheme();
+            }
+        };
 
         LayoutInflater inflater = (LayoutInflater)
-                c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
-        inflater = inflater.cloneInContext(c);
+        // Clone inflater so we load resources from correct context and
+        // we don't add a filter to the static version returned by getSystemService.
+        inflater = inflater.cloneInContext(inflationContext);
         inflater.setFilter(this);
-
         result = inflater.inflate(rvToApply.getLayoutId(), parent, false);
 
         rvToApply.performApply(result, parent, handler);
@@ -2557,7 +2575,6 @@
             }
         }
 
-        prepareContext(context);
         rvToApply.performApply(v, (ViewGroup) v.getParent(), handler);
     }
 
@@ -2572,7 +2589,7 @@
         }
     }
 
-    private Context prepareContext(Context context) {
+    private Context getContextForResources(Context context) {
         if (mApplication != null) {
             if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
                     && context.getPackageName().equals(mApplication.packageName)) {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 0a3c7ff..0289ccc 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -334,6 +334,10 @@
             setInputType(inputType);
         }
 
+        boolean focusable = true;
+        focusable = a.getBoolean(R.styleable.SearchView_focusable, focusable);
+        setFocusable(focusable);
+
         a.recycle();
 
         // Save voice intent for later queries/launching
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9b3a1e0..3e1b674 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1861,6 +1861,10 @@
             return getCompoundPaddingTop();
         }
 
+        if (mLayout == null) {
+            assumeLayout();
+        }
+
         if (mLayout.getLineCount() <= mMaximum) {
             return getCompoundPaddingTop();
         }
@@ -1894,6 +1898,10 @@
             return getCompoundPaddingBottom();
         }
 
+        if (mLayout == null) {
+            assumeLayout();
+        }
+
         if (mLayout.getLineCount() <= mMaximum) {
             return getCompoundPaddingBottom();
         }
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 6169d2e..73e05e8 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -21,7 +21,6 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.graphics.Color;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -40,7 +39,6 @@
 
 import com.android.internal.R;
 
-import java.text.DateFormatSymbols;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Locale;
@@ -71,6 +69,7 @@
 
     private static final int HOURS_IN_HALF_DAY = 12;
 
+    private View mHeaderView;
     private TextView mHourView;
     private TextView mMinuteView;
     private TextView mAmPmTextView;
@@ -156,11 +155,8 @@
             mAmPmTextView.setTextAppearance(context, headerAmPmTextAppearance);
         }
 
-        final int headerBackgroundColor = a.getColor(
-                R.styleable.TimePicker_headerBackgroundColor, Color.TRANSPARENT);
-        if (headerBackgroundColor != Color.TRANSPARENT) {
-            mainView.findViewById(R.id.time_header).setBackgroundColor(headerBackgroundColor);
-        }
+        mHeaderView = mainView.findViewById(R.id.time_header);
+        mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
 
         a.recycle();
 
@@ -194,14 +190,11 @@
     }
 
     private void setupListeners() {
-        KeyboardListener keyboardListener = new KeyboardListener();
-        mDelegator.setOnKeyListener(keyboardListener);
+        mHeaderView.setOnKeyListener(mKeyListener);
+        mHeaderView.setOnFocusChangeListener(mFocusListener);
+        mHeaderView.setFocusable(true);
 
-        mHourView.setOnKeyListener(keyboardListener);
-        mMinuteView.setOnKeyListener(keyboardListener);
-        mAmPmTextView.setOnKeyListener(keyboardListener);
         mRadialTimePickerView.setOnValueSelectedListener(this);
-        mRadialTimePickerView.setOnKeyListener(keyboardListener);
 
         mHourView.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -641,7 +634,7 @@
             if (!isTypedTimeFullyLegal()) {
                 mTypedTimes.clear();
             }
-            finishKbMode(true);
+            finishKbMode();
         }
     }
 
@@ -776,27 +769,7 @@
      * @return true if the key was successfully processed, false otherwise.
      */
     private boolean processKeyUp(int keyCode) {
-        if (keyCode == KeyEvent.KEYCODE_ESCAPE || keyCode == KeyEvent.KEYCODE_TAB) {
-            if(mInKbMode) {
-                if (isTypedTimeFullyLegal()) {
-                    finishKbMode(true);
-                }
-                return true;
-            }
-        } else if (keyCode == KeyEvent.KEYCODE_ENTER) {
-            if (mInKbMode) {
-                if (!isTypedTimeFullyLegal()) {
-                    return true;
-                }
-                finishKbMode(false);
-            }
-            if (mOnTimeChangedListener != null) {
-                mOnTimeChangedListener.onTimeChanged(mDelegator,
-                        mRadialTimePickerView.getCurrentHour(),
-                        mRadialTimePickerView.getCurrentMinute());
-            }
-            return true;
-        } else if (keyCode == KeyEvent.KEYCODE_DEL) {
+        if (keyCode == KeyEvent.KEYCODE_DEL) {
             if (mInKbMode) {
                 if (!mTypedTimes.isEmpty()) {
                     int deleted = deleteLastTypedKey();
@@ -925,9 +898,8 @@
 
     /**
      * Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time.
-     * @param updateDisplays If true, update the displays with the relevant time.
      */
-    private void finishKbMode(boolean updateDisplays) {
+    private void finishKbMode() {
         mInKbMode = false;
         if (!mTypedTimes.isEmpty()) {
             int values[] = getEnteredTime(null);
@@ -938,10 +910,8 @@
             }
             mTypedTimes.clear();
         }
-        if (updateDisplays) {
-            updateDisplay(false);
-            mRadialTimePickerView.setInputEnabled(true);
-        }
+        updateDisplay(false);
+        mRadialTimePickerView.setInputEnabled(true);
     }
 
     /**
@@ -1261,7 +1231,7 @@
         }
     }
 
-    private class KeyboardListener implements View.OnKeyListener {
+    private final View.OnKeyListener mKeyListener = new View.OnKeyListener() {
         @Override
         public boolean onKey(View v, int keyCode, KeyEvent event) {
             if (event.getAction() == KeyEvent.ACTION_UP) {
@@ -1269,5 +1239,20 @@
             }
             return false;
         }
-    }
+    };
+
+    private final View.OnFocusChangeListener mFocusListener = new View.OnFocusChangeListener() {
+        @Override
+        public void onFocusChange(View v, boolean hasFocus) {
+            if (!hasFocus && mInKbMode && isTypedTimeFullyLegal()) {
+                finishKbMode();
+
+                if (mOnTimeChangedListener != null) {
+                    mOnTimeChangedListener.onTimeChanged(mDelegator,
+                            mRadialTimePickerView.getCurrentHour(),
+                            mRadialTimePickerView.getCurrentMinute());
+                }
+            }
+        }
+    };
 }
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index ece8aa4..be28199 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -37,6 +37,7 @@
 import android.view.ViewGroup;
 
 import com.android.internal.R;
+import com.android.internal.app.ToolbarActionBar;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuItemImpl;
 import com.android.internal.view.menu.MenuPresenter;
@@ -153,6 +154,8 @@
     private ToolbarWidgetWrapper mWrapper;
     private ActionMenuPresenter mOuterActionMenuPresenter;
     private ExpandedActionViewMenuPresenter mExpandedMenuPresenter;
+    private MenuPresenter.Callback mActionMenuPresenterCallback;
+    private MenuBuilder.Callback mMenuBuilderCallback;
 
     private boolean mCollapsible;
 
@@ -248,11 +251,12 @@
         final Drawable navIcon = a.getDrawable(R.styleable.Toolbar_navigationIcon);
         if (navIcon != null) {
             setNavigationIcon(navIcon);
-            final CharSequence navDesc = a.getText(
-                    R.styleable.Toolbar_navigationContentDescription);
-            if (!TextUtils.isEmpty(navDesc)) {
-                setNavigationContentDescription(navDesc);
-            }
+        }
+
+        final CharSequence navDesc = a.getText(
+                R.styleable.Toolbar_navigationContentDescription);
+        if (!TextUtils.isEmpty(navDesc)) {
+            setNavigationContentDescription(navDesc);
         }
         a.recycle();
     }
@@ -824,6 +828,7 @@
             mMenuView = new ActionMenuView(getContext());
             mMenuView.setPopupTheme(mPopupTheme);
             mMenuView.setOnMenuItemClickListener(mMenuViewItemClickListener);
+            mMenuView.setMenuCallbacks(mActionMenuPresenterCallback, mMenuBuilderCallback);
             final LayoutParams lp = generateDefaultLayoutParams();
             lp.gravity = Gravity.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
             mMenuView.setLayoutParams(lp);
@@ -1677,6 +1682,15 @@
     }
 
     /**
+     * Must be called before the menu is accessed
+     * @hide
+     */
+    public void setMenuCallbacks(MenuPresenter.Callback pcb, MenuBuilder.Callback mcb) {
+        mActionMenuPresenterCallback = pcb;
+        mMenuBuilderCallback = mcb;
+    }
+
+    /**
      * Interface responsible for receiving menu item click events if the items themselves
      * do not have individual item click listeners.
      */
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index c409520..6d5c98e 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -63,63 +63,46 @@
     private final Context mContext;
     private final DialogInterface mDialogInterface;
     private final Window mWindow;
-    
+
     private CharSequence mTitle;
-
     private CharSequence mMessage;
-
     private ListView mListView;
-    
     private View mView;
 
     private int mViewLayoutResId;
 
     private int mViewSpacingLeft;
-    
     private int mViewSpacingTop;
-    
     private int mViewSpacingRight;
-    
     private int mViewSpacingBottom;
-    
     private boolean mViewSpacingSpecified = false;
-    
+
     private Button mButtonPositive;
-
     private CharSequence mButtonPositiveText;
-
     private Message mButtonPositiveMessage;
 
     private Button mButtonNegative;
-
     private CharSequence mButtonNegativeText;
-
     private Message mButtonNegativeMessage;
 
     private Button mButtonNeutral;
-
     private CharSequence mButtonNeutralText;
-
     private Message mButtonNeutralMessage;
 
     private ScrollView mScrollView;
-    
+
     private int mIconId = 0;
-    
     private Drawable mIcon;
-    
+
     private ImageView mIconView;
-    
     private TextView mTitleView;
-
     private TextView mMessageView;
-
     private View mCustomTitleView;
-    
+
     private boolean mForceInverseBackground;
-    
+
     private ListAdapter mAdapter;
-    
+
     private int mCheckedItem = -1;
 
     private int mAlertDialogLayout;
@@ -130,7 +113,7 @@
     private int mListItemLayout;
 
     private int mButtonPanelLayoutHint = AlertDialog.LAYOUT_HINT_NONE;
-    
+
     private Handler mHandler;
 
     private final View.OnClickListener mButtonHandler = new View.OnClickListener() {
@@ -160,7 +143,7 @@
     private static final class ButtonHandler extends Handler {
         // Button clicks have Message.what as the BUTTON{1,2,3} constant
         private static final int MSG_DISMISS_DIALOG = 1;
-        
+
         private WeakReference<DialogInterface> mDialog;
 
         public ButtonHandler(DialogInterface dialog) {
@@ -170,13 +153,13 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                
+
                 case DialogInterface.BUTTON_POSITIVE:
                 case DialogInterface.BUTTON_NEGATIVE:
                 case DialogInterface.BUTTON_NEUTRAL:
                     ((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what);
                     break;
-                    
+
                 case MSG_DISMISS_DIALOG:
                     ((DialogInterface) msg.obj).dismiss();
             }
@@ -220,16 +203,16 @@
 
         a.recycle();
     }
-    
+
     static boolean canTextInput(View v) {
         if (v.onCheckIsTextEditor()) {
             return true;
         }
-        
+
         if (!(v instanceof ViewGroup)) {
             return false;
         }
-        
+
         ViewGroup vg = (ViewGroup)v;
         int i = vg.getChildCount();
         while (i > 0) {
@@ -239,10 +222,10 @@
                 return true;
             }
         }
-        
+
         return false;
     }
-    
+
     public void installContent() {
         /* We use a custom title so never request a window title */
         mWindow.requestFeature(Window.FEATURE_NO_TITLE);
@@ -262,7 +245,7 @@
         // TODO: use layout hint side for long messages/lists
         return mAlertDialogLayout;
     }
-    
+
     public void setTitle(CharSequence title) {
         mTitle = title;
         if (mTitleView != null) {
@@ -276,7 +259,7 @@
     public void setCustomTitle(View customTitleView) {
         mCustomTitleView = customTitleView;
     }
-    
+
     public void setMessage(CharSequence message) {
         mMessage = message;
         if (mMessageView != null) {
@@ -301,7 +284,7 @@
         mViewLayoutResId = 0;
         mViewSpacingSpecified = false;
     }
-    
+
     /**
      * Set the view to display in the dialog along with the spacing around that view
      */
@@ -326,7 +309,7 @@
     /**
      * Sets a click listener or a message to be sent when the button is clicked.
      * You only need to pass one of {@code listener} or {@code msg}.
-     * 
+     *
      * @param whichButton Which button, can be one of
      *            {@link DialogInterface#BUTTON_POSITIVE},
      *            {@link DialogInterface#BUTTON_NEGATIVE}, or
@@ -341,24 +324,24 @@
         if (msg == null && listener != null) {
             msg = mHandler.obtainMessage(whichButton, listener);
         }
-        
+
         switch (whichButton) {
 
             case DialogInterface.BUTTON_POSITIVE:
                 mButtonPositiveText = text;
                 mButtonPositiveMessage = msg;
                 break;
-                
+
             case DialogInterface.BUTTON_NEGATIVE:
                 mButtonNegativeText = text;
                 mButtonNegativeMessage = msg;
                 break;
-                
+
             case DialogInterface.BUTTON_NEUTRAL:
                 mButtonNeutralText = text;
                 mButtonNeutralMessage = msg;
                 break;
-                
+
             default:
                 throw new IllegalArgumentException("Button does not exist");
         }
@@ -416,11 +399,11 @@
     public void setInverseBackgroundForced(boolean forceInverseBackground) {
         mForceInverseBackground = forceInverseBackground;
     }
-    
+
     public ListView getListView() {
         return mListView;
     }
-    
+
     public Button getButton(int whichButton) {
         switch (whichButton) {
             case DialogInterface.BUTTON_POSITIVE:
@@ -433,7 +416,7 @@
                 return null;
         }
     }
-    
+
     @SuppressWarnings({"UnusedDeclaration"})
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         return mScrollView != null && mScrollView.executeKeyEvent(event);
@@ -469,12 +452,12 @@
         final LinearLayout contentPanel = (LinearLayout) mWindow.findViewById(R.id.contentPanel);
         setupContent(contentPanel);
         final boolean hasButtons = setupButtons();
-        
+
         final LinearLayout topPanel = (LinearLayout) mWindow.findViewById(R.id.topPanel);
         final TypedArray a = mContext.obtainStyledAttributes(
                 null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
         final boolean hasTitle = setupTitle(topPanel);
-            
+
         final View buttonPanel = mWindow.findViewById(R.id.buttonPanel);
         if (!hasButtons) {
             buttonPanel.setVisibility(View.GONE);
@@ -536,14 +519,14 @@
 
     private boolean setupTitle(LinearLayout topPanel) {
         boolean hasTitle = true;
-        
+
         if (mCustomTitleView != null) {
             // Add the custom title view directly to the topPanel layout
             LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                     LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
-            
+
             topPanel.addView(mCustomTitleView, 0, lp);
-            
+
             // Hide the title template
             View titleTemplate = mWindow.findViewById(R.id.title_template);
             titleTemplate.setVisibility(View.GONE);
@@ -587,19 +570,19 @@
     private void setupContent(LinearLayout contentPanel) {
         mScrollView = (ScrollView) mWindow.findViewById(R.id.scrollView);
         mScrollView.setFocusable(false);
-        
+
         // Special case for users that only want to display a String
         mMessageView = (TextView) mWindow.findViewById(R.id.message);
         if (mMessageView == null) {
             return;
         }
-        
+
         if (mMessage != null) {
             mMessageView.setText(mMessage);
         } else {
             mMessageView.setVisibility(View.GONE);
             mScrollView.removeView(mMessageView);
-            
+
             if (mListView != null) {
                 contentPanel.removeView(mWindow.findViewById(R.id.scrollView));
                 contentPanel.addView(mListView,
@@ -664,7 +647,7 @@
                 centerButton(mButtonNeutral);
             }
         }
-        
+
         return whichButtons != 0;
     }
 
@@ -694,7 +677,12 @@
         int centerBright = 0;
         int bottomBright = 0;
         int bottomMedium = 0;
-        if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.KITKAT) {
+
+        // If the needsDefaultBackgrounds attribute is set, we know we're
+        // inheriting from a framework style.
+        final boolean needsDefaultBackgrounds = a.getBoolean(
+                R.styleable.AlertDialog_needsDefaultBackgrounds, true);
+        if (needsDefaultBackgrounds) {
             fullDark = R.drawable.popup_full_dark;
             topDark = R.drawable.popup_top_dark;
             centerDark = R.drawable.popup_center_dark;
@@ -705,12 +693,12 @@
             bottomBright = R.drawable.popup_bottom_bright;
             bottomMedium = R.drawable.popup_bottom_medium;
         }
+
         topBright = a.getResourceId(R.styleable.AlertDialog_topBright, topBright);
         topDark = a.getResourceId(R.styleable.AlertDialog_topDark, topDark);
         centerBright = a.getResourceId(R.styleable.AlertDialog_centerBright, centerBright);
         centerDark = a.getResourceId(R.styleable.AlertDialog_centerDark, centerDark);
 
-
         /* We now set the background of all of the sections of the alert.
          * First collect together each section that is being displayed along
          * with whether it is on a light or dark background, then run through
@@ -789,31 +777,6 @@
             }
         }
 
-        /* TODO: uncomment section below. The logic for this should be if 
-         * it's a Contextual menu being displayed AND only a Cancel button 
-         * is shown then do this.
-         */
-//        if (hasButtons && (mListView != null)) {
-            
-            /* Yet another *special* case. If there is a ListView with buttons
-             * don't put the buttons on the bottom but instead put them in the
-             * footer of the ListView this will allow more items to be
-             * displayed.
-             */
-            
-            /*
-            contentPanel.setBackgroundResource(bottomBright);
-            buttonPanel.setBackgroundResource(centerMedium);
-            ViewGroup parent = (ViewGroup) mWindow.findViewById(R.id.parentPanel);
-            parent.removeView(buttonPanel);
-            AbsListView.LayoutParams params = new AbsListView.LayoutParams(
-                    AbsListView.LayoutParams.MATCH_PARENT, 
-                    AbsListView.LayoutParams.MATCH_PARENT);
-            buttonPanel.setLayoutParams(params);
-            mListView.addFooterView(buttonPanel);
-            */
-//        }
-
         final ListView listView = mListView;
         if (listView != null && mAdapter != null) {
             listView.setAdapter(mAdapter);
@@ -854,7 +817,7 @@
     public static class AlertParams {
         public final Context mContext;
         public final LayoutInflater mInflater;
-        
+
         public int mIconId = 0;
         public Drawable mIcon;
         public int mIconAttrId = 0;
@@ -899,20 +862,20 @@
          * will be bound to an adapter.
          */
         public interface OnPrepareListViewListener {
-            
+
             /**
              * Called before the ListView is bound to an adapter.
              * @param listView The ListView that will be shown in the dialog.
              */
             void onPrepareListView(ListView listView);
         }
-        
+
         public AlertParams(Context context) {
             mContext = context;
             mCancelable = true;
             mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         }
-    
+
         public void apply(AlertController dialog) {
             if (mCustomTitleView != null) {
                 dialog.setCustomTitle(mCustomTitleView);
@@ -972,12 +935,12 @@
             }
             */
         }
-        
+
         private void createListView(final AlertController dialog) {
             final RecycleListView listView = (RecycleListView)
                     mInflater.inflate(dialog.mListLayout, null);
             ListAdapter adapter;
-            
+
             if (mIsMultiChoice) {
                 if (mCursor == null) {
                     adapter = new ArrayAdapter<CharSequence>(
@@ -1012,37 +975,37 @@
                             listView.setItemChecked(cursor.getPosition(),
                                     cursor.getInt(mIsCheckedIndex) == 1);
                         }
-    
+
                         @Override
                         public View newView(Context context, Cursor cursor, ViewGroup parent) {
                             return mInflater.inflate(dialog.mMultiChoiceItemLayout,
                                     parent, false);
                         }
-                        
+
                     };
                 }
             } else {
-                int layout = mIsSingleChoice 
+                int layout = mIsSingleChoice
                         ? dialog.mSingleChoiceItemLayout : dialog.mListItemLayout;
                 if (mCursor == null) {
                     adapter = (mAdapter != null) ? mAdapter
                             : new CheckedItemAdapter(mContext, layout, R.id.text1, mItems);
                 } else {
-                    adapter = new SimpleCursorAdapter(mContext, layout, 
+                    adapter = new SimpleCursorAdapter(mContext, layout,
                             mCursor, new String[]{mLabelColumn}, new int[]{R.id.text1});
                 }
             }
-            
+
             if (mOnPrepareListViewListener != null) {
                 mOnPrepareListViewListener.onPrepareListView(listView);
             }
-            
+
             /* Don't directly set the adapter on the ListView as we might
              * want to add a footer to the ListView later.
              */
             dialog.mAdapter = adapter;
             dialog.mCheckedItem = mCheckedItem;
-            
+
             if (mOnClickListener != null) {
                 listView.setOnItemClickListener(new OnItemClickListener() {
                     @Override
@@ -1065,12 +1028,12 @@
                     }
                 });
             }
-            
+
             // Attach a given OnItemSelectedListener to the ListView
             if (mOnItemSelectedListener != null) {
                 listView.setOnItemSelectedListener(mOnItemSelectedListener);
             }
-            
+
             if (mIsSingleChoice) {
                 listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
             } else if (mIsMultiChoice) {
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index abe8a9f..99c87ea 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
 import android.view.ActionMode;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -32,7 +33,9 @@
 import android.view.WindowCallbackWrapper;
 import android.widget.SpinnerAdapter;
 import android.widget.Toolbar;
+import com.android.internal.R;
 import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuPresenter;
 import com.android.internal.widget.DecorToolbar;
 import com.android.internal.widget.ToolbarWidgetWrapper;
 
@@ -43,6 +46,9 @@
     private DecorToolbar mDecorToolbar;
     private boolean mToolbarMenuPrepared;
     private Window.Callback mWindowCallback;
+    private boolean mMenuCallbackSet;
+
+    private CharSequence mHomeDescription;
 
     private boolean mLastMenuVisibility;
     private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
@@ -70,6 +76,8 @@
         mDecorToolbar.setWindowCallback(mWindowCallback);
         toolbar.setOnMenuItemClickListener(mMenuClicker);
         mDecorToolbar.setWindowTitle(title);
+        mHomeDescription = mToolbar.getNavigationContentDescription();
+        updateNavDescription();
     }
 
     public Window.Callback getWrappedWindowCallback() {
@@ -161,6 +169,7 @@
     @Override
     public void setHomeActionContentDescription(CharSequence description) {
         mToolbar.setNavigationContentDescription(description);
+        mHomeDescription = description;
     }
 
     @Override
@@ -171,6 +180,7 @@
     @Override
     public void setHomeActionContentDescription(int resId) {
         mToolbar.setNavigationContentDescription(resId);
+        mHomeDescription = mToolbar.getNavigationContentDescription();
     }
 
     @Override
@@ -247,8 +257,22 @@
 
     @Override
     public void setDisplayOptions(@DisplayOptions int options, @DisplayOptions int mask) {
-        mDecorToolbar.setDisplayOptions((options & mask) |
-                mDecorToolbar.getDisplayOptions() & ~mask);
+        final int currentOptions = mDecorToolbar.getDisplayOptions();
+        final int changed = (options ^ currentOptions) & mask;
+        mDecorToolbar.setDisplayOptions(options & mask | currentOptions & ~mask);
+        if ((changed & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
+            updateNavDescription();
+        }
+    }
+
+    private void updateNavDescription() {
+        if ((mDecorToolbar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
+            if (TextUtils.isEmpty(mHomeDescription)) {
+                mToolbar.setNavigationContentDescription(R.string.action_bar_up_description);
+            } else {
+                mToolbar.setNavigationContentDescription(mHomeDescription);
+            }
+        }
     }
 
     @Override
@@ -431,6 +455,10 @@
     }
 
     void populateOptionsMenu() {
+        if (!mMenuCallbackSet) {
+            mToolbar.setMenuCallbacks(new ActionMenuPresenterCallback(), new MenuBuilderCallback());
+            mMenuCallbackSet = true;
+        }
         final Menu menu = mToolbar.getMenu();
         final MenuBuilder mb = menu instanceof MenuBuilder ? (MenuBuilder) menu : null;
         if (mb != null) {
@@ -492,4 +520,51 @@
             return result;
         }
     }
+
+    private final class ActionMenuPresenterCallback implements MenuPresenter.Callback {
+        private boolean mClosingActionMenu;
+
+        @Override
+        public boolean onOpenSubMenu(MenuBuilder subMenu) {
+            if (mWindowCallback != null) {
+                mWindowCallback.onMenuOpened(Window.FEATURE_ACTION_BAR, subMenu);
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+            if (mClosingActionMenu) {
+                return;
+            }
+
+            mClosingActionMenu = true;
+            mToolbar.dismissPopupMenus();
+            if (mWindowCallback != null) {
+                mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu);
+            }
+            mClosingActionMenu = false;
+        }
+    }
+
+    private final class MenuBuilderCallback implements MenuBuilder.Callback {
+
+        @Override
+        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
+            return false;
+        }
+
+        @Override
+        public void onMenuModeChange(MenuBuilder menu) {
+            if (mWindowCallback != null) {
+                if (mToolbar.isOverflowMenuShowing()) {
+                    mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu);
+                } else if (mWindowCallback.onPreparePanel(Window.FEATURE_OPTIONS_PANEL,
+                        null, menu)) {
+                    mWindowCallback.onMenuOpened(Window.FEATURE_ACTION_BAR, menu);
+                }
+            }
+        }
+    }
 }
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 54c532a..c5211bb 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -20,9 +20,12 @@
 import dalvik.system.ZygoteHooks;
 import android.system.ErrnoException;
 import android.system.Os;
+import android.os.SystemClock;
+import android.util.Slog;
 
 /** @hide */
 public final class Zygote {
+    private static final String TAG = "Zygote";
     /*
     * Bit values for "debugFlags" argument.  The definitions are duplicated
     * in the native code.
@@ -81,10 +84,14 @@
      */
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+        long startTime = SystemClock.elapsedRealtime();
         VM_HOOKS.preFork();
+        checkTime(startTime, "Zygote.preFork");
         int pid = nativeForkAndSpecialize(
                   uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+        checkTime(startTime, "Zygote.nativeForkAndSpecialize");
         VM_HOOKS.postForkCommon();
+        checkTime(startTime, "Zygote.postForkCommon");
         return pid;
     }
 
@@ -92,6 +99,18 @@
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
 
     /**
+     * Temporary hack: check time since start time and log if over a fixed threshold.
+     *
+     */
+    private static void checkTime(long startTime, String where) {
+        long now = SystemClock.elapsedRealtime();
+        if ((now-startTime) > 1000) {
+            // If we are taking more than a second, log about it.
+            Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where);
+        }
+    }
+
+    /**
      * Special method to start the system server process. In addition to the
      * common actions performed in forkAndSpecialize, the pid of the child
      * process is recorded such that the death of the child process will cause
@@ -127,7 +146,9 @@
             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
 
     private static void callPostForkChildHooks(int debugFlags) {
+        long startTime = SystemClock.elapsedRealtime();
         VM_HOOKS.postForkChild(debugFlags);
+        checkTime(startTime, "Zygote.callPostForkChildHooks");
     }
 
 
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 43ebb3d..b4c4da6 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -37,6 +37,8 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import libcore.io.IoUtils;
+import android.os.SystemClock;
+import android.util.Slog;
 
 /**
  * A connection that can make spawn requests.
@@ -103,11 +105,23 @@
     }
 
     /**
+     * Temporary hack: check time since start time and log if over a fixed threshold.
+     *
+     */
+    private void checkTime(long startTime, String where) {
+        long now = SystemClock.elapsedRealtime();
+        if ((now-startTime) > 1000) {
+            // If we are taking more than a second, log about it.
+            Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where);
+        }
+    }
+
+    /**
      * Returns the file descriptor of the associated socket.
      *
      * @return null-ok; file descriptor
      */
-    FileDescriptor getFileDesciptor() {
+    FileDescriptor getFileDescriptor() {
         return mSocket.getFileDescriptor();
     }
 
@@ -131,6 +145,8 @@
         Arguments parsedArgs = null;
         FileDescriptor[] descriptors;
 
+        long startTime = SystemClock.elapsedRealtime();
+
         try {
             args = readArgumentList();
             descriptors = mSocket.getAncillaryFileDescriptors();
@@ -140,6 +156,7 @@
             return true;
         }
 
+        checkTime(startTime, "zygoteConnection.runOnce: readArgumentList");
         if (args == null) {
             // EOF reached.
             closeSocket();
@@ -171,14 +188,19 @@
                         ", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
             }
 
+
             applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
             applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
             applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
             applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);
 
+            checkTime(startTime, "zygoteConnection.runOnce: apply security policies");
+
             applyDebuggerSystemProperty(parsedArgs);
             applyInvokeWithSystemProperty(parsedArgs);
 
+            checkTime(startTime, "zygoteConnection.runOnce: apply security policies");
+
             int[][] rlimits = null;
 
             if (parsedArgs.rlimits != null) {
@@ -220,9 +242,11 @@
 
             fd = null;
 
+            checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
             pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                     parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                     parsedArgs.niceName, fdsToClose);
+            checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
         } catch (IOException ex) {
             logAndPrintError(newStderr, "Exception creating pipe", ex);
         } catch (ErrnoException ex) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 051de6e..0aee0e3 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -770,7 +770,7 @@
             } else if (index == 0) {
                 ZygoteConnection newPeer = acceptCommandPeer(abiList);
                 peers.add(newPeer);
-                fds.add(newPeer.getFileDesciptor());
+                fds.add(newPeer.getFileDescriptor());
             } else {
                 boolean done;
                 done = peers.get(index).runOnce();
diff --git a/core/java/com/android/internal/util/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java
index a5ce6e0..c153904 100644
--- a/core/java/com/android/internal/util/ImageUtils.java
+++ b/core/java/com/android/internal/util/ImageUtils.java
@@ -17,6 +17,10 @@
 package com.android.internal.util;
 
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
 
 /**
  * Utility class for image analysis and processing.
@@ -31,17 +35,49 @@
     // Alpha amount for which values below are considered transparent.
     private static final int ALPHA_TOLERANCE = 50;
 
+    // Size of the smaller bitmap we're actually going to scan.
+    private static final int COMPACT_BITMAP_SIZE = 64; // pixels
+
     private int[] mTempBuffer;
+    private Bitmap mTempCompactBitmap;
+    private Canvas mTempCompactBitmapCanvas;
+    private Paint mTempCompactBitmapPaint;
+    private final Matrix mTempMatrix = new Matrix();
 
     /**
      * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect
      * gray".
+     *
+     * Instead of scanning every pixel in the bitmap, we first resize the bitmap to no more than
+     * COMPACT_BITMAP_SIZE^2 pixels using filtering. The hope is that any non-gray color elements
+     * will survive the squeezing process, contaminating the result with color.
      */
     public boolean isGrayscale(Bitmap bitmap) {
-        final int height = bitmap.getHeight();
-        final int width = bitmap.getWidth();
-        int size = height*width;
+        int height = bitmap.getHeight();
+        int width = bitmap.getWidth();
 
+        // shrink to a more manageable (yet hopefully no more or less colorful) size
+        if (height > COMPACT_BITMAP_SIZE || width > COMPACT_BITMAP_SIZE) {
+            if (mTempCompactBitmap == null) {
+                mTempCompactBitmap = Bitmap.createBitmap(
+                        COMPACT_BITMAP_SIZE, COMPACT_BITMAP_SIZE, Bitmap.Config.ARGB_8888
+                );
+                mTempCompactBitmapCanvas = new Canvas(mTempCompactBitmap);
+                mTempCompactBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+                mTempCompactBitmapPaint.setFilterBitmap(true);
+            }
+            mTempMatrix.reset();
+            mTempMatrix.setScale(
+                    (float) COMPACT_BITMAP_SIZE / width,
+                    (float) COMPACT_BITMAP_SIZE / height,
+                    0, 0);
+            mTempCompactBitmapCanvas.drawColor(0, PorterDuff.Mode.SRC); // select all, erase
+            mTempCompactBitmapCanvas.drawBitmap(bitmap, mTempMatrix, mTempCompactBitmapPaint);
+            bitmap = mTempCompactBitmap;
+            width = height = COMPACT_BITMAP_SIZE;
+        }
+
+        final int size = height*width;
         ensureBufferSize(size);
         bitmap.getPixels(mTempBuffer, 0, width, 0, 0, width, height);
         for (int i = 0; i < size; i++) {
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 665055c..3249ea3 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -50,23 +50,36 @@
     private final WeakHashMap<Bitmap, Pair<Boolean, Integer>> mGrayscaleBitmapCache =
             new WeakHashMap<Bitmap, Pair<Boolean, Integer>>();
 
-    public static NotificationColorUtil getInstance() {
+    private final int mGrayscaleIconMaxSize; // @dimen/notification_large_icon_width (64dp)
+
+    public static NotificationColorUtil getInstance(Context context) {
         synchronized (sLock) {
             if (sInstance == null) {
-                sInstance = new NotificationColorUtil();
+                sInstance = new NotificationColorUtil(context);
             }
             return sInstance;
         }
     }
 
+    private NotificationColorUtil(Context context) {
+        mGrayscaleIconMaxSize = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_large_icon_width);
+    }
+
     /**
-     * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect
-     * gray".
+     * Checks whether a Bitmap is a small grayscale icon.
+     * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp".
      *
      * @param bitmap The bitmap to test.
-     * @return Whether the bitmap is grayscale.
+     * @return True if the bitmap is grayscale; false if it is color or too large to examine.
      */
-    public boolean isGrayscale(Bitmap bitmap) {
+    public boolean isGrayscaleIcon(Bitmap bitmap) {
+        // quick test: reject large bitmaps
+        if (bitmap.getWidth() > mGrayscaleIconMaxSize
+                || bitmap.getHeight() > mGrayscaleIconMaxSize) {
+            return false;
+        }
+
         synchronized (sLock) {
             Pair<Boolean, Integer> cached = mGrayscaleBitmapCache.get(bitmap);
             if (cached != null) {
@@ -92,22 +105,22 @@
     }
 
     /**
-     * Checks whether a drawable is grayscale. Grayscale here means "very close to a perfect
-     * gray".
+     * Checks whether a Drawable is a small grayscale icon.
+     * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp".
      *
      * @param d The drawable to test.
-     * @return Whether the drawable is grayscale.
+     * @return True if the bitmap is grayscale; false if it is color or too large to examine.
      */
-    public boolean isGrayscale(Drawable d) {
+    public boolean isGrayscaleIcon(Drawable d) {
         if (d == null) {
             return false;
         } else if (d instanceof BitmapDrawable) {
             BitmapDrawable bd = (BitmapDrawable) d;
-            return bd.getBitmap() != null && isGrayscale(bd.getBitmap());
+            return bd.getBitmap() != null && isGrayscaleIcon(bd.getBitmap());
         } else if (d instanceof AnimationDrawable) {
             AnimationDrawable ad = (AnimationDrawable) d;
             int count = ad.getNumberOfFrames();
-            return count > 0 && isGrayscale(ad.getFrame(0));
+            return count > 0 && isGrayscaleIcon(ad.getFrame(0));
         } else if (d instanceof VectorDrawable) {
             // We just assume you're doing the right thing if using vectors
             return true;
@@ -117,16 +130,16 @@
     }
 
     /**
-     * Checks whether a drawable with a resoure id is grayscale. Grayscale here means "very close
-     * to a perfect gray".
+     * Checks whether a drawable with a resoure id is a small grayscale icon.
+     * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp".
      *
      * @param context The context to load the drawable from.
-     * @return Whether the drawable is grayscale.
+     * @return True if the bitmap is grayscale; false if it is color or too large to examine.
      */
-    public boolean isGrayscale(Context context, int drawableResId) {
+    public boolean isGrayscaleIcon(Context context, int drawableResId) {
         if (drawableResId != 0) {
             try {
-                return isGrayscale(context.getDrawable(drawableResId));
+                return isGrayscaleIcon(context.getDrawable(drawableResId));
             } catch (Resources.NotFoundException ex) {
                 Log.e(TAG, "Drawable not found: " + drawableResId);
                 return false;
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index b1f5d90..e19b2b6 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -437,7 +437,7 @@
                         return;
                     }
                     args.callback.setRequestUpdateCursorAnchorInfoResult(
-                            ic.requestUpdateCursorAnchorInfo(msg.arg1), args.seq);
+                            ic.requestCursorUpdates(msg.arg1), args.seq);
                 } catch (RemoteException e) {
                     Log.w(TAG, "Got RemoteException calling requestCursorAnchorInfo", e);
                 }
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index a8526c8..0c65ad1 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -428,7 +428,7 @@
         }
     }
 
-    public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+    public boolean requestCursorUpdates(int cursorUpdateMode) {
         boolean result = false;
         try {
             InputContextCallback callback = InputContextCallback.getInstance();
@@ -445,4 +445,11 @@
         }
         return result;
     }
+
+    /**
+     * @removed
+     */
+    public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+        return requestCursorUpdates(cursorUpdateMode);
+    }
 }
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index c7ac815..062a9b1 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -59,6 +59,7 @@
     private int mSubtitleStyleRes;
     private Drawable mSplitBackground;
     private boolean mTitleOptional;
+    private int mCloseItemLayout;
 
     private Animator mCurrentAnimation;
     private boolean mAnimateInOnLayout;
@@ -99,6 +100,10 @@
         mSplitBackground = a.getDrawable(
                 com.android.internal.R.styleable.ActionMode_backgroundSplit);
 
+        mCloseItemLayout = a.getResourceId(
+                com.android.internal.R.styleable.ActionMode_closeItemLayout,
+                R.layout.action_mode_close_item);
+
         a.recycle();
     }
 
@@ -120,7 +125,7 @@
                         LayoutParams.MATCH_PARENT);
                 if (!split) {
                     mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
-                    mMenuView.setBackgroundDrawable(null);
+                    mMenuView.setBackground(null);
                     final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
                     if (oldParent != null) oldParent.removeView(mMenuView);
                     addView(mMenuView, layoutParams);
@@ -134,7 +139,7 @@
                     layoutParams.width = LayoutParams.MATCH_PARENT;
                     layoutParams.height = mContentHeight;
                     mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
-                    mMenuView.setBackgroundDrawable(mSplitBackground);
+                    mMenuView.setBackground(mSplitBackground);
                     final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
                     if (oldParent != null) oldParent.removeView(mMenuView);
                     mSplitView.addView(mMenuView, layoutParams);
@@ -211,7 +216,7 @@
     public void initForMode(final ActionMode mode) {
         if (mClose == null) {
             LayoutInflater inflater = LayoutInflater.from(mContext);
-            mClose = inflater.inflate(R.layout.action_mode_close_item, this, false);
+            mClose = inflater.inflate(mCloseItemLayout, this, false);
             addView(mClose);
         } else if (mClose.getParent() == null) {
             addView(mClose);
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index ba236f3..f211ff2 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -188,13 +188,13 @@
     }
 
     @Override
-    public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) {
+    public boolean requestCursorUpdates(int cursorUpdateMode) {
         if (DEBUG) Log.v(TAG, "requestUpdateCursorAnchorInfo " + cursorUpdateMode);
 
         // It is possible that any other bit is used as a valid flag in a future release.
         // We should reject the entire request in such a case.
-        final int KNOWN_FLAGS_MASK = InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE |
-                InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR;
+        final int KNOWN_FLAGS_MASK = InputConnection.CURSOR_UPDATE_IMMEDIATE |
+                InputConnection.CURSOR_UPDATE_MONITOR;
         final int unknownFlags = cursorUpdateMode & ~KNOWN_FLAGS_MASK;
         if (unknownFlags != 0) {
             if (DEBUG) {
@@ -212,7 +212,7 @@
             return false;
         }
         mIMM.setUpdateCursorAnchorInfoMode(cursorUpdateMode);
-        if ((cursorUpdateMode & InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0) {
+        if ((cursorUpdateMode & InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0) {
             if (mTextView == null) {
                 // In this case, FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE is silently ignored.
                 // TODO: Return some notification code for the input method that indicates
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2114ff6..c84708e 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1449,7 +1449,7 @@
         }
 
         int textId;
-        if (getTelecommManager().isInCall()) {
+        if (isInCall()) {
             // show "return to call" text and show phone icon
             textId = R.string.lockscreen_return_to_call;
             int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
@@ -1470,6 +1470,13 @@
         getTelecommManager().showInCallScreen(false);
     }
 
+    /**
+     * @return {@code true} if there is a call currently in progress, {@code false} otherwise.
+     */
+    public boolean isInCall() {
+        return getTelecommManager().isInCall();
+    }
+
     private TelecommManager getTelecommManager() {
         return (TelecommManager) mContext.getSystemService(Context.TELECOMM_SERVICE);
     }
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 62ea351..8ea28ec 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -367,6 +367,9 @@
                 peeker.mOpticalInsets[0], peeker.mOpticalInsets[1], peeker.mOpticalInsets[2], peeker.mOpticalInsets[3],
                 peeker.mOutlineInsets[0], peeker.mOutlineInsets[1], peeker.mOutlineInsets[2], peeker.mOutlineInsets[3],
                 peeker.mOutlineRadius, peeker.mOutlineAlpha, scale);
+        if (ninePatchInsets == NULL) {
+            return nullObjectReturn("nine patch insets == null");
+        }
         if (javaBitmap != NULL) {
             env->SetObjectField(javaBitmap, gBitmap_ninePatchInsetsFieldID, ninePatchInsets);
         }
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 7c41c2e..d7b75db 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -419,6 +419,7 @@
 {
     SkASSERT(bitmap);
     SkASSERT(bitmap->pixelRef());
+    SkASSERT(!env->ExceptionCheck());
     bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
     bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
 
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index f5eaf94..9b96320 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -35,7 +35,15 @@
 
 extern "C" void free_malloc_leak_info(uint8_t* info);
 
+#define DDMS_HEADER_SIGNATURE 0x812345dd
+#define DDMS_VERSION 2
+
 struct Header {
+#if defined(__LP64__)
+    uint32_t signature;
+    uint16_t version;
+    uint16_t pointerSize;
+#endif
     size_t mapSize;
     size_t allocSize;
     size_t allocInfoSize;
@@ -77,6 +85,12 @@
     ALOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d",
           header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
 
+#if defined(__LP64__)
+    header.signature = DDMS_HEADER_SIGNATURE;
+    header.version = DDMS_VERSION;
+    header.pointerSize = sizeof(void*);
+#endif
+
     jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize);
     if (array != NULL) {
         env->SetByteArrayRegion(array, 0,
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 1296831..949f4ff 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -458,7 +458,7 @@
 static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
         jlong renderNodePtr) {
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
-    renderNode->animators().endAllAnimators();
+    renderNode->animators().endAllStagingAnimators();
 }
 
 #endif // USE_OPENGL_RENDERER
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 99babac..7e6d335 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -166,12 +166,7 @@
     // Runs any animations still left in mCurrentFrameAnimations
     virtual void runRemainingAnimations(TreeInfo& info) {
         AnimationContext::runRemainingAnimations(info);
-        // post all the finished stuff
-        if (mOnFinishedEvents.size()) {
-            sp<InvokeAnimationListeners> message
-                    = new InvokeAnimationListeners(mOnFinishedEvents);
-            mRootNode->sendMessage(message);
-        }
+        postOnFinishedEvents();
     }
 
     virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
@@ -179,9 +174,22 @@
         mOnFinishedEvents.push_back(event);
     }
 
+    virtual void destroy() {
+        AnimationContext::destroy();
+        postOnFinishedEvents();
+    }
+
 private:
     sp<RootRenderNode> mRootNode;
     std::vector<OnFinishedEvent> mOnFinishedEvents;
+
+    void postOnFinishedEvents() {
+        if (mOnFinishedEvents.size()) {
+            sp<InvokeAnimationListeners> message
+                    = new InvokeAnimationListeners(mOnFinishedEvents);
+            mRootNode->sendMessage(message);
+        }
+    }
 };
 
 class ContextFactoryImpl : public IContextFactory {
@@ -291,10 +299,10 @@
     return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density);
 }
 
-static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
         jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->destroyCanvasAndSurface();
+    proxy->destroy();
 }
 
 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
@@ -430,7 +438,7 @@
     { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
     { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
-    { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
+    { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
     { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
     { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
     { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 1f7acec..3d2d471 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -43,6 +43,7 @@
 #include <utils/String8.h>
 #include <selinux/android.h>
 #include <processgroup/processgroup.h>
+#include <inttypes.h>
 
 #include "android_runtime/AndroidRuntime.h"
 #include "JNIHelp.h"
@@ -398,6 +399,22 @@
   }
 }
 
+  // Temporary timing check.
+uint64_t MsTime() {
+  timespec now;
+  clock_gettime(CLOCK_MONOTONIC, &now);
+  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_nsec / UINT64_C(1000000);
+}
+
+
+void ckTime(uint64_t start, const char* where) {
+  uint64_t now = MsTime();
+  if ((now-start) > 1000) {
+    // If we are taking more than a second, log about it.
+    ALOGW("Slow operation: %"PRIu64" ms in %s", (uint64_t)(now-start), where);
+  }
+}
+
 // Utility routine to fork zygote and specialize the child process.
 static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                      jint debug_flags, jobjectArray javaRlimits,
@@ -405,7 +422,9 @@
                                      jint mount_external,
                                      jstring java_se_info, jstring java_se_name,
                                      bool is_system_server, jintArray fdsToClose) {
+  uint64_t start = MsTime();
   SetSigChldHandler();
+  ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler");
 
   pid_t pid = fork();
 
@@ -413,9 +432,12 @@
     // The child process.
     gMallocLeakZygoteChild = 1;
 
+
     // Clean up any descriptors which must be closed immediately
     DetachDescriptors(env, fdsToClose);
 
+    ckTime(start, "ForkAndSpecializeCommon:Fork and detach");
+
     // Keep capabilities across UID change, unless we're staying root.
     if (uid != 0) {
       EnableKeepCapabilities(env);
@@ -518,7 +540,10 @@
 
     UnsetSigChldHandler();
 
+    ckTime(start, "ForkAndSpecializeCommon:child process setup");
+
     env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+    ckTime(start, "ForkAndSpecializeCommon:PostForkChildHooks returns");
     if (env->ExceptionCheck()) {
       ALOGE("Error calling post fork hooks.");
       RuntimeAbort(env);
diff --git a/core/res/res/drawable-hdpi/pointer_spot_anchor.png b/core/res/res/drawable-hdpi/pointer_spot_anchor.png
index d7aca36..bdb5311 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_anchor.png
+++ b/core/res/res/drawable-hdpi/pointer_spot_anchor.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/pointer_spot_hover.png b/core/res/res/drawable-hdpi/pointer_spot_hover.png
index 5041aa3..e7f2a0c 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_hover.png
+++ b/core/res/res/drawable-hdpi/pointer_spot_hover.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/pointer_spot_touch.png b/core/res/res/drawable-hdpi/pointer_spot_touch.png
index 64a42a1..0326f91 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_touch.png
+++ b/core/res/res/drawable-hdpi/pointer_spot_touch.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_arrow_icon.xml b/core/res/res/drawable-mdpi/pointer_arrow_icon.xml
deleted file mode 100644
index 2f5676f..0000000
--- a/core/res/res/drawable-mdpi/pointer_arrow_icon.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
-    android:bitmap="@drawable/pointer_arrow"
-    android:hotSpotX="6"
-    android:hotSpotY="6" />
diff --git a/core/res/res/drawable-mdpi/pointer_spot_anchor.png b/core/res/res/drawable-mdpi/pointer_spot_anchor.png
index d7aca36..4e282e7 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_anchor.png
+++ b/core/res/res/drawable-mdpi/pointer_spot_anchor.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml b/core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml
deleted file mode 100644
index 2222b8e..0000000
--- a/core/res/res/drawable-mdpi/pointer_spot_anchor_icon.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
-    android:bitmap="@drawable/pointer_spot_anchor"
-    android:hotSpotX="33"
-    android:hotSpotY="33" />
diff --git a/core/res/res/drawable-mdpi/pointer_spot_hover.png b/core/res/res/drawable-mdpi/pointer_spot_hover.png
index 5041aa3..67d0b06 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_hover.png
+++ b/core/res/res/drawable-mdpi/pointer_spot_hover.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml b/core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml
deleted file mode 100644
index dc62a69..0000000
--- a/core/res/res/drawable-mdpi/pointer_spot_hover_icon.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
-    android:bitmap="@drawable/pointer_spot_hover"
-    android:hotSpotX="33"
-    android:hotSpotY="33" />
diff --git a/core/res/res/drawable-mdpi/pointer_spot_touch.png b/core/res/res/drawable-mdpi/pointer_spot_touch.png
index 64a42a1..45dc5c0 100644
--- a/core/res/res/drawable-mdpi/pointer_spot_touch.png
+++ b/core/res/res/drawable-mdpi/pointer_spot_touch.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml b/core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml
deleted file mode 100644
index 4bffee6..0000000
--- a/core/res/res/drawable-mdpi/pointer_spot_touch_icon.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
-    android:bitmap="@drawable/pointer_spot_touch"
-    android:hotSpotX="24"
-    android:hotSpotY="24" />
diff --git a/core/res/res/drawable-xhdpi/pointer_arrow_icon.xml b/core/res/res/drawable-xhdpi/pointer_arrow_icon.xml
deleted file mode 100644
index 2fbe45a..0000000
--- a/core/res/res/drawable-xhdpi/pointer_arrow_icon.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
-    android:bitmap="@drawable/pointer_arrow"
-    android:hotSpotX="12"
-    android:hotSpotY="12" />
diff --git a/core/res/res/drawable-xhdpi/pointer_spot_anchor.png b/core/res/res/drawable-xhdpi/pointer_spot_anchor.png
index ad41c97..fa9226e 100644
--- a/core/res/res/drawable-xhdpi/pointer_spot_anchor.png
+++ b/core/res/res/drawable-xhdpi/pointer_spot_anchor.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_spot_hover.png b/core/res/res/drawable-xhdpi/pointer_spot_hover.png
index e9b98f6..f09a778 100644
--- a/core/res/res/drawable-xhdpi/pointer_spot_hover.png
+++ b/core/res/res/drawable-xhdpi/pointer_spot_hover.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_spot_touch.png b/core/res/res/drawable-xhdpi/pointer_spot_touch.png
index e10d998..53d7a20 100644
--- a/core/res/res/drawable-xhdpi/pointer_spot_touch.png
+++ b/core/res/res/drawable-xhdpi/pointer_spot_touch.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/pointer_arrow_icon.xml b/core/res/res/drawable/pointer_arrow_icon.xml
similarity index 73%
rename from core/res/res/drawable-hdpi/pointer_arrow_icon.xml
rename to core/res/res/drawable/pointer_arrow_icon.xml
index a4cce5c..8f7d658 100644
--- a/core/res/res/drawable-hdpi/pointer_arrow_icon.xml
+++ b/core/res/res/drawable/pointer_arrow_icon.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
     android:bitmap="@drawable/pointer_arrow"
-    android:hotSpotX="9"
-    android:hotSpotY="9" />
+    android:hotSpotX="6dp"
+    android:hotSpotY="6dp" />
diff --git a/core/res/res/drawable-hdpi/pointer_spot_anchor_icon.xml b/core/res/res/drawable/pointer_spot_anchor_icon.xml
similarity index 73%
rename from core/res/res/drawable-hdpi/pointer_spot_anchor_icon.xml
rename to core/res/res/drawable/pointer_spot_anchor_icon.xml
index 2222b8e..73c0c11 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_anchor_icon.xml
+++ b/core/res/res/drawable/pointer_spot_anchor_icon.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
     android:bitmap="@drawable/pointer_spot_anchor"
-    android:hotSpotX="33"
-    android:hotSpotY="33" />
+    android:hotSpotX="22dp"
+    android:hotSpotY="22dp" />
diff --git a/core/res/res/drawable-hdpi/pointer_spot_hover_icon.xml b/core/res/res/drawable/pointer_spot_hover_icon.xml
similarity index 73%
rename from core/res/res/drawable-hdpi/pointer_spot_hover_icon.xml
rename to core/res/res/drawable/pointer_spot_hover_icon.xml
index dc62a69..1d7440b 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_hover_icon.xml
+++ b/core/res/res/drawable/pointer_spot_hover_icon.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
     android:bitmap="@drawable/pointer_spot_hover"
-    android:hotSpotX="33"
-    android:hotSpotY="33" />
+    android:hotSpotX="22dp"
+    android:hotSpotY="22dp" />
diff --git a/core/res/res/drawable-hdpi/pointer_spot_touch_icon.xml b/core/res/res/drawable/pointer_spot_touch_icon.xml
similarity index 73%
rename from core/res/res/drawable-hdpi/pointer_spot_touch_icon.xml
rename to core/res/res/drawable/pointer_spot_touch_icon.xml
index 4bffee6..f4f0639 100644
--- a/core/res/res/drawable-hdpi/pointer_spot_touch_icon.xml
+++ b/core/res/res/drawable/pointer_spot_touch_icon.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
     android:bitmap="@drawable/pointer_spot_touch"
-    android:hotSpotX="24"
-    android:hotSpotY="24" />
+    android:hotSpotX="16dp"
+    android:hotSpotY="16dp" />
diff --git a/core/res/res/drawable/stat_sys_tether_wifi.xml b/core/res/res/drawable/stat_sys_tether_wifi.xml
index a816db8..4396962 100644
--- a/core/res/res/drawable/stat_sys_tether_wifi.xml
+++ b/core/res/res/drawable/stat_sys_tether_wifi.xml
@@ -14,11 +14,12 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="26.0dp"
+        android:width="24.0dp"
         android:height="24.0dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+
     <path
         android:fillColor="#FFFFFFFF"
-        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"/>
+        android:pathData="M24.000000,22.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000C28.000000,23.799999 26.200001,22.000000 24.000000,22.000000zM36.000000,26.000000c0.000000,-6.600000 -5.400000,-12.000000 -12.000000,-12.000000c-6.600000,0.000000 -12.000000,5.400000 -12.000000,12.000000c0.000000,4.400000 2.400000,8.300000 6.000000,10.400000l2.000000,-3.500000c-2.400000,-1.400000 -4.000000,-3.900000 -4.000000,-6.900000c0.000000,-4.400000 3.600000,-8.000000 8.000000,-8.000000s8.000000,3.600000 8.000000,8.000000c0.000000,3.000000 -1.600000,5.500000 -4.000000,6.900000l2.000000,3.500000C33.599998,34.299999 36.000000,30.400000 36.000000,26.000000zM24.000000,6.000000C13.000000,6.000000 4.000000,15.000000 4.000000,26.000000c0.000000,7.400000 4.000000,13.800000 10.000000,17.299999l2.000000,-3.500000c-4.800000,-2.800000 -8.000000,-7.900000 -8.000000,-13.800000c0.000000,-8.800000 7.200000,-16.000000 16.000000,-16.000000s16.000000,7.200000 16.000000,16.000000c0.000000,5.900000 -3.200000,11.100000 -8.000000,13.800000l2.000000,3.500000c6.000000,-3.500000 10.000000,-9.900000 10.000000,-17.299999C44.000000,15.000000 35.000000,6.000000 24.000000,6.000000z"/>
 </vector>
diff --git a/core/res/res/drawable/ic_cab_done_material.xml b/core/res/res/drawable/time_picker_header_material.xml
similarity index 77%
rename from core/res/res/drawable/ic_cab_done_material.xml
rename to core/res/res/drawable/time_picker_header_material.xml
index a370288..cdb92b6 100644
--- a/core/res/res/drawable/ic_cab_done_material.xml
+++ b/core/res/res/drawable/time_picker_header_material.xml
@@ -14,6 +14,9 @@
      limitations under the License.
 -->
 
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-    android:src="@drawable/ic_cab_done_mtrl_alpha"
-    android:tint="?attr/colorControlNormal" />
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?attr/colorControlHighlight">
+    <item>
+        <color android:color="?attr/colorAccent" />
+    </item>
+</ripple>
diff --git a/core/res/res/layout-land/time_picker_holo.xml b/core/res/res/layout-land/time_picker_holo.xml
index f316f1b..ce90a5b 100644
--- a/core/res/res/layout-land/time_picker_holo.xml
+++ b/core/res/res/layout-land/time_picker_holo.xml
@@ -21,7 +21,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal"
-    android:focusable="true"
     android:layout_marginLeft="@dimen/timepicker_minimum_margin_sides"
     android:layout_marginRight="@dimen/timepicker_minimum_margin_sides"
     android:layout_marginTop="@dimen/timepicker_minimum_margin_top_bottom"
@@ -42,7 +41,5 @@
         android:id="@+id/radial_picker"
         android:layout_width="@dimen/timepicker_radial_picker_dimen"
         android:layout_height="match_parent"
-        android:layout_gravity="center"
-        android:focusable="true"
-        android:focusableInTouchMode="true" />
+        android:layout_gravity="center" />
 </LinearLayout>
diff --git a/core/res/res/layout/action_mode_close_item_material.xml b/core/res/res/layout/action_mode_close_item_material.xml
new file mode 100644
index 0000000..8eb780b
--- /dev/null
+++ b/core/res/res/layout/action_mode_close_item_material.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/action_mode_close_button"
+        android:focusable="true"
+        android:clickable="true"
+        android:paddingStart="8dip"
+        android:src="?android:attr/actionModeCloseDrawable"
+        style="?android:attr/actionModeCloseButtonStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_marginEnd="16dip" />
diff --git a/core/res/res/layout/preference_material.xml b/core/res/res/layout/preference_material.xml
index 778e70a..a137149 100644
--- a/core/res/res/layout/preference_material.xml
+++ b/core/res/res/layout/preference_material.xml
@@ -24,7 +24,8 @@
     android:gravity="center_vertical"
     android:paddingStart="?attr/listPreferredItemPaddingStart"
     android:paddingEnd="?attr/listPreferredItemPaddingEnd"
-    android:background="?attr/activatedBackgroundIndicator">
+    android:background="?attr/activatedBackgroundIndicator"
+    android:clipToPadding="false">
 
     <LinearLayout
         android:id="@+id/icon_frame"
diff --git a/core/res/res/layout/screen_toolbar.xml b/core/res/res/layout/screen_toolbar.xml
index 039e89f..88c9cf6 100644
--- a/core/res/res/layout/screen_toolbar.xml
+++ b/core/res/res/layout/screen_toolbar.xml
@@ -41,6 +41,7 @@
             android:id="@+id/action_bar"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:navigationContentDescription="@string/action_bar_up_description"
             style="?attr/toolbarStyle" />
         <com.android.internal.widget.ActionBarContextView
             android:id="@+id/action_context_bar"
diff --git a/core/res/res/layout/time_picker_holo.xml b/core/res/res/layout/time_picker_holo.xml
index 483eb6d..08d2211 100644
--- a/core/res/res/layout/time_picker_holo.xml
+++ b/core/res/res/layout/time_picker_holo.xml
@@ -18,20 +18,17 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-          android:layout_width="wrap_content"
-          android:layout_height="match_parent"
-          android:orientation="vertical"
-          android:focusable="true" >
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
     <include
-            layout="@layout/time_header_label"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/timepicker_header_height"
-            android:layout_gravity="center" />
+        layout="@layout/time_header_label"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/timepicker_header_height"
+        android:layout_gravity="center" />
     <android.widget.RadialTimePickerView
-            android:id="@+id/radial_picker"
-            android:layout_width="wrap_content"
-            android:layout_height="@dimen/timepicker_radial_picker_dimen"
-            android:layout_gravity="center"
-            android:focusable="true"
-            android:focusableInTouchMode="true" />
+        android:id="@+id/radial_picker"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/timepicker_radial_picker_dimen"
+        android:layout_gravity="center" />
 </LinearLayout>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b6c876d..35ff766 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1228,9 +1228,9 @@
     <string name="smv_application" msgid="3307209192155442829">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) porušila své vlastní vynucené zásady StrictMode."</string>
     <string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> porušil své vlastní vynucené zásady StrictMode."</string>
     <string name="android_upgrading_title" msgid="1584192285441405746">"Android se upgraduje..."</string>
-    <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimalizace aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimalizování aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Spouštění aplikací."</string>
-    <string name="android_upgrading_complete" msgid="1405954754112999229">"Probíhá dokončování spouštění."</string>
+    <string name="android_upgrading_complete" msgid="1405954754112999229">"Dokončování inicializace."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"Běží aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="heavy_weight_notification_detail" msgid="1721681741617898865">"Dotykem přepnete aplikaci"</string>
     <string name="heavy_weight_switcher_title" msgid="7153167085403298169">"Přepnout aplikace?"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 451ac5d..fb635dd 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1294,7 +1294,7 @@
     <string name="sms_control_yes" msgid="3663725993855816807">"Autoriser"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Refuser"</string>
     <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; souhaite envoyer un message à &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
-    <string name="sms_short_code_details" msgid="5873295990846059400">"Ce "<b>"peut entraîner des frais"</b>" sur votre compte."</string>
+    <string name="sms_short_code_details" msgid="5873295990846059400">"Ceci "<b>"peut entraîner des frais"</b>" sur votre compte."</string>
     <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Cela entraînera des frais sur votre compte."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Envoyer"</string>
     <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Annuler"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 88adba5..7add9a6 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1294,8 +1294,8 @@
     <string name="sms_control_yes" msgid="3663725993855816807">"Izinkan"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Tolak"</string>
     <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingin mengirim pesan kepada &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
-    <string name="sms_short_code_details" msgid="5873295990846059400">"Tindakan ini "<b>"dapat menimbulkan tagihan"</b>" terhadap akun seluler Anda."</string>
-    <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Tindakan ini akan menimbulkan tagihan terhadap akun seluler Anda."</b></string>
+    <string name="sms_short_code_details" msgid="5873295990846059400">"Tindakan ini "<b>"dapat menimbulkan tagihan"</b>" untuk ponsel Anda."</string>
+    <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Tindakan ini akan menimbulkan tagihan untuk ponsel Anda."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Kirim"</string>
     <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Batal"</string>
     <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Ingat pilihan saya"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 3120104..7a72fd3 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1588,7 +1588,7 @@
     <string name="media_route_status_in_use" msgid="4533786031090198063">"בשימוש"</string>
     <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"מסך מובנה"</string>
     <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"‏מסך HDMI"</string>
-    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"שכבת על #<xliff:g id="ID">%1$d</xliff:g>"</string>
+    <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"שכבת-על #<xliff:g id="ID">%1$d</xliff:g>"</string>
     <string name="display_manager_overlay_display_title" msgid="652124517672257172">"‏<xliff:g id="NAME">%1$s</xliff:g>: ‎<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>‎, ‏<xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
     <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", מאובטח"</string>
     <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"העברת מסך מתבצעת"</string>
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index 423e250..2778b6e 100644
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -34,4 +34,11 @@
     </string-array>
 
     <bool name="config_auto_attach_data_on_creation">false</bool>
+
+    <!-- Values for GPS configuration (Verizon) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>CAPABILITIES=0x31</item>
+        <item>LPP_PROFILE=3</item>
+        <item>GPS_LOCK=3</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc120/config.xml b/core/res/res/values-mcc310-mnc120/config.xml
index 62001d9..3b95db5 100644
--- a/core/res/res/values-mcc310-mnc120/config.xml
+++ b/core/res/res/values-mcc310-mnc120/config.xml
@@ -25,4 +25,10 @@
     -->
     <integer name="config_mobile_mtu">1422</integer>
 
+    <!-- Values for GPS configuration (Sprint) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>CAPABILITIES=0x31</item>
+        <item>GPS_LOCK=3</item>
+        <item>LPP_PROFILE=2</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc150/config.xml b/core/res/res/values-mcc310-mnc150/config.xml
index f1936f4..00d2db8 100644
--- a/core/res/res/values-mcc310-mnc150/config.xml
+++ b/core/res/res/values-mcc310-mnc150/config.xml
@@ -33,4 +33,10 @@
         <item>315</item>
         <item>316</item>
     </string-array>
+    <!-- Values for GPS configuration (AT&T) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>CAPABILITIES=0x33</item>
+        <item>LPP_PROFILE=3</item>
+        <item>GPS_LOCK=1</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml
index 00cdaeb..2f9394a 100644
--- a/core/res/res/values-mcc310-mnc260/config.xml
+++ b/core/res/res/values-mcc310-mnc260/config.xml
@@ -25,9 +25,10 @@
     -->
     <integer name="config_mobile_mtu">1440</integer>
 
-    <!-- Values for GPS configuration -->
+    <!-- Values for GPS configuration (T-Mobile) -->
     <string-array translatable="false" name="config_gpsParameters">
-        <item>"SUPL_PORT=7279"</item>
+        <item>CAPABILITEIS=0x33</item>
         <item>GPS_LOCK=1</item>
+        <item>LPP_PROFILE=2</item>
     </string-array>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc410/config.xml
index 9e63047..edf6d9f 100644
--- a/core/res/res/values-mcc310-mnc410/config.xml
+++ b/core/res/res/values-mcc310-mnc410/config.xml
@@ -40,8 +40,15 @@
         <item>315</item>
         <item>316</item>
     </string-array>
-    <!-- Values for GPS configuration -->
+    <!-- Values for GPS configuration (AT&T) -->
     <string-array translatable="false" name="config_gpsParameters">
-        <item>"SUPL_HOST=supl.google.com"</item>
+        <item>CAPABILITIES=0x33</item>
+        <item>GPS_LOCK=1</item>
+        <item>LPP_PROFILE=3</item>
+    </string-array>
+    <!-- Do not translate. Defines the slots is Two Digit Number for dialing normally not USSD -->
+    <string-array name="config_twoDigitNumberPattern">
+        <item>"0"</item>
+        <item>"00"</item>
     </string-array>
 </resources>
diff --git a/core/res/res/values-mcc311-mnc190/config.xml b/core/res/res/values-mcc311-mnc190/config.xml
index a6c4d1b..b4e436d 100644
--- a/core/res/res/values-mcc311-mnc190/config.xml
+++ b/core/res/res/values-mcc311-mnc190/config.xml
@@ -37,4 +37,11 @@
          note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
     <string translatable="false" name="config_tether_apndata">Tether,broadband.cellular1.net,,,,,,,,,311,190,,DUN</string>
 
+    <!-- Values for GPS configuration (Sprint) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>CAPABILITIES=0x31</item>
+        <item>GPS_LOCK=3</item>
+        <item>LPP_PROFILE=2</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index e5af60b..cd5d55b 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -44,4 +44,11 @@
     <bool name="config_mobile_allow_volte_vt">false</bool>
 
     <bool name="config_auto_attach_data_on_creation">false</bool>
+
+    <!-- Values for GPS configuration (Verizon) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>CAPABILITIES=0x31</item>
+        <item>GPS_LOCK=3</item>
+        <item>LPP_PROFILE=3</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 0a109ba..2e0792a 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1774,6 +1774,6 @@
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
-    <string name="battery_saver_description" msgid="2510530476513605742">"Para ajudar a melhorar a vida útil da bateria, a economia de bateria reduz o desempenho do dispositivo e restringe a vibração e a maioria dos dados em segundo plano. É possível que apps de e-mail, mensagens, entre outros, que dependem de sincronização não sejam atualizados a menos que sejam abertos.\n\nA economia de bateria é desativada automaticamente quando o dispositivo estiver carregando."</string>
+    <string name="battery_saver_description" msgid="2510530476513605742">"Para ajudar a melhorar a vida útil da bateria, a economia de bateria reduz o desempenho do dispositivo e restringe a vibração e a maioria dos dados em segundo plano. É possível que apps de e-mail, mensagens, entre outros que dependem de sincronização não sejam atualizados a menos que sejam abertos.\n\nA economia de bateria é desativada automaticamente quando o dispositivo estiver carregando."</string>
     <string name="downtime_condition_summary" msgid="8761776337475705749">"Até o período de inatividade terminar às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index daad675..f95d29d 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1295,7 +1295,7 @@
     <string name="sms_control_no" msgid="625438561395534982">"Kataza"</string>
     <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ingependa kutuma ujumbe kwa &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
     <string name="sms_short_code_details" msgid="5873295990846059400">"Hii "<b>"huenda ikasababisha ulipe gharama"</b>" kwenye akaunti ya kifaa chako cha mkononi."</string>
-    <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Hii itasababisha ulipe gharama kwenye akaunti ya kifaa chako cha mkononi."</b></string>
+    <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Hii itafanya ulipe gharama kwenye akaunti ya kifaa chako cha mkononi."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Tuma"</string>
     <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Ghairi"</string>
     <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Kumbuka chaguo yangu"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 516bea4..2c0ed15 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -54,17 +54,17 @@
     <string name="serviceErased" msgid="1288584695297200972">"அழித்தல் வெற்றியடைந்தது."</string>
     <string name="passwordIncorrect" msgid="7612208839450128715">"தவறான கடவுச்சொல்."</string>
     <string name="mmiComplete" msgid="8232527495411698359">"MMI நிறைவடைந்தது."</string>
-    <string name="badPin" msgid="9015277645546710014">"உள்ளிட்ட பழைய PIN தவறானது."</string>
+    <string name="badPin" msgid="9015277645546710014">"உள்ளிட்ட பழைய பின் தவறானது."</string>
     <string name="badPuk" msgid="5487257647081132201">"உள்ளிட்ட PUK2 தவறானது."</string>
     <string name="mismatchPin" msgid="609379054496863419">"உள்ளிட்ட PINகள் பொருந்தவில்லை."</string>
-    <string name="invalidPin" msgid="3850018445187475377">"4 இலிருந்து 8 எண்கள் வரையுள்ள PIN ஐத் தட்டச்சு செய்யவும்."</string>
+    <string name="invalidPin" msgid="3850018445187475377">"4 இலிருந்து 8 எண்கள் வரையுள்ள பின் ஐத் தட்டச்சு செய்யவும்."</string>
     <string name="invalidPuk" msgid="8761456210898036513">"8 அல்லது அதற்கு மேல் எண்கள் உள்ள PUK ஐத் தட்டச்சு செய்யவும்."</string>
-    <string name="needPuk" msgid="919668385956251611">"உங்கள் SIM கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது. அதைத் திறக்க PUK குறியீட்டைத் உள்ளிடவும்."</string>
-    <string name="needPuk2" msgid="4526033371987193070">"SIM கார்டைத் தடுப்பு நீக்க PUK2 ஐ உள்ளிடவும்."</string>
-    <string name="enablePin" msgid="209412020907207950">"தோல்வி, SIM/RUIM பூட்டை இயக்கவும்."</string>
+    <string name="needPuk" msgid="919668385956251611">"உங்கள் சிம் கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது. அதைத் திறக்க PUK குறியீட்டைத் உள்ளிடவும்."</string>
+    <string name="needPuk2" msgid="4526033371987193070">"சிம் கார்டைத் தடுப்பு நீக்க PUK2 ஐ உள்ளிடவும்."</string>
+    <string name="enablePin" msgid="209412020907207950">"தோல்வி, சிம்/RUIM பூட்டை இயக்கவும்."</string>
   <plurals name="pinpuk_attempts">
-    <item quantity="one" msgid="6596245285809790142">"SIM பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
-    <item quantity="other" msgid="7530597808358774740">"SIM பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
+    <item quantity="one" msgid="6596245285809790142">"சிம் பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
+    <item quantity="other" msgid="7530597808358774740">"சிம் பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
   </plurals>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
@@ -76,7 +76,7 @@
     <string name="CwMmi" msgid="9129678056795016867">"அழைப்பு காத்திருப்பு"</string>
     <string name="BaMmi" msgid="455193067926770581">"அழைப்புத் தவிர்ப்பு"</string>
     <string name="PwdMmi" msgid="7043715687905254199">"கடவுச்சொல்லை மாற்று"</string>
-    <string name="PinMmi" msgid="3113117780361190304">"PIN ஐ மாற்று"</string>
+    <string name="PinMmi" msgid="3113117780361190304">"பின்னை மாற்று"</string>
     <string name="CnipMmi" msgid="3110534680557857162">"இருக்கும் எண்ணை அழைக்கிறது"</string>
     <string name="CnirMmi" msgid="3062102121430548731">"அழைப்பு எண் வரையறுக்கப்பட்டது"</string>
     <string name="ThreeWCMmi" msgid="9051047170321190368">"மும்முனை அழைப்பு"</string>
@@ -289,11 +289,11 @@
     <string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"நிகழ்வுகளுக்குச் செய்தி வழியாகப் பதிலை அனுப்புதல்"</string>
     <string name="permdesc_sendRespondViaMessageRequest" msgid="7107648548468778734">"உள்வரும் அழைப்புகளுக்கான நிகழ்வுகளுக்கு, செய்தி வழியாகப் பதிலளிப்பதை நிர்வகிப்பதற்கு, பிற மெசேஜ் பயன்பாடுகளுக்குக் கோரிக்கைகளை அனுப்புவதற்குப் பயன்பாட்டை அனுமதிக்கிறது."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"உங்கள் உரைச் செய்திகளை (SMS அல்லது MMS) படித்தல்"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"உங்கள் டேப்லெட் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
-    <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"உங்கள் மொபைல் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்கப் பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"உங்கள் டேப்லெட் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
+    <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"உங்கள் மொபைல் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்கப் பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
     <string name="permlab_writeSms" msgid="3216950472636214774">"உங்கள் உரைச் செய்திகளைத் (SMS அல்லது MMS) திருத்துதல்"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"டேப்லெட் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
-    <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"ஃபோன் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"டேப்லெட் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
+    <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"ஃபோன் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"உரைச் செய்திகளைப் (WAP) பெறுதல்"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAP செய்திகளைப் பெற, செயற்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது. உங்களுக்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிக்க அல்லது நீக்குவதற்கான திறன் இந்த அனுமதியில் உள்ளடங்கும்."</string>
     <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetooth செய்திகளைப் (MAP) பெறுதல்"</string>
@@ -541,8 +541,8 @@
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ஒலியளவு மற்றும் வெளியீட்டிற்கு ஸ்பீக்கர்கள் பயன்படுத்தப்படுவது போன்ற ஒட்டுமொத்த ஆடியோ அமைப்புகளைக் கட்டுப்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ஆடியோவைப் பதிவுசெய்தல்"</string>
     <string name="permdesc_recordAudio" msgid="4906839301087980680">"மைக்ரோஃபோன் மூலம் ஆடியோவைப் பதிவுசெய்ய பயன்பாட்டை அனுமதிக்கிறது. உங்கள் உறுதிப்படுத்தல் இல்லாமல் எந்நேரத்திலும் ஆடியோவைப் பதிவுசெய்ய இந்த அனுமதி பயன்பாட்டை அனுமதிக்கிறது."</string>
-    <string name="permlab_sim_communication" msgid="1180265879464893029">"SIM தகவல்தொடர்பு"</string>
-    <string name="permdesc_sim_communication" msgid="5725159654279639498">"SIM க்குக் கட்டளைகளை அனுப்ப பயன்பாட்டை அனுமதிக்கிறது. இது மிகவும் ஆபத்தானதாகும்."</string>
+    <string name="permlab_sim_communication" msgid="1180265879464893029">"சிம் தகவல்தொடர்பு"</string>
+    <string name="permdesc_sim_communication" msgid="5725159654279639498">"சிம் க்குக் கட்டளைகளை அனுப்ப பயன்பாட்டை அனுமதிக்கிறது. இது மிகவும் ஆபத்தானதாகும்."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"படங்கள் மற்றும் வீடியோக்களை எடுத்தல்"</string>
     <string name="permdesc_camera" msgid="8497216524735535009">"கேமரா மூலமாகப் படங்களையும், வீடியோக்களையும் எடுக்க பயன்பாட்டை அனுமதிக்கிறது. உங்கள் உறுதிப்படுத்தல் இன்றி கேமராவை எந்நேரத்திலும் பயன்படுத்தப் பயன்பாட்டை இது அனுமதிக்கிறது."</string>
     <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"கேமரா பயன்பாட்டில் இருக்கும்போது டிரான்ஸ்மிட் இன்டிகேட்டர் LED ஐ முடக்குதல்"</string>
@@ -882,14 +882,14 @@
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"அலுவலகம்"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"மற்றவை"</string>
     <string name="quick_contacts_not_available" msgid="746098007828579688">"இதைப் பார்ப்பதற்குகந்த பயன்பாடு எதுவும் நிறுவப்படவில்லை."</string>
-    <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN குறியீட்டை உள்ளிடவும்"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK மற்றும் புதிய PIN குறியீட்டை உள்ளிடவும்"</string>
+    <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"பின் குறியீட்டை உள்ளிடவும்"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK மற்றும் புதிய பின் குறியீட்டை உள்ளிடவும்"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK குறியீடு"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"புதிய PIN குறியீடு"</string>
+    <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"புதிய பின் குறியீடு"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"கடவுச்சொல்லை உள்ளிட, தொடவும்"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"திறக்க, கடவுச்சொல்லை உள்ளிடவும்"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"திறக்க, PIN ஐ உள்ளிடவும்"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"தவறான PIN குறியீடு."</string>
+    <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"திறக்க, பின்னை உள்ளிடவும்"</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"தவறான பின் குறியீடு."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"தடைநீக்க, மெனுவை அழுத்தி பின்பு 0 ஐ அழுத்தவும்."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"அவசர எண்"</string>
     <string name="lockscreen_carrier_default" msgid="8963839242565653192">"சேவை இல்லை."</string>
@@ -907,13 +907,13 @@
     <string name="lockscreen_charged" msgid="321635745684060624">"சார்ஜ் செய்யப்பட்டது"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"உங்கள் சார்ஜரை இணைக்கவும்."</string>
-    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM கார்டு இல்லை"</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"டேப்லெட்டில் SIM கார்டு இல்லை."</string>
-    <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"தொலைபேசியில் SIM கார்டு இல்லை."</string>
-    <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"SIM கார்டைச் செருகவும்."</string>
-    <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM கார்டு இல்லை அல்லது படிக்கக்கூடியதாக இல்லை. SIM கார்டைச் செருகவும்."</string>
-    <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"பயன்படுத்த முடியாத SIM கார்டு."</string>
-    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"உங்கள் SIM கார்டு நிரந்தரமாக முடக்கப்பட்டது.\n மற்றொரு SIM கார்டிற்காக உங்கள் வயர்லெஸ் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string>
+    <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"சிம் கார்டு இல்லை"</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"டேப்லெட்டில் சிம் கார்டு இல்லை."</string>
+    <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"தொலைபேசியில் சிம் கார்டு இல்லை."</string>
+    <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"சிம் கார்டைச் செருகவும்."</string>
+    <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"சிம் கார்டு இல்லை அல்லது படிக்கக்கூடியதாக இல்லை. சிம் கார்டைச் செருகவும்."</string>
+    <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"பயன்படுத்த முடியாத சிம் கார்டு."</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"உங்கள் சிம் கார்டு நிரந்தரமாக முடக்கப்பட்டது.\n மற்றொரு சிம் கார்டிற்காக உங்கள் வயர்லெஸ் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string>
     <string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"முந்தைய ட்ராக்"</string>
     <string name="lockscreen_transport_next_description" msgid="573285210424377338">"அடுத்த ட்ராக்"</string>
     <string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"இடைநிறுத்து"</string>
@@ -923,13 +923,13 @@
     <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"வேகமாக முன்செல்"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"அவசர அழைப்புகள் மட்டும்"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"நெட்வொர்க் பூட்டப்பட்டது"</string>
-    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது."</string>
+    <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"சிம் கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது."</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"பயனர் கையேட்டைப் பார்க்கவும் அல்லது வாடிக்கையாளர் சேவையைத் தொடர்புகொள்ளவும்."</string>
-    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM கார்டு பூட்டப்பட்டுள்ளது."</string>
-    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM கார்டைத் திறக்கிறது..."</string>
+    <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"சிம் கார்டு பூட்டப்பட்டுள்ளது."</string>
+    <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"சிம் கார்டைத் திறக்கிறது..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"உங்கள் PIN ஐ <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> முறை தவறாக வரைந்தால், உங்கள் Google உள்நுழைவைப் பயன்படுத்தி டேப்லெட்டைத் திறக்குமாறு கேட்கப்படுவீர்கள். \n\n <xliff:g id="NUMBER_2">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> முறை தவறாக வரைந்தால், உங்கள் Google உள்நுழைவைப் பயன்படுத்தி மொபைலைத் திறக்குமாறு கேட்கப்படுவீர்கள். \n\n <xliff:g id="NUMBER_2">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"டேப்லெட்டைத் தடைநீக்க <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக முயற்சித்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, டேப்லெட்டானது ஆரம்ப இயல்புநிலைக்கு மீட்டமைக்கப்பட்டு, எல்லா பயனர் தரவும் இழக்கப்படும்."</string>
@@ -1284,8 +1284,8 @@
     <string name="wifi_p2p_invitation_to_connect_title" msgid="4958803948658533637">"இணைவதற்கான அழைப்பு"</string>
     <string name="wifi_p2p_from_message" msgid="570389174731951769">"அனுப்புநர்:"</string>
     <string name="wifi_p2p_to_message" msgid="248968974522044099">"பெறுநர்:"</string>
-    <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"பின்வரும் அவசியமான PIN ஐ உள்ளிடவும்:"</string>
-    <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+    <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"பின்வரும் அவசியமான பின்னை உள்ளிடவும்:"</string>
+    <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"பின்:"</string>
     <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> உடன் டேப்லெட் இணைக்கப்படும்போது, வைஃபையிலிருந்து தற்காலிகமாகத் துண்டிக்கப்படும்."</string>
     <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> உடன் மொபைல் இணைக்கப்படும்போது, வைஃபையிலிருந்து தற்காலிகமாகத் துண்டிக்கப்படும்."</string>
     <string name="select_character" msgid="3365550120617701745">"எழுத்துக்குறியைச் செருகு"</string>
@@ -1302,10 +1302,10 @@
     <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"அமைப்பு &gt; பயன்பாடுகள் என்பதில் பிறகு நீங்கள் மாற்றலாம்"</string>
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"எப்போதும் அனுமதி"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"ஒருபோதும் அனுமதிக்காதே"</string>
-    <string name="sim_removed_title" msgid="6227712319223226185">"SIM கார்டு அகற்றப்பட்டது"</string>
-    <string name="sim_removed_message" msgid="5450336489923274918">"சரியான SIM கார்டைச் செருகி, மறுதொடக்கம் செய்யும் வரை செல்லுலார் நெட்வொர்க் கிடைக்காது."</string>
+    <string name="sim_removed_title" msgid="6227712319223226185">"சிம் கார்டு அகற்றப்பட்டது"</string>
+    <string name="sim_removed_message" msgid="5450336489923274918">"சரியான சிம் கார்டைச் செருகி, மறுதொடக்கம் செய்யும் வரை செல்லுலார் நெட்வொர்க் கிடைக்காது."</string>
     <string name="sim_done_button" msgid="827949989369963775">"முடிந்தது"</string>
-    <string name="sim_added_title" msgid="3719670512889674693">"SIM கார்டு சேர்க்கப்பட்டது"</string>
+    <string name="sim_added_title" msgid="3719670512889674693">"சிம் கார்டு சேர்க்கப்பட்டது"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"செல்லுலார் நெட்வொர்க்கை அணுக உங்கள் சாதனத்தை மறுதொடக்கம் செய்யவும்."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"மறுதொடக்கம்"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"நேரத்தை அமை"</string>
@@ -1568,7 +1568,7 @@
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"இப்போது மட்டும்"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s பணி சுயவிவரத்தை ஆதரிக்காது"</string>
     <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"டேப்லெட்"</string>
-    <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"மொபைல்"</string>
+    <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ஃபோன்"</string>
     <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ஹெட்ஃபோன்கள்"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"மொபைல் வைக்கும் கருவியின் ஸ்பீக்கர்கள்"</string>
     <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
@@ -1600,21 +1600,21 @@
     <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"வடிவத்தை மறந்துவிட்டீர்களா"</string>
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"தவறான வடிவம்"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"தவறான கடவுச்சொல்"</string>
-    <string name="kg_wrong_pin" msgid="1131306510833563801">"தவறான PIN"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"தவறான பின்"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"உங்கள் வடிவத்தை வரையவும்"</string>
-    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PIN ஐ உள்ளிடவும்"</string>
-    <string name="kg_pin_instructions" msgid="2377242233495111557">"PIN ஐ உள்ளிடுக"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"சிம் பின்னை உள்ளிடவும்"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"பின்னை உள்ளிடுக"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"கடவுச்சொல்லை உள்ளிடவும்"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு மொபைல் நிறுவனங்களைத் தொடர்புகொள்ளவும்."</string>
-    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"விரும்பிய PIN குறியீட்டை உள்ளிடவும்"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"விரும்பிய PIN குறியீட்டை உறுதிப்படுத்தவும்"</string>
-    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM கார்டின் தடையைநீக்குகிறது..."</string>
-    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"தவறான PIN குறியீடு."</string>
-    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 இலிருந்து 8 எண்கள் வரையுள்ள PIN ஐ உள்ளிடவும்."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு மொபைல் நிறுவனங்களைத் தொடர்புகொள்ளவும்."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"விரும்பிய பின் குறியீட்டை உள்ளிடவும்"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"விரும்பிய பின் குறியீட்டை உறுதிப்படுத்தவும்"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"சிம் கார்டின் தடையைநீக்குகிறது..."</string>
+    <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"தவறான பின் குறியீடு."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 இலிருந்து 8 எண்கள் வரையுள்ள பின்னை உள்ளிடவும்."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"PUK குறியீட்டில் 8 எழுத்துக்குறிகள் இருக்க வேண்டும்."</string>
-    <string name="kg_invalid_puk" msgid="3638289409676051243">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் SIM ஐ நிரந்தரமாக முடக்கிவிடும்."</string>
-    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN குறியீடுகள் பொருந்தவில்லை"</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் சிம் ஐ நிரந்தரமாக முடக்கிவிடும்."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"பின் குறியீடுகள் பொருந்தவில்லை"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"அதிகமான வடிவ முயற்சிகள்"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"திறக்க, உங்கள் Google கணக்கு மூலம் உள்நுழையவும்."</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"பயனர்பெயர் (மின்னஞ்சல்)"</string>
@@ -1623,7 +1623,7 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"தவறான பயனர்பெயர் அல்லது கடவுச்சொல்."</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"உங்கள் பயனர்பெயர் அல்லது கடவுச்சொல்லை மறந்துவிட்டீர்களா?\n"<b>"google.com/accounts/recovery"</b>" ஐப் பார்வையிடவும்."</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"கணக்கைச் சரிபார்க்கிறது…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"உங்கள் PIN ஐ <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகளில் மீண்டும் முயற்சிக்கவும்."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"டேப்லெட்டைத் திறக்க <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக முயற்சித்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, டேப்லெட்டானது ஆரம்பநிலைக்கு மீட்டமைக்கப்பட்டு, எல்லா பயனர் தரவையும் இழப்பீர்கள்."</string>
@@ -1734,15 +1734,15 @@
     <string name="reason_service_unavailable" msgid="7824008732243903268">"பிரிண்டர் இயக்கத்தில் இல்லை"</string>
     <string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> சேவை நிறுவப்பட்டது"</string>
     <string name="print_service_installed_message" msgid="5897362931070459152">"இயக்குவதற்குத் தட்டவும்"</string>
-    <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"நிர்வாகி PIN ஐ உள்ளிடவும்"</string>
-    <string name="restr_pin_enter_pin" msgid="3395953421368476103">"PIN ஐ உள்ளிடவும்"</string>
+    <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"நிர்வாகி பின்னை உள்ளிடவும்"</string>
+    <string name="restr_pin_enter_pin" msgid="3395953421368476103">"பின்னை உள்ளிடவும்"</string>
     <string name="restr_pin_incorrect" msgid="8571512003955077924">"தவறானது"</string>
-    <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"நடப்பு PIN"</string>
-    <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"புதிய PIN"</string>
-    <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"புதிய PIN ஐ உறுதிப்படுத்தவும்"</string>
-    <string name="restr_pin_create_pin" msgid="8017600000263450337">"வரம்புகளைத் திருத்துவதற்கு PIN ஐ உருவாக்கவும்"</string>
+    <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"நடப்பு பின்"</string>
+    <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"புதிய பின்"</string>
+    <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"புதிய பின்னை உறுதிப்படுத்தவும்"</string>
+    <string name="restr_pin_create_pin" msgid="8017600000263450337">"வரம்புகளைத் திருத்துவதற்கு பின்னை உருவாக்கவும்"</string>
     <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PINகள் பொருந்தவில்லை. மீண்டும் முயற்சிக்கவும்."</string>
-    <string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN மிகவும் சிறியதாக உள்ளது. குறைந்தது 4 இலக்கங்கள் இருக்க வேண்டும்."</string>
+    <string name="restr_pin_error_too_short" msgid="8173982756265777792">"பின் மிகவும் சிறியதாக உள்ளது. குறைந்தது 4 இலக்கங்கள் இருக்க வேண்டும்."</string>
   <plurals name="restr_pin_countdown">
     <item quantity="one" msgid="311050995198548675">"1 வினாடி கழித்து முயற்சிக்கவும்"</item>
     <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்"</item>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index c4a6e53c..cd0ef0b 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1294,8 +1294,8 @@
     <string name="sms_control_yes" msgid="3663725993855816807">"允許"</string>
     <string name="sms_control_no" msgid="625438561395534982">"拒絕"</string>
     <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 要求將訊息傳送至 &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;。"</string>
-    <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_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_remember_choice" msgid="5289538592272218136">"記住我的選擇"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 093ce63..fdb54ec 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -376,7 +376,7 @@
     <string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"允許應用程式啟動完整備份確認使用者介面 (不建議任何應用程式使用)。"</string>
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"顯示未授權視窗"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"允許應用程式為內部系統使用者介面建立視窗 (不建議一般應用程式使用)。"</string>
-    <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"在其他應用程式之上顯示内容"</string>
+    <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"在其他應用程式之上顯示內容"</string>
     <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"允許應用程式在其他應用程式頂層或使用者介面的特定部分繪圖。這可能會干擾您在所有應用程式中的介面使用行為,或是使您在其他應用程式中預期看到的內容發生變化。"</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"編輯全域動畫速度"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"允許應用程式隨時變更全域的動畫速度 (更快或更慢)。"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a798d2e..d1cc1fd 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -514,8 +514,8 @@
         <!-- Flag indicating whether this Window's transition should overlap with
              the exiting transition of the called Activity when the called Activity
              finishes. Corresponds to
-             {@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
-        <attr name="windowAllowExitTransitionOverlap" format="boolean"/>
+             {@link android.view.Window#setAllowReturnTransitionOverlap(boolean)}. -->
+        <attr name="windowAllowReturnTransitionOverlap" format="boolean"/>
 
         <!-- Indicates whether or not shared elements should use an overlay
              during transitions. The default value is true. -->
@@ -1726,6 +1726,34 @@
         <enum name="KEYCODE_LAST_CHANNEL" value="229" />
         <enum name="KEYCODE_TV_DATA_SERVICE" value="230" />
         <enum name="KEYCODE_VOICE_ASSIST" value="231" />
+        <enum name="KEYCODE_TV_RADIO_SERVICE" value="232" />
+        <enum name="KEYCODE_TV_TELETEXT" value="233" />
+        <enum name="KEYCODE_TV_NUMBER_ENTRY" value="234" />
+        <enum name="KEYCODE_TV_TERRESTRIAL_ANALOG" value="235" />
+        <enum name="KEYCODE_TV_TERRESTRIAL_DIGITAL" value="236" />
+        <enum name="KEYCODE_TV_SATELLITE" value="237" />
+        <enum name="KEYCODE_TV_SATELLITE_BS" value="238" />
+        <enum name="KEYCODE_TV_SATELLITE_CS" value="239" />
+        <enum name="KEYCODE_TV_SATELLITE_SERVICE" value="240" />
+        <enum name="KEYCODE_TV_NETWORK" value="241" />
+        <enum name="KEYCODE_TV_ANTENNA_CABLE" value="242" />
+        <enum name="KEYCODE_TV_INPUT_HDMI_1" value="243" />
+        <enum name="KEYCODE_TV_INPUT_HDMI_2" value="244" />
+        <enum name="KEYCODE_TV_INPUT_HDMI_3" value="245" />
+        <enum name="KEYCODE_TV_INPUT_HDMI_4" value="246" />
+        <enum name="KEYCODE_TV_INPUT_COMPOSITE_1" value="247" />
+        <enum name="KEYCODE_TV_INPUT_COMPOSITE_2" value="248" />
+        <enum name="KEYCODE_TV_INPUT_COMPONENT_1" value="249" />
+        <enum name="KEYCODE_TV_INPUT_COMPONENT_2" value="250" />
+        <enum name="KEYCODE_TV_INPUT_VGA_1" value="251" />
+        <enum name="KEYCODE_TV_AUDIO_DESCRIPTION" value="252" />
+        <enum name="KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP" value="253" />
+        <enum name="KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN" value="254" />
+        <enum name="KEYCODE_TV_ZOOM_MODE" value="255" />
+        <enum name="KEYCODE_TV_CONTENTS_MENU" value="256" />
+        <enum name="KEYCODE_TV_MEDIA_CONTEXT_MENU" value="257" />
+        <enum name="KEYCODE_TV_TIMER_PROGRAMMING" value="258" />
+        <enum name="KEYCODE_HELP" value="259" />
     </attr>
 
     <!-- ***************************************************************** -->
@@ -1853,8 +1881,8 @@
         <!-- Flag indicating whether this Window's transition should overlap with
              the exiting transition of the called Activity when the called Activity
              finishes. Corresponds to
-             {@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
-        <attr name="windowAllowExitTransitionOverlap"/>
+             {@link android.view.Window#setAllowReturnTransitionOverlap(boolean)}. -->
+        <attr name="windowAllowReturnTransitionOverlap"/>
 
         <!-- Indicates whether or not shared elements should use an overlay
              during transitions. The default value is true. -->
@@ -1921,6 +1949,8 @@
         <attr name="listItemLayout" format="reference" />
         <attr name="progressLayout" format="reference" />
         <attr name="horizontalProgressLayout" format="reference" />
+        <!-- @hide Whether fullDark, etc. should use default values if null. -->
+        <attr name="needsDefaultBackgrounds" format="boolean" />
     </declare-styleable>
 
     <!-- Fragment animation class attributes. -->
@@ -4316,7 +4346,7 @@
         <!-- @hide The layout of the legacy DatePicker. -->
         <attr name="legacyLayout" />
         <!-- The background color for the date selector 's day of week. -->
-        <attr name="dayOfWeekBackgroundColor" format="color" />
+        <attr name="dayOfWeekBackground" format="color|reference" />
         <!-- The text color for the date selector's day of week. -->
         <attr name="dayOfWeekTextAppearance" format="reference" />
         <!-- The month's text appearance in the date selector. -->
@@ -4325,8 +4355,8 @@
         <attr name="headerDayOfMonthTextAppearance" format="reference" />
         <!-- The year's text appearance in the date selector. -->
         <attr name="headerYearTextAppearance" format="reference" />
-        <!-- The background color for the date selector. -->
-        <attr name="headerBackgroundColor" />
+        <!-- The background for the date selector. -->
+        <attr name="headerBackground" />
         <!-- @hide The selected text color for the date selector. Used as a
              backup if the text appearance does not explicitly have a color
              set for the selected state. -->
@@ -4623,29 +4653,29 @@
         <attr name="legacyLayout" format="reference" />
         <!-- @hide The layout of the time picker. -->
         <attr name="internalLayout" />
-        <!-- The text appearance for the AM/PM header of the TimePicker. -->
+        <!-- The text appearance for the AM/PM header. -->
         <attr name="headerAmPmTextAppearance" format="reference" />
-        <!-- The text appearance for the time header of the TimePicker. -->
+        <!-- The text appearance for the time header. -->
         <attr name="headerTimeTextAppearance" format="reference" />
         <!-- @hide The text color for selected time header of the TimePicker.
              This will override the value from the text appearance if it does
              not explicitly have a color set for the selected state. -->
         <attr name="headerSelectedTextColor" format="color" />
-        <!-- The background color for the header of the TimePicker. -->
-        <attr name="headerBackgroundColor" format="color" />
-        <!-- The color for the hours/minutes numbers of the TimePicker. -->
+        <!-- The background for the header containing the currently selected time. -->
+        <attr name="headerBackground" />
+        <!-- The color for the hours/minutes numbers. -->
         <attr name="numbersTextColor" format="color" />
-        <!-- The background color for the hours/minutes numbers of the TimePicker. -->
+        <!-- The background color for the hours/minutes numbers. -->
         <attr name="numbersBackgroundColor" format="color" />
-        <!-- The color for the AM/PM selectors of the TimePicker. -->
+        <!-- The color for the AM/PM selectors. -->
         <attr name="amPmTextColor" format="color" />
-        <!-- The background color state list for the AM/PM selectors of the TimePicker. -->
+        <!-- The background color state list for the AM/PM selectors. -->
         <attr name="amPmBackgroundColor" format="color" />
         <!-- @hide The background color for the AM/PM selectors of the
              TimePicker when selected. Used if the background color does not
              explicitly have a color set for the selected state. -->
         <attr name="amPmSelectedBackgroundColor" format="color" />
-        <!-- The color for the hours/minutes selector of the TimePicker. -->
+        <!-- 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,
@@ -5656,12 +5686,12 @@
         <attr name="maximumAngle" format="float" />
     </declare-styleable>
 
-    <!-- Use <code>patternMotion</code> as the root tag of the XML resource that
-         describes a {@link android.transition.PatternMotion}. This must be used
+    <!-- Use <code>patternPathMotion</code> as the root tag of the XML resource that
+         describes a {@link android.transition.PatternPathMotion}. This must be used
          within a transition with which the PathMotion should be associated. -->
-    <declare-styleable name="PatternMotion">
-        <!-- The path string describing the pattern to use for the PathMotion. -->
-        <attr name="pathData" />
+    <declare-styleable name="PatternPathMotion">
+        <!-- The path string describing the pattern to use for the PathPathMotion. -->
+        <attr name="patternPathData" format="string" />
     </declare-styleable>
 
     <!-- ========================== -->
@@ -6570,12 +6600,12 @@
             <flag name="vertical" value="0x2" />
         </attr>
         <!-- Optional parameter which indicates where this widget can be shown,
-             ie. home screen, keyguard, recents or any combination thereof.
+             ie. home screen, keyguard, search bar or any combination thereof.
              Supports combined values using | operator. -->
         <attr name="widgetCategory" format="integer">
             <flag name="home_screen" value="0x1" />
             <flag name="keyguard" value="0x2" />
-            <flag name="recents" value="0x4" />
+            <flag name="searchbox" value="0x4" />
         </attr>
     </declare-styleable>
 
@@ -6627,6 +6657,53 @@
              IDs (through the android:id attribute) instead of tags because
              they are faster and allow for compile-time type checking. -->
         <attr name="tag" />
+
+        <!-- The Transition that will be used to move Views out of the scene when the
+             fragment is removed, hidden, or detached when not popping the back stack.
+             Corresponds to {@link android.app.Fragment#setExitTransition(
+             android.transition.Transition)} -->
+        <attr name="fragmentExitTransition" format="reference"/>
+
+        <!-- The Transition that will be used to move Views into the initial scene.
+             Corresponds to {@link android.app.Fragment#setEnterTransition(
+             android.transition.Transition)} -->
+        <attr name="fragmentEnterTransition" format="reference"/>
+
+        <!-- The Transition that will be used for shared elements transferred into the content
+             Scene.
+             Corresponds to {@link android.app.Fragment#setSharedElementEnterTransition(
+             android.transition.Transition)} -->
+        <attr name="fragmentSharedElementEnterTransition" format="reference"/>
+
+        <!-- The Transition that will be used to move Views out of the scene when the Fragment is
+             preparing to be removed, hidden, or detached because of popping the back stack.
+             Corresponds to {@link android.app.Fragment#setReturnTransition(
+             android.transition.Transition)} -->
+        <attr name="fragmentReturnTransition" format="reference"/>
+
+        <!-- The Transition that will be used for shared elements transferred back during a
+             pop of the back stack. This Transition acts in the leaving Fragment.
+             Corresponds to {@link android.app.Fragment#setSharedElementReturnTransition(
+             android.transition.Transition)} -->
+        <attr name="fragmentSharedElementReturnTransition" format="reference"/>
+
+        <!-- The Transition that will be used to move Views in to the scene when returning due
+             to popping a back stack.
+             Corresponds to {@link android.app.Fragment#setReenterTransition(
+             android.transition.Transition)} -->
+        <attr name="fragmentReenterTransition" format="reference"/>
+
+        <!-- Sets whether the enter and exit transitions should overlap when transitioning
+             forward.
+             Corresponds to {@link android.app.Fragment#setAllowEnterTransitionOverlap(
+             boolean)} -->
+        <attr name="fragmentAllowEnterTransitionOverlap" format="reference"/>
+
+        <!-- Sets whether the enter and exit transitions should overlap when transitioning
+             because of popping the back stack.
+             Corresponds to {@link android.app.Fragment#setAllowReturnTransitionOverlap(
+             boolean)} -->
+        <attr name="fragmentAllowReturnTransitionOverlap" format="reference"/>
     </declare-styleable>
 
     <!-- Use <code>device-admin</code> as the root tag of the XML resource that
@@ -7040,6 +7117,8 @@
         <attr name="backgroundSplit" />
         <!-- Specifies a fixed height for the action mode bar. -->
         <attr name="height" />
+        <!-- Specifies a layout to use for the "close" item at the starting edge. -->
+        <attr name="closeItemLayout" format="reference" />
     </declare-styleable>
 
     <declare-styleable name="SearchView">
@@ -7072,6 +7151,7 @@
         <attr name="queryBackground" format="reference" />
         <!-- Background for the section containing the action (e.g. voice search) -->
         <attr name="submitBackground" format="reference" />
+        <attr name="focusable" />
     </declare-styleable>
 
     <declare-styleable name="Switch">
@@ -7112,9 +7192,9 @@
         <!-- Drawable to use as the icon bitmap. -->
         <attr name="bitmap" format="reference" />
         <!-- X coordinate of the icon hot spot. -->
-        <attr name="hotSpotX" format="float" />
+        <attr name="hotSpotX" format="dimension" />
         <!-- Y coordinate of the icon hot spot. -->
-        <attr name="hotSpotY" format="float" />
+        <attr name="hotSpotY" format="dimension" />
     </declare-styleable>
 
     <declare-styleable name="Storage">
@@ -7355,6 +7435,9 @@
     <!-- @removed -->
     <attr name="__removed1" format="reference" />
 
+    <!-- TODO: Spacer to be removed from here and public.xml -->
+    <attr name="__removed2" format="reference" />
+
     <!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
          XML resource that describes TV content rating of a {@link android.media.tv.TvInputService},
          which is referenced from its
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f5f079c..b63b91d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -374,7 +374,7 @@
     <bool name="config_useAttentionLight">false</bool>
 
     <!-- If this is true, the screen will fade off. -->
-    <bool name="config_animateScreenLights">true</bool>
+    <bool name="config_animateScreenLights">false</bool>
 
     <!-- If this is true, key chords can be used to take a screenshot on the device. -->
     <bool name="config_enableScreenshotChord">true</bool>
@@ -628,7 +628,7 @@
     <integer name="config_notificationsBatteryLedOff">2875</integer>
 
     <!-- Number of notifications to keep in the notification service historical archive -->
-    <integer name="config_notificationServiceArchiveSize">250</integer>
+    <integer name="config_notificationServiceArchiveSize">100</integer>
 
     <!-- Allow the menu hard key to be disabled in LockScreen on some devices -->
     <bool name="config_disableMenuKeyInLockScreen">false</bool>
@@ -1456,6 +1456,10 @@
     <!-- Set to true if after a provisioning apn the radio should be restarted -->
     <bool name="config_restartRadioAfterProvisioning">false</bool>
 
+    <!-- Boolean indicating if RADIO POWER OFF is required on receiving SIM REFRESH with RESET.
+         This will be handled by modem if it is false. -->
+    <bool name="config_requireRadioPowerOffOnSimRefreshReset">false</bool>
+
     <!-- Vibrator pattern to be used as the default for notifications
          that specify DEFAULT_VIBRATE.
      -->
@@ -1533,6 +1537,7 @@
         <item>com.android.server.notification.ValidateNotificationPeople</item>
         <item>com.android.server.notification.PackagePriorityExtractor</item>
         <item>com.android.server.notification.NotificationIntrusivenessExtractor</item>
+        <item>com.android.server.notification.PackageVisibilityExtractor</item>
     </string-array>
 
     <!-- Flag indicating that this device does not rotate and will always remain in its default
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5e76a87..a4c3474 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2146,7 +2146,7 @@
   <public type="attr" name="windowExitTransition" />
   <public type="attr" name="windowSharedElementEnterTransition" />
   <public type="attr" name="windowSharedElementExitTransition" />
-  <public type="attr" name="windowAllowExitTransitionOverlap" />
+  <public type="attr" name="windowAllowReturnTransitionOverlap" />
   <public type="attr" name="windowAllowEnterTransitionOverlap" />
   <public type="attr" name="sessionService" />
   <public type="attr" name="stackViewStyle" />
@@ -2235,7 +2235,7 @@
   <public type="attr" name="launchTaskBehindTargetAnimation" />
   <public type="attr" name="launchTaskBehindSourceAnimation" />
   <public type="attr" name="restrictionType" />
-  <public type="attr" name="dayOfWeekBackgroundColor" />
+  <public type="attr" name="dayOfWeekBackground" />
   <public type="attr" name="dayOfWeekTextAppearance" />
   <public type="attr" name="headerMonthTextAppearance" />
   <public type="attr" name="headerDayOfMonthTextAppearance" />
@@ -2248,7 +2248,7 @@
   <public type="attr" name="timePickerDialogTheme" />
   <public type="attr" name="headerTimeTextAppearance" />
   <public type="attr" name="headerAmPmTextAppearance" />
-  <public type="attr" name="headerBackgroundColor" />
+  <public type="attr" name="__removed2" />
   <public type="attr" name="numbersTextColor" />
   <public type="attr" name="numbersBackgroundColor" />
   <public type="attr" name="numbersSelectorColor" />
@@ -2282,6 +2282,15 @@
   <public type="attr" name="spotShadowAlpha" />
   <public type="attr" name="navigationIcon" />
   <public type="attr" name="navigationContentDescription" />
+  <public type="attr" name="fragmentExitTransition" />
+  <public type="attr" name="fragmentEnterTransition" />
+  <public type="attr" name="fragmentSharedElementEnterTransition" />
+  <public type="attr" name="fragmentReturnTransition" />
+  <public type="attr" name="fragmentSharedElementReturnTransition" />
+  <public type="attr" name="fragmentReenterTransition" />
+  <public type="attr" name="fragmentAllowEnterTransitionOverlap" />
+  <public type="attr" name="fragmentAllowReturnTransitionOverlap" />
+  <public type="attr" name="patternPathData" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 4aed037..c6d0b0b 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -62,6 +62,7 @@
         <item name="centerMedium">@drawable/popup_center_medium</item>
         <item name="progressLayout">@layout/progress_dialog</item>
         <item name="horizontalProgressLayout">@layout/alert_dialog_progress</item>
+        <item name="needsDefaultBackgrounds">false</item>
     </style>
 
     <style name="Widget.PreferenceFrameLayout">
diff --git a/core/res/res/values/styles_holo.xml b/core/res/res/values/styles_holo.xml
index 2a54ccf..c7d2db1 100644
--- a/core/res/res/values/styles_holo.xml
+++ b/core/res/res/values/styles_holo.xml
@@ -468,7 +468,7 @@
         <item name="internalLayout">@layout/time_picker_holo</item>
         <item name="headerTimeTextAppearance">@style/TextAppearance.Holo.TimePicker.TimeLabel</item>
         <item name="headerAmPmTextAppearance">@style/TextAppearance.Holo.TimePicker.AmPmLabel</item>
-        <item name="headerBackgroundColor">@color/timepicker_default_background_holo_dark</item>
+        <item name="headerBackground">@color/timepicker_default_background_holo_dark</item>
         <item name="headerSelectedTextColor">@color/holo_blue_light</item>
         <item name="numbersTextColor">@color/timepicker_default_text_color_holo_dark</item>
         <item name="numbersBackgroundColor">@color/timepicker_default_background_holo_dark</item>
@@ -484,9 +484,9 @@
         <item name="internalLayout">@layout/date_picker_holo</item>
         <item name="calendarViewShown">true</item>
         <!-- New-style date picker attributes. -->
-        <item name="dayOfWeekBackgroundColor">@color/datepicker_default_header_dayofweek_background_color_holo_dark</item>
+        <item name="dayOfWeekBackground">@color/datepicker_default_header_dayofweek_background_color_holo_dark</item>
         <item name="dayOfWeekTextAppearance">@style/TextAppearance.Holo.DatePicker.DayOfWeekLabel</item>
-        <item name="headerBackgroundColor">@color/datepicker_default_header_selector_background_holo_dark</item>
+        <item name="headerBackground">@color/datepicker_default_header_selector_background_holo_dark</item>
         <item name="headerMonthTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.MonthLabel</item>
         <item name="headerDayOfMonthTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.DayOfMonthLabel</item>
         <item name="headerYearTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.YearLabel</item>
@@ -892,7 +892,7 @@
         <item name="internalLayout">@layout/time_picker_holo</item>
         <item name="headerTimeTextAppearance">@style/TextAppearance.Holo.Light.TimePicker.TimeLabel</item>
         <item name="headerAmPmTextAppearance">@style/TextAppearance.Holo.Light.TimePicker.AmPmLabel</item>
-        <item name="headerBackgroundColor">@color/timepicker_default_background_holo_light</item>
+        <item name="headerBackground">@color/timepicker_default_background_holo_light</item>
         <item name="headerSelectedTextColor">@color/holo_blue_light</item>
         <item name="numbersTextColor">@color/timepicker_default_text_color_holo_light</item>
         <item name="numbersBackgroundColor">@color/timepicker_default_background_holo_light</item>
@@ -908,12 +908,12 @@
         <item name="internalLayout">@layout/date_picker_holo</item>
         <item name="calendarViewShown">true</item>
         <!-- New-style date picker attributes. -->
-        <item name="dayOfWeekBackgroundColor">@color/datepicker_default_header_dayofweek_background_color_holo_light</item>
+        <item name="dayOfWeekBackground">@color/datepicker_default_header_dayofweek_background_color_holo_light</item>
         <item name="dayOfWeekTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.DayOfWeekLabel</item>
         <item name="headerMonthTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.MonthLabel</item>
         <item name="headerDayOfMonthTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.DayOfMonthLabel</item>
         <item name="headerYearTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.YearLabel</item>
-        <item name="headerBackgroundColor">@color/datepicker_default_header_selector_background_holo_light</item>
+        <item name="headerBackground">@color/datepicker_default_header_selector_background_holo_light</item>
         <item name="headerSelectedTextColor">@color/holo_blue_light</item>
         <item name="yearListItemTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.List.YearLabel</item>
         <item name="yearListSelectorColor">@color/datepicker_default_circle_background_color_holo_light</item>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 8b3cbaf..a7335af 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -619,7 +619,7 @@
         <item name="headerTimeTextAppearance">@style/TextAppearance.Material.TimePicker.TimeLabel</item>
         <item name="headerAmPmTextAppearance">@style/TextAppearance.Material.TimePicker.AmPmLabel</item>
         <item name="headerSelectedTextColor">?attr/textColorPrimaryInverse</item>
-        <item name="headerBackgroundColor">?attr/colorAccent</item>
+        <item name="headerBackground">@drawable/time_picker_header_material</item>
         <item name="numbersTextColor">?attr/textColorSecondary</item>
         <item name="numbersBackgroundColor">#10ffffff</item>
         <item name="amPmTextColor">?attr/textColorSecondary</item>
@@ -634,13 +634,13 @@
         <!-- Attributes for new-style DatePicker. -->
         <item name="internalLayout">@layout/date_picker_holo</item>
         <item name="calendarViewShown">true</item>
-        <item name="dayOfWeekBackgroundColor">#10000000</item>
+        <item name="dayOfWeekBackground">#10000000</item>
         <item name="dayOfWeekTextAppearance">@style/TextAppearance.Material.DatePicker.DayOfWeekLabel</item>
         <item name="headerMonthTextAppearance">@style/TextAppearance.Material.DatePicker.MonthLabel</item>
         <item name="headerDayOfMonthTextAppearance">@style/TextAppearance.Material.DatePicker.DayOfMonthLabel</item>
         <item name="headerYearTextAppearance">@style/TextAppearance.Material.DatePicker.YearLabel</item>
         <item name="headerSelectedTextColor">?attr/textColorPrimaryInverse</item>
-        <item name="headerBackgroundColor">?attr/colorAccent</item>
+        <item name="headerBackground">?attr/colorAccent</item>
         <item name="yearListItemTextAppearance">@style/TextAppearance.Material.DatePicker.List.YearLabel</item>
         <item name="yearListSelectorColor">?attr/colorControlActivated</item>
         <item name="calendarTextColor">?attr/textColorSecondary</item>
@@ -838,7 +838,7 @@
     </style>
 
     <style name="Widget.Material.ActionButton.CloseMode">
-        <item name="background">@drawable/btn_cab_done_material</item>
+        <item name="background">?attr/selectableItemBackgroundBorderless</item>
     </style>
 
     <style name="Widget.Material.ActionButton.Overflow">
@@ -901,6 +901,7 @@
     <style name="Widget.Material.ActionMode" parent="Widget.ActionMode">
         <item name="titleTextStyle">@style/TextAppearance.Material.Widget.ActionMode.Title</item>
         <item name="subtitleTextStyle">@style/TextAppearance.Material.Widget.ActionMode.Subtitle</item>
+        <item name="closeItemLayout">@layout/action_mode_close_item_material</item>
     </style>
 
     <style name="Widget.Material.FastScroll" parent="Widget.FastScroll">
@@ -1068,16 +1069,16 @@
     <!-- Dialog styles -->
 
     <style name="AlertDialog.Material" parent="AlertDialog">
-        <item name="fullDark">@color/transparent</item>
-        <item name="topDark">@color/transparent</item>
-        <item name="centerDark">@color/transparent</item>
-        <item name="bottomDark">@color/transparent</item>
-        <item name="fullBright">@color/transparent</item>
-        <item name="topBright">@color/transparent</item>
-        <item name="centerBright">@color/transparent</item>
-        <item name="bottomBright">@color/transparent</item>
-        <item name="bottomMedium">@color/transparent</item>
-        <item name="centerMedium">@color/transparent</item>
+        <item name="fullDark">@null</item>
+        <item name="topDark">@null</item>
+        <item name="centerDark">@null</item>
+        <item name="bottomDark">@null</item>
+        <item name="fullBright">@null</item>
+        <item name="topBright">@null</item>
+        <item name="centerBright">@null</item>
+        <item name="bottomBright">@null</item>
+        <item name="bottomMedium">@null</item>
+        <item name="centerMedium">@null</item>
         <item name="layout">@layout/alert_dialog_material</item>
         <item name="listLayout">@layout/select_dialog_material</item>
         <item name="progressLayout">@layout/progress_dialog_material</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 06bd2ec..1b0f9c4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -283,6 +283,7 @@
   <java-symbol type="bool" name="config_camera_sound_forced" />
   <java-symbol type="bool" name="config_dontPreferApn" />
   <java-symbol type="bool" name="config_restartRadioAfterProvisioning" />
+  <java-symbol type="bool" name="config_requireRadioPowerOffOnSimRefreshReset" />
   <java-symbol type="bool" name="config_speed_up_audio_on_mt_calls" />
   <java-symbol type="bool" name="config_useFixedVolume" />
   <java-symbol type="bool" name="config_forceDefaultOrientation" />
@@ -2000,4 +2001,5 @@
   <java-symbol type="id" name="parentMatrix" />
   <java-symbol type="bool" name="config_auto_attach_data_on_creation" />
   <java-symbol type="id" name="date_picker_month_day_year_layout" />
+  <java-symbol type="attr" name="closeItemLayout" />
 </resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 2296a12..ab5cd5a 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -306,7 +306,7 @@
         <item name="actionOverflowMenuStyle">@style/Widget.Material.PopupMenu.Overflow</item>
         <item name="actionModeBackground">@drawable/cab_background_top_material</item>
         <item name="actionModeSplitBackground">@drawable/cab_background_bottom_material</item>
-        <item name="actionModeCloseDrawable">@drawable/ic_cab_done_material</item>
+        <item name="actionModeCloseDrawable">@drawable/ic_ab_back_material</item>
         <item name="actionBarTabStyle">@style/Widget.Material.ActionBar.TabView</item>
         <item name="actionBarTabBarStyle">@style/Widget.Material.ActionBar.TabBar</item>
         <item name="actionBarTabTextStyle">@style/Widget.Material.ActionBar.TabText</item>
@@ -652,7 +652,7 @@
         <item name="actionOverflowMenuStyle">@style/Widget.Material.Light.PopupMenu.Overflow</item>
         <item name="actionModeBackground">@drawable/cab_background_top_material</item>
         <item name="actionModeSplitBackground">@drawable/cab_background_bottom_material</item>
-        <item name="actionModeCloseDrawable">@drawable/ic_cab_done_material</item>
+        <item name="actionModeCloseDrawable">@drawable/ic_ab_back_material</item>
         <item name="actionBarTabStyle">@style/Widget.Material.Light.ActionBar.TabView</item>
         <item name="actionBarTabBarStyle">@style/Widget.Material.Light.ActionBar.TabBar</item>
         <item name="actionBarTabTextStyle">@style/Widget.Material.Light.ActionBar.TabText</item>
diff --git a/core/tests/ConnectivityManagerTest/assets/accesspoints.xml b/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
deleted file mode 100644
index ce6eebc..0000000
--- a/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-  <accesspoint>
-    <ssid>opennet</ssid>
-    <security>NONE</security>
-  </accesspoint>
-  <accesspoint>
-    <ssid>GoogleGuest</ssid>
-    <security>NONE</security>
-  </accesspoint>
-  <accesspoint>
-    <ssid>securenetdhcp</ssid>
-    <security>PSK</security>
-    <password>androidwifi</password>
-  </accesspoint>
-  <accesspoint>
-    <ssid>securenetstatic</ssid>
-    <security>PSK</security>
-    <password>androidwifi</password>
-    <ip>192.168.14.2</ip>
-    <gateway>192.168.14.1</gateway>
-    <networkprefixlength>24</networkprefixlength>
-    <dns1>192.168.14.1</dns1>
-    <dns2>192.168.1.9</dns2>
-  </accesspoint>
-<!-- TODO: This AP is outdated and only supports 2.4GHz.
-           Need to switch to a new dual-band AP.
-           Enable this test case again once the configuration is completed.
-     bug#: 9470594
-  <accesspoint>
-    <ssid>botnet</ssid>
-    <security>EAP</security>
-    <eap>PEAP</eap>
-    <phase2>MSCHAPV2</phase2>
-    <identity>donut</identity>
-    <password>android</password>
-  </accesspoint>
--->
-</resources>
-
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
deleted file mode 100644
index 1222c8b..0000000
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (C) 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.connectivitymanagertest;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
-import android.net.LinkAddress;
-import android.net.RouteInfo;
-import android.net.StaticIpConfiguration;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.AuthAlgorithm;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiEnterpriseConfig;
-
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.List;
-
-
-/**
- * Help class to process configurations of access points saved in an XML file.
- * The configurations of an access point is included in tag
- * <accesspoint></accesspoint>. The supported configuration includes: ssid,
- * security, eap, phase2, identity, password, anonymousidentity, cacert, usercert,
- * in which each is included in the corresponding tags. Static IP setting is also supported.
- * Tags that can be used include: ip, gateway, networkprefixlength, dns1, dns2. All access points
- * have to be enclosed in tags of <resources></resources>.
- *
- * The following is a sample configuration file for an access point using EAP-PEAP with MSCHAP2.
- * <resources>
- *   <accesspoint>
- *   <ssid>testnet</ssid>
- *   <security>EAP</security>
- *   <eap>PEAP</eap>
- *   <phase2>MSCHAP2</phase2>
- *   <identity>donut</identity</identity>
- *   <password>abcdefgh</password>
- *   </accesspoint>
- * </resources>
- *
- * Note:ssid and security have to be the first two tags
- *      for static ip setting, tag "ip" should be listed before other fields: dns, gateway,
- *      networkprefixlength.
- */
-public class AccessPointParserHelper {
-    static final int NONE = 0;
-    static final int WEP = 1;
-    static final int PSK = 2;
-    static final int EAP = 3;
-
-    List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
-
-    private int getSecurityType (String security) {
-        if (security.equalsIgnoreCase("NONE")) {
-            return NONE;
-        } else if (security.equalsIgnoreCase("WEP")) {
-            return WEP;
-        } else if (security.equalsIgnoreCase("PSK")) {
-            return PSK;
-        } else if (security.equalsIgnoreCase("EAP")) {
-            return EAP;
-        } else {
-            return -1;
-        }
-    }
-
-    private boolean validateEapValue(String value) {
-        if (value.equalsIgnoreCase("PEAP") ||
-                value.equalsIgnoreCase("TLS") ||
-                value.equalsIgnoreCase("TTLS")) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    DefaultHandler mHandler = new DefaultHandler() {
-
-        boolean ssid = false;
-        boolean security = false;
-        boolean password = false;
-        boolean ip = false;
-        boolean gateway = false;
-        boolean networkprefix = false;
-        boolean dns1 = false;
-        boolean dns2 = false;
-        boolean eap = false;
-        boolean phase2 = false;
-        boolean identity = false;
-        boolean anonymousidentity = false;
-        boolean cacert = false;
-        boolean usercert = false;
-        WifiConfiguration config = null;
-        int securityType = NONE;
-        StaticIpConfiguration mStaticIpConfiguration = null;
-        InetAddress mInetAddr = null;
-
-        @Override
-        public void startElement(String uri, String localName, String tagName,
-                Attributes attributes) throws SAXException {
-            if (tagName.equalsIgnoreCase("accesspoint")) {
-                config = new WifiConfiguration();
-            }
-            if (tagName.equalsIgnoreCase("ssid")) {
-                ssid = true;
-            }
-            if (tagName.equalsIgnoreCase("security")) {
-                security = true;
-            }
-            if (tagName.equalsIgnoreCase("password")) {
-                password = true;
-            }
-            if (tagName.equalsIgnoreCase("eap")) {
-                eap = true;
-            }
-            if (tagName.equalsIgnoreCase("phase2")) {
-                phase2 = true;
-            }
-            if (tagName.equalsIgnoreCase("identity")) {
-                identity = true;
-            }
-            if (tagName.equalsIgnoreCase("anonymousidentity")) {
-                anonymousidentity = true;
-            }
-            if (tagName.equalsIgnoreCase("cacert")) {
-                cacert = true;
-            }
-            if (tagName.equalsIgnoreCase("usercert")) {
-                usercert = true;
-            }
-            if (tagName.equalsIgnoreCase("ip")) {
-                mStaticIpConfiguration = new StaticIpConfiguration();
-                ip = true;
-            }
-            if (tagName.equalsIgnoreCase("gateway")) {
-                gateway = true;
-            }
-            if (tagName.equalsIgnoreCase("networkprefixlength")) {
-                networkprefix = true;
-            }
-            if (tagName.equalsIgnoreCase("dns1")) {
-                dns1 = true;
-            }
-            if (tagName.equalsIgnoreCase("dns2")) {
-                dns2 = true;
-            }
-        }
-
-        @Override
-        public void endElement(String uri, String localName, String tagName) throws SAXException {
-            if (tagName.equalsIgnoreCase("accesspoint")) {
-                if (mStaticIpConfiguration != null) {
-                    config.setIpAssignment(IpAssignment.STATIC);
-                    config.setStaticIpConfiguration(mStaticIpConfiguration);
-                } else {
-                    config.setIpAssignment(IpAssignment.DHCP);
-                }
-                config.setProxySettings(ProxySettings.NONE);
-                networks.add(config);
-                mStaticIpConfiguration = null;
-            }
-        }
-
-        @Override
-        public void characters(char ch[], int start, int length) throws SAXException {
-            if (ssid) {
-                config.SSID = new String(ch, start, length);
-                ssid = false;
-            }
-            if (security) {
-                String securityStr = (new String(ch, start, length)).toUpperCase();
-                securityType = getSecurityType(securityStr);
-                switch (securityType) {
-                    case NONE:
-                        config.allowedKeyManagement.set(KeyMgmt.NONE);
-                        break;
-                    case WEP:
-                        config.allowedKeyManagement.set(KeyMgmt.NONE);
-                        config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
-                        config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
-                        break;
-                    case PSK:
-                        config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
-                        break;
-                    case EAP:
-                        config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
-                        config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
-                        // Initialize other fields.
-                        config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
-                        config.enterpriseConfig.setCaCertificateAlias("");
-                        config.enterpriseConfig.setClientCertificateAlias("");
-                        config.enterpriseConfig.setIdentity("");
-                        config.enterpriseConfig.setAnonymousIdentity("");
-                        break;
-                    default:
-                        throw new SAXException();
-                }
-                security = false;
-            }
-            if (password) {
-                String passwordStr = new String(ch, start, length);
-                int len = passwordStr.length();
-                if (len == 0) {
-                    throw new SAXException();
-                }
-                if (securityType == WEP) {
-                    if ((len == 10 || len == 26 || len == 58) &&
-                            passwordStr.matches("[0-9A-Fa-f]*")) {
-                        config.wepKeys[0] = passwordStr;
-                    } else {
-                        config.wepKeys[0] = '"' + passwordStr + '"';
-                    }
-                } else if (securityType == PSK) {
-                    if (passwordStr.matches("[0-9A-Fa-f]{64}")) {
-                        config.preSharedKey = passwordStr;
-                    } else {
-                        config.preSharedKey = '"' + passwordStr + '"';
-                    }
-                } else if (securityType == EAP) {
-                    config.enterpriseConfig.setPassword(passwordStr);
-                } else {
-                    throw new SAXException();
-                }
-                password = false;
-            }
-            if (eap) {
-                String eapValue = new String(ch, start, length);
-                if (!validateEapValue(eapValue)) {
-                    throw new SAXException();
-                }
-                if (eapValue.equals("TLS")) {
-                    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
-                } else if (eapValue.equals("TTLS")) {
-                    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
-                } else if (eapValue.equals("PEAP")) {
-                    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
-                }
-                eap = false;
-            }
-            if (phase2) {
-                String phase2Value = new String(ch, start, length);
-                if (phase2Value.equals("PAP")) {
-                    config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP);
-                } else if (phase2Value.equals("MSCHAP")) {
-                    config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAP);
-                } else if (phase2Value.equals("MSCHAPV2")) {
-                    config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
-                } else if (phase2Value.equals("GTC")) {
-                    config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
-                }
-                phase2 = false;
-            }
-            if (identity) {
-                String identityValue = new String(ch, start, length);
-                config.enterpriseConfig.setIdentity(identityValue);
-                identity = false;
-            }
-            if (anonymousidentity) {
-                String anonyId = new String(ch, start, length);
-                config.enterpriseConfig.setAnonymousIdentity(anonyId);
-                anonymousidentity = false;
-            }
-            if (cacert) {
-                String cacertValue = new String(ch, start, length);
-                config.enterpriseConfig.setCaCertificateAlias(cacertValue);
-                cacert = false;
-            }
-            if (usercert) {
-                String usercertValue = new String(ch, start, length);
-                config.enterpriseConfig.setClientCertificateAlias(usercertValue);
-                usercert = false;
-            }
-            if (ip) {
-                try {
-                    String ipAddr = new String(ch, start, length);
-                    if (!InetAddress.isNumeric(ipAddr)) {
-                        throw new SAXException();
-                    }
-                    mInetAddr = InetAddress.getByName(ipAddr);
-                } catch (UnknownHostException e) {
-                    throw new SAXException();
-                }
-                ip = false;
-            }
-            if (gateway) {
-                try {
-                    String gwAddr = new String(ch, start, length);
-                    if (!InetAddress.isNumeric(gwAddr)) {
-                        throw new SAXException();
-                    }
-                    mStaticIpConfiguration.gateway = InetAddress.getByName(gwAddr);
-                } catch (UnknownHostException e) {
-                    throw new SAXException();
-                }
-                gateway = false;
-            }
-            if (networkprefix) {
-                try {
-                    int nwPrefixLength = Integer.parseInt(new String(ch, start, length));
-                    if ((nwPrefixLength < 0) || (nwPrefixLength > 32)) {
-                        throw new SAXException();
-                    }
-                    mStaticIpConfiguration.ipAddress = new LinkAddress(mInetAddr, nwPrefixLength);
-                } catch (NumberFormatException e) {
-                    throw new SAXException();
-                }
-                networkprefix = false;
-            }
-            if (dns1) {
-                try {
-                    String dnsAddr = new String(ch, start, length);
-                    if (!InetAddress.isNumeric(dnsAddr)) {
-                        throw new SAXException();
-                    }
-                    mStaticIpConfiguration.dnsServers.add(InetAddress.getByName(dnsAddr));
-                } catch (UnknownHostException e) {
-                    throw new SAXException();
-                }
-                dns1 = false;
-            }
-            if (dns2) {
-                try {
-                    String dnsAddr = new String(ch, start, length);
-                    if (!InetAddress.isNumeric(dnsAddr)) {
-                        throw new SAXException();
-                    }
-                    mStaticIpConfiguration.dnsServers.add(InetAddress.getByName(dnsAddr));
-                } catch (UnknownHostException e) {
-                    throw new SAXException();
-                }
-                dns2 = false;
-            }
-        }
-    };
-
-    /**
-     * Process the InputStream in
-     * @param in is the InputStream that can be used for XML parsing
-     * @throws Exception
-     */
-    public AccessPointParserHelper(InputStream in) throws Exception {
-        SAXParserFactory factory = SAXParserFactory.newInstance();
-        SAXParser saxParser = factory.newSAXParser();
-        saxParser.parse(in, mHandler);
-    }
-
-    public List<WifiConfiguration> getNetworkConfigurations() throws Exception {
-        return networks;
-    }
-}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
index 0f9d8e9..a3c5351 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
@@ -26,7 +26,6 @@
 import android.net.NetworkInfo.State;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiManager;
 import android.os.PowerManager;
 import android.os.SystemClock;
@@ -35,10 +34,8 @@
 import android.view.KeyEvent;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.UnknownHostException;
 import java.util.List;
-import java.util.regex.Pattern;
 
 
 /**
@@ -52,8 +49,6 @@
  */
 public class ConnectivityManagerTestBase extends InstrumentationTestCase {
 
-    private static final String LOG_TAG = "ConnectivityManagerTestBase";
-    private static final String ACCESS_POINT_FILE = "accesspoints.xml";
     private static final String PING_IP_ADDR = "8.8.8.8";
 
     protected static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
@@ -69,9 +64,10 @@
     protected static final int FAILURE = 1;
     protected static final int INIT = -1;
 
+    protected final String mLogTag;
+
     private ConnectivityReceiver mConnectivityReceiver = null;
     private WifiReceiver mWifiReceiver = null;
-    private AccessPointParserHelper mParseHelper = null;
 
     private long mLastConnectivityChangeTime = -1;
     protected ConnectivityManager mCm;
@@ -82,6 +78,11 @@
     /* Control Wifi States */
     public WifiManager mWifiManager;
 
+    public ConnectivityManagerTestBase(String logTag) {
+        super();
+        mLogTag = logTag;
+    }
+
     protected long getLastConnectivityChangeTime() {
         return mLastConnectivityChangeTime;
     }
@@ -94,7 +95,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             mLastConnectivityChangeTime = SystemClock.uptimeMillis();
-            log("ConnectivityReceiver: " + intent);
+            logv("ConnectivityReceiver: " + intent);
             String action = intent.getAction();
             if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                 Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
@@ -108,7 +109,7 @@
             String action = intent.getAction();
             Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
             if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
-                log("scan results are available");
+                logv("scan results are available");
                 synchronized (mWifiScanResultLock) {
                     mLastScanResult = mWifiManager.getScanResults();
                     mWifiScanResultLock.notifyAll();
@@ -130,7 +131,7 @@
         if (mWifiManager.isWifiApEnabled()) {
             // if soft AP is enabled, disable it
             mWifiManager.setWifiApEnabled(null, false);
-            log("Disable soft ap");
+            logv("Disable soft ap");
         }
 
         // register a connectivity receiver for CONNECTIVITY_ACTION;
@@ -148,32 +149,25 @@
         mIntentFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
         mContext.registerReceiver(mWifiReceiver, mIntentFilter);
 
-        log("Clear Wifi before we start the test.");
+        logv("Clear Wifi before we start the test.");
         removeConfiguredNetworksAndDisableWifi();
      }
 
-    protected List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
-        InputStream in = mContext.getAssets().open(ACCESS_POINT_FILE);
-        mParseHelper = new AccessPointParserHelper(in);
-        return mParseHelper.getNetworkConfigurations();
-    }
-
     // wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING,
     //                                      DISCONNECTED, UNKNOWN
     protected boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
         long startTime = SystemClock.uptimeMillis();
         while (true) {
             NetworkInfo ni = mCm.getNetworkInfo(networkType);
-            String niString = ni == null ? "null" : ni.toString();
             if (ni != null && expectedState.equals(ni.getState())) {
-                log("waitForNetworkState success: " + niString);
+                logv("waitForNetworkState success: %s", ni);
                 return true;
             }
             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
-                log("waitForNetworkState timeout: " + niString);
+                logv("waitForNetworkState timeout: %s", ni);
                 return false;
             }
-            log("waitForNetworkState interim: " + niString);
+            logv("waitForNetworkState interim: %s", ni);
             SystemClock.sleep(SHORT_TIMEOUT);
         }
     }
@@ -185,16 +179,14 @@
         while (true) {
             int state = mWifiManager.getWifiState();
             if (state == expectedState) {
-                log("waitForWifiState success: state=" + state);
+                logv("waitForWifiState success: state=" + state);
                 return true;
             }
             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
-                log(String.format("waitForWifiState timeout: expected=%d, actual=%d",
-                        expectedState, state));
+                logv("waitForWifiState timeout: expected=%d, actual=%d", expectedState, state);
                 return false;
             }
-            log(String.format("waitForWifiState interim: expected=%d, actual=%d",
-                    expectedState, state));
+            logv("waitForWifiState interim: expected=%d, actual=%d", expectedState, state);
             SystemClock.sleep(SHORT_TIMEOUT);
         }
     }
@@ -206,15 +198,15 @@
         while (true) {
             int state = mWifiManager.getWifiApState();
             if (state == expectedState) {
-                log("waitForWifiAPState success: state=" + state);
+                logv("waitForWifiAPState success: state=" + state);
                 return true;
             }
             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
-                log(String.format("waitForWifiAPState timeout: expected=%d, actual=%d",
+                logv(String.format("waitForWifiAPState timeout: expected=%d, actual=%d",
                         expectedState, state));
                 return false;
             }
-            log(String.format("waitForWifiAPState interim: expected=%d, actual=%d",
+            logv(String.format("waitForWifiAPState interim: expected=%d, actual=%d",
                     expectedState, state));
             SystemClock.sleep(SHORT_TIMEOUT);
         }
@@ -269,7 +261,7 @@
 
     // Turn screen off
     protected void turnScreenOff() {
-        log("Turn screen off");
+        logv("Turn screen off");
         PowerManager pm =
             (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         pm.goToSleep(SystemClock.uptimeMillis());
@@ -277,7 +269,7 @@
 
     // Turn screen on
     protected void turnScreenOn() {
-        log("Turn screen on");
+        logv("Turn screen on");
         PowerManager pm =
                 (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         pm.wakeUp(SystemClock.uptimeMillis());
@@ -305,7 +297,7 @@
                 // assume the chance that all servers are down is very small
                 for (int i = 0; i < hostList.length; i++ ) {
                     String host = hostList[i];
-                    log("Start ping test, ping " + host);
+                    logv("Start ping test, ping " + host);
                     Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
                     int status = p.waitFor();
                     if (status == 0) {
@@ -314,11 +306,11 @@
                     }
                 }
             } catch (UnknownHostException e) {
-                log("Ping test Fail: Unknown Host");
+                logv("Ping test Fail: Unknown Host");
             } catch (IOException e) {
-                log("Ping test Fail:  IOException");
+                logv("Ping test Fail:  IOException");
             } catch (InterruptedException e) {
-                log("Ping test Fail: InterruptedException");
+                logv("Ping test Fail: InterruptedException");
             }
         }
         // ping test timeout
@@ -331,29 +323,22 @@
      * We don't verify whether the connection is successful or not, leave this to the test
      */
     protected boolean connectToWifi(String knownSSID) {
-        WifiConfiguration config = new WifiConfiguration();
-        config.SSID = knownSSID;
-        config.allowedKeyManagement.set(KeyMgmt.NONE);
+        WifiConfiguration config = WifiConfigurationHelper.createOpenConfig(knownSSID);
         return connectToWifiWithConfiguration(config);
     }
 
     /**
      * Connect to Wi-Fi with the given configuration. Note the SSID in the configuration
      * is pure string, we need to convert it to quoted string.
-     * @param config
-     * @return
      */
     protected boolean connectToWifiWithConfiguration(WifiConfiguration config) {
-        String ssid = config.SSID;
-        config.SSID = convertToQuotedString(ssid);
-
         // If Wifi is not enabled, enable it
         if (!mWifiManager.isWifiEnabled()) {
-            log("Wifi is not enabled, enable it");
+            logv("Wifi is not enabled, enable it");
             mWifiManager.setWifiEnabled(true);
             // wait for the wifi state change before start scanning.
             if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT)) {
-                log("wait for WIFI_STATE_ENABLED failed");
+                logv("wait for WIFI_STATE_ENABLED failed");
                 return false;
             }
         }
@@ -361,10 +346,13 @@
         // Save network configuration and connect to network without scanning
         mWifiManager.connect(config,
             new WifiManager.ActionListener() {
+                @Override
                 public void onSuccess() {
                 }
+
+                @Override
                 public void onFailure(int reason) {
-                    log("connect failure " + reason);
+                    logv("connect failure " + reason);
                 }
             });
         return true;
@@ -376,25 +364,28 @@
     protected boolean disconnectAP() {
         // remove saved networks
         if (!mWifiManager.isWifiEnabled()) {
-            log("Enabled wifi before remove configured networks");
+            logv("Enabled wifi before remove configured networks");
             mWifiManager.setWifiEnabled(true);
             SystemClock.sleep(SHORT_TIMEOUT);
         }
 
         List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks();
         if (wifiConfigList == null) {
-            log("no configuration list is null");
+            logv("no configuration list is null");
             return true;
         }
-        log("size of wifiConfigList: " + wifiConfigList.size());
+        logv("size of wifiConfigList: " + wifiConfigList.size());
         for (WifiConfiguration wifiConfig: wifiConfigList) {
-            log("remove wifi configuration: " + wifiConfig.networkId);
+            logv("remove wifi configuration: " + wifiConfig.networkId);
             int netId = wifiConfig.networkId;
             mWifiManager.forget(netId, new WifiManager.ActionListener() {
+                    @Override
                     public void onSuccess() {
                     }
+
+                    @Override
                     public void onFailure(int reason) {
-                        log("Failed to forget " + reason);
+                        logv("Failed to forget " + reason);
                     }
                 });
         }
@@ -431,15 +422,14 @@
         long startTime = SystemClock.uptimeMillis();
         while (true) {
             NetworkInfo ni = mCm.getActiveNetworkInfo();
-            String niString = ni == null ? "null" : ni.toString();
             if (ni != null && ni.isConnected()) {
                 return true;
             }
             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
-                log("waitForActiveNetworkConnection timeout: " + niString);
+                logv("waitForActiveNetworkConnection timeout: %s", ni);
                 return false;
             }
-            log("waitForActiveNetworkConnection interim: " + niString);
+            logv("waitForActiveNetworkConnection interim: %s", ni);
             SystemClock.sleep(SHORT_TIMEOUT);
         }
     }
@@ -451,12 +441,11 @@
             if (ni == null) {
                 return true;
             }
-            String niString = ni.toString();
             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
-                log("waitForActiveNetworkConnection timeout: " + niString);
+                logv("waitForActiveNetworkConnection timeout: %s", ni);
                 return false;
             }
-            log("waitForActiveNetworkConnection interim: " + niString);
+            logv("waitForActiveNetworkConnection interim: %s", ni);
             SystemClock.sleep(SHORT_TIMEOUT);
         }
     }
@@ -467,12 +456,9 @@
         try {
             Process proc = Runtime.getRuntime().exec(new String[]{
                     "/system/bin/ping", "-W", "30", "-c", "1", PING_IP_ADDR});
-            int exitCode = proc.waitFor();
-            return exitCode == 0;
-        } catch (InterruptedException ie) {
-            Log.e(LOG_TAG, "InterruptedException while waiting for ping");
-        } catch (IOException ioe) {
-            Log.e(LOG_TAG, "IOException during ping", ioe);
+            return proc.waitFor() == 0;
+        } catch (InterruptedException | IOException e) {
+            Log.e(mLogTag, "Ping failed", e);
         }
         return false;
     }
@@ -489,8 +475,8 @@
         super.tearDown();
     }
 
-    private void log(String message) {
-        Log.v(LOG_TAG, message);
+    protected void logv(String format, Object... args) {
+        Log.v(mLogTag, String.format(format, args));
     }
 
     /**
@@ -506,22 +492,10 @@
         // step 2: verify Wifi state and network state;
         assertTrue("wifi state not connected with " + config.SSID,
                 waitForNetworkState(ConnectivityManager.TYPE_WIFI,
-                State.CONNECTED, LONG_TIMEOUT));
+                State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
 
         // step 3: verify the current connected network is the given SSID
         assertNotNull("no active wifi info", mWifiManager.getConnectionInfo());
         assertEquals("SSID mismatch", config.SSID, mWifiManager.getConnectionInfo().getSSID());
     }
-
-    /**
-     * checks if the input is a hexadecimal string of given length
-     *
-     * @param input string to be checked
-     * @param length required length of the string
-     * @return
-     */
-    protected static boolean isHex(String input, int length) {
-        Pattern p = Pattern.compile(String.format("[0-9A-Fa-f]{%d}", length));
-        return p.matcher(input).matches();
-    }
 }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java
new file mode 100644
index 0000000..f0a8367
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/WifiConfigurationHelper.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.connectivitymanagertest;
+
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.LinkAddress;
+import android.net.StaticIpConfiguration;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiEnterpriseConfig;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helper for dealing with creating {@link WifiConfiguration} objects.
+ */
+public class WifiConfigurationHelper {
+    private static final int NONE = 0;
+    private static final int WEP = 1;
+    private static final int PSK = 2;
+    private static final int EAP = 3;
+
+    /**
+     * Private constructor since this a static class.
+     */
+    private WifiConfigurationHelper() {}
+
+    /**
+     * Create a {@link WifiConfiguration} for an open network
+     *
+     * @param ssid The SSID of the wifi network
+     * @return The {@link WifiConfiguration}
+     */
+    public static WifiConfiguration createOpenConfig(String ssid) {
+        WifiConfiguration config = createGenericConfig(ssid);
+
+        config.allowedKeyManagement.set(KeyMgmt.NONE);
+        return config;
+    }
+
+    /**
+     * Create a {@link WifiConfiguration} for a WEP secured network
+     *
+     * @param ssid The SSID of the wifi network
+     * @param password Either a 10, 26, or 58 character hex string or the plain text password
+     * @return The {@link WifiConfiguration}
+     */
+    public static WifiConfiguration createWepConfig(String ssid, String password) {
+        WifiConfiguration config = createGenericConfig(ssid);
+
+        if (isHex(password, 10) || isHex(password, 26) || isHex(password, 58)) {
+            config.wepKeys[0] = password;
+        } else {
+            config.wepKeys[0] = quotedString(password);
+        }
+
+        config.allowedKeyManagement.set(KeyMgmt.NONE);
+        config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
+        config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+        return config;
+    }
+
+    /**
+     * Create a {@link WifiConfiguration} for a PSK secured network
+     *
+     * @param ssid The SSID of the wifi network
+     * @param password Either a 64 character hex string or the plain text password
+     * @return The {@link WifiConfiguration}
+     */
+    public static WifiConfiguration createPskConfig(String ssid, String password) {
+        WifiConfiguration config = createGenericConfig(ssid);
+
+        if (isHex(password, 64)) {
+            config.preSharedKey = password;
+        } else {
+            config.preSharedKey = quotedString(password);
+        }
+        config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+        return config;
+    }
+
+    /**
+     * Create a {@link WifiConfiguration} for an EAP secured network
+     *
+     * @param ssid The SSID of the wifi network
+     * @param password The password
+     * @param eapMethod The EAP method
+     * @param phase2 The phase 2 method or null
+     * @param identity The identity or null
+     * @param anonymousIdentity The anonymous identity or null
+     * @param caCert The CA certificate or null
+     * @param clientCert The client certificate or null
+     * @return The {@link WifiConfiguration}
+     */
+    public static WifiConfiguration createEapConfig(String ssid, String password, int eapMethod,
+            Integer phase2, String identity, String anonymousIdentity, String caCert,
+            String clientCert) {
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = quotedString(ssid);
+
+        config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+        config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+
+        // Set defaults
+        if (phase2 == null) phase2 = WifiEnterpriseConfig.Phase2.NONE;
+        if (identity == null) identity = "";
+        if (anonymousIdentity == null) anonymousIdentity = "";
+        if (caCert == null) caCert = "";
+        if (clientCert == null) clientCert = "";
+
+        config.enterpriseConfig.setPassword(password);
+        config.enterpriseConfig.setEapMethod(eapMethod);
+        config.enterpriseConfig.setPhase2Method(phase2);
+        config.enterpriseConfig.setIdentity(identity);
+        config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity);
+        config.enterpriseConfig.setCaCertificateAlias(caCert);
+        config.enterpriseConfig.setClientCertificateAlias(clientCert);
+        return config;
+    }
+
+    /**
+     * Create a generic {@link WifiConfiguration} used by the other create methods.
+     */
+    private static WifiConfiguration createGenericConfig(String ssid) {
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = quotedString(ssid);
+        config.setIpAssignment(IpAssignment.DHCP);
+        config.setProxySettings(ProxySettings.NONE);
+        return config;
+    }
+
+    /**
+     * Parse a JSON string for WiFi configurations stored as a JSON string.
+     * <p>
+     * This json string should be a list of dictionaries, with each dictionary containing a single
+     * wifi configuration. The wifi configuration requires the fields "ssid" and "security" with
+     * security being one of NONE, WEP, PSK, or EAP. If WEP, PSK, or EAP are selected, the field
+     * "password" must also be provided.  If EAP is selected, then the fiels "eap", "phase2",
+     * "identity", "ananymous_identity", "ca_cert", and "client_cert" are also required. Lastly,
+     * static IP settings are also supported.  If the field "ip" is set, then the fields "gateway",
+     * "prefix_length", "dns1", and "dns2" are required.
+     * </p>
+     * @throws IllegalArgumentException if the input string was not valid JSON or if any mandatory
+     * fields are missing.
+     */
+    public static List<WifiConfiguration> parseJson(String in) {
+        try {
+            JSONArray jsonConfigs = new JSONArray(in);
+            List<WifiConfiguration> wifiConfigs = new ArrayList<>(jsonConfigs.length());
+
+            for (int i = 0; i < jsonConfigs.length(); i++) {
+                JSONObject jsonConfig = jsonConfigs.getJSONObject(i);
+
+                wifiConfigs.add(getWifiConfiguration(jsonConfig));
+            }
+            return wifiConfigs;
+        } catch (JSONException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * Parse a {@link JSONObject} and return the wifi configuration.
+     *
+     * @throws IllegalArgumentException if any mandatory fields are missing.
+     */
+    private static WifiConfiguration getWifiConfiguration(JSONObject jsonConfig)
+            throws JSONException {
+        String ssid = jsonConfig.getString("ssid");
+        String password = null;
+        WifiConfiguration config;
+
+        int securityType = getSecurityType(jsonConfig.getString("security"));
+        switch (securityType) {
+            case NONE:
+                config = createOpenConfig(ssid);
+                break;
+            case WEP:
+                password = jsonConfig.getString("password");
+                config = createWepConfig(ssid, password);
+                break;
+            case PSK:
+                password = jsonConfig.getString("password");
+                config = createPskConfig(ssid, password);
+                break;
+            case EAP:
+                password = jsonConfig.getString("password");
+                int eapMethod = getEapMethod(jsonConfig.getString("eap"));
+                Integer phase2 = null;
+                if (jsonConfig.has("phase2")) {
+                    phase2 = getPhase2(jsonConfig.getString("phase2"));
+                }
+                String identity = null;
+                if (jsonConfig.has("identity")) {
+                    identity = jsonConfig.getString("identity");
+                }
+                String anonymousIdentity = null;
+                if (jsonConfig.has("anonymous_identity")) {
+                    anonymousIdentity = jsonConfig.getString("anonymous_identity");
+                }
+                String caCert = null;
+                if (jsonConfig.has("ca_cert")) {
+                    caCert = (jsonConfig.getString("ca_cert"));
+                }
+                String clientCert = null;
+                if (jsonConfig.has("client_cert")) {
+                    clientCert = jsonConfig.getString("client_cert");
+                }
+                config = createEapConfig(ssid, password, eapMethod, phase2, identity,
+                        anonymousIdentity, caCert, clientCert);
+                break;
+            default:
+                // Should never reach here as getSecurityType will already throw an exception
+                throw new IllegalArgumentException();
+        }
+
+        if (jsonConfig.has("ip")) {
+            StaticIpConfiguration staticIpConfig = new StaticIpConfiguration();
+
+            InetAddress ipAddress = getInetAddress(jsonConfig.getString("ip"));
+            int prefixLength = getPrefixLength(jsonConfig.getInt("prefix_length"));
+            staticIpConfig.ipAddress = new LinkAddress(ipAddress, prefixLength);
+            staticIpConfig.gateway = getInetAddress(jsonConfig.getString("gateway"));
+            staticIpConfig.dnsServers.add(getInetAddress(jsonConfig.getString("dns1")));
+            staticIpConfig.dnsServers.add(getInetAddress(jsonConfig.getString("dns2")));
+
+            config.setIpAssignment(IpAssignment.STATIC);
+            config.setStaticIpConfiguration(staticIpConfig);
+        } else {
+            config.setIpAssignment(IpAssignment.DHCP);
+        }
+
+        config.setProxySettings(ProxySettings.NONE);
+        return config;
+    }
+
+    private static String quotedString(String s) {
+        return String.format("\"%s\"", s);
+    }
+
+    /**
+     * Get the security type from a string.
+     *
+     * @throws IllegalArgumentException if the string is not a supported security type.
+     */
+    private static int getSecurityType(String security) {
+        if ("NONE".equalsIgnoreCase(security)) {
+            return NONE;
+        }
+        if ("WEP".equalsIgnoreCase(security)) {
+            return WEP;
+        }
+        if ("PSK".equalsIgnoreCase(security)) {
+            return PSK;
+        }
+        if ("EAP".equalsIgnoreCase(security)) {
+            return EAP;
+        }
+        throw new IllegalArgumentException("Security type must be one of NONE, WEP, PSK, or EAP");
+    }
+
+    /**
+     * Get the EAP method from a string.
+     *
+     * @throws IllegalArgumentException if the string is not a supported EAP method.
+     */
+    private static int getEapMethod(String eapMethod) {
+        if ("TLS".equalsIgnoreCase(eapMethod)) {
+            return WifiEnterpriseConfig.Eap.TLS;
+        }
+        if ("TTLS".equalsIgnoreCase(eapMethod)) {
+            return WifiEnterpriseConfig.Eap.TTLS;
+        }
+        if ("PEAP".equalsIgnoreCase(eapMethod)) {
+            return WifiEnterpriseConfig.Eap.PEAP;
+        }
+        throw new IllegalArgumentException("EAP method must be one of TLS, TTLS, or PEAP");
+    }
+
+    /**
+     * Get the phase 2 method from a string.
+     *
+     * @throws IllegalArgumentException if the string is not a supported phase 2 method.
+     */
+    private static int getPhase2(String phase2) {
+        if ("PAP".equalsIgnoreCase(phase2)) {
+            return WifiEnterpriseConfig.Phase2.PAP;
+        }
+        if ("MSCHAP".equalsIgnoreCase(phase2)) {
+            return WifiEnterpriseConfig.Phase2.MSCHAP;
+        }
+        if ("MSCHAPV2".equalsIgnoreCase(phase2)) {
+            return WifiEnterpriseConfig.Phase2.MSCHAPV2;
+        }
+        if ("GTC".equalsIgnoreCase(phase2)) {
+            return WifiEnterpriseConfig.Phase2.GTC;
+        }
+        throw new IllegalArgumentException("Phase2 must be one of PAP, MSCHAP, MSCHAPV2, or GTC");
+    }
+
+    /**
+     * Get an {@link InetAddress} from a string
+     *
+     * @throws IllegalArgumentException if the string is not a valid IP address.
+     */
+    private static InetAddress getInetAddress(String ipAddress) {
+        if (!InetAddress.isNumeric(ipAddress)) {
+            throw new IllegalArgumentException(
+                    String.format("IP address %s is not numeric", ipAddress));
+        }
+
+        try {
+            return InetAddress.getByName(ipAddress);
+        } catch (UnknownHostException e) {
+            throw new IllegalArgumentException(
+                    String.format("IP address %s could not be resolved", ipAddress));
+        }
+    }
+
+    /**
+     * Get the prefix length from an int.
+     *
+     * @throws IllegalArgumentException if the prefix length is less than 0 or greater than 32.
+     */
+    private static int getPrefixLength(int prefixLength) {
+        if (prefixLength < 0 || prefixLength > 32) {
+            throw new IllegalArgumentException("Prefix length cannot be less than 0 or more than 32");
+        }
+        return prefixLength;
+    }
+
+    /**
+     * Utility method to check if a given string is a hexadecimal string of given length
+     */
+    public static boolean isHex(String input, int length) {
+        if (input == null || length < 0) {
+            return false;
+        }
+        return input.matches(String.format("[0-9A-Fa-f]{%d}", length));
+    }
+}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index 01995c7..b280106 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -23,14 +23,15 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
 
 import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
 import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
 
-public class ConnectivityManagerMobileTest extends
-        ConnectivityManagerTestBase {
-    private static final String TAG = "ConnectivityManagerMobileTest";
+public class ConnectivityManagerMobileTest extends  ConnectivityManagerTestBase {
+
+    public ConnectivityManagerMobileTest() {
+        super(ConnectivityManagerMobileTest.class.getSimpleName());
+    }
 
     private String mTestAccessPoint;
     private boolean mWifiOnlyFlag;
@@ -46,7 +47,7 @@
         // Each test case will start with cellular connection
         if (Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
                 Settings.Global.AIRPLANE_MODE_ON) == 1) {
-            log("airplane is not disabled, disable it.");
+            logv("airplane is not disabled, disable it.");
             mCm.setAirplaneMode(false);
         }
 
@@ -77,16 +78,14 @@
         assertTrue("not connected to cellular network", extraNetInfo.isConnected());
     }
 
-    private void log(String message) {
-        Log.v(TAG, message);
-    }
+
 
     // Test case 1: Test enabling Wifi without associating with any AP, no broadcast on network
     //              event should be expected.
     @LargeTest
     public void test3GToWifiNotification() {
         if (mWifiOnlyFlag) {
-            Log.v(TAG, getName() + " is excluded for wifi-only test");
+            logv(getName() + " is excluded for wifi-only test");
             return;
         }
 
@@ -225,7 +224,7 @@
     @LargeTest
     public void testDataConnectionWith3GToAmTo3G() {
         if (mWifiOnlyFlag) {
-            Log.v(TAG, getName() + " is excluded for wifi-only test");
+            logv(getName() + " is excluded for wifi-only test");
             return;
         }
         // disable wifi
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
index eb75b0d..c2b80dc 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiAssociationTest.java
@@ -21,16 +21,15 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.AuthAlgorithm;
 import android.net.wifi.WifiConfiguration.GroupCipher;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.PairwiseCipher;
 import android.net.wifi.WifiConfiguration.Protocol;
 import android.net.wifi.WifiInfo;
 import android.os.Bundle;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
 
 import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
 import com.android.connectivitymanagertest.WifiAssociationTestRunner;
+import com.android.connectivitymanagertest.WifiConfigurationHelper;
 
 /**
  * Test Wi-Fi connection with different configuration
@@ -40,7 +39,6 @@
  * -w com.android.connectivitymanagertest/.WifiAssociationTestRunner"
  */
 public class WifiAssociationTest extends ConnectivityManagerTestBase {
-    private static final String TAG = "WifiAssociationTest";
     private String mSsid = null;
     private String mPassword = null;
     private String mSecurityType = null;
@@ -51,6 +49,10 @@
         OPEN, WEP64, WEP128, WPA_TKIP, WPA2_AES
     }
 
+    public WifiAssociationTest() {
+        super(WifiAssociationTest.class.getSimpleName());
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -77,90 +79,58 @@
     private void validateFrequencyBand() {
         if (mFrequencyBand != null) {
             int currentFreq = mWifiManager.getFrequencyBand();
-            Log.v(TAG, "read frequency band: " + currentFreq);
+            logv("read frequency band: " + currentFreq);
             assertEquals("specified frequency band does not match operational band of WifiManager",
                     currentFreq, mBand);
          }
     }
 
-    private void log(String message) {
-        Log.v(TAG, message);
-    }
-
     @LargeTest
     public void testWifiAssociation() {
         assertNotNull("no test ssid", mSsid);
-        WifiConfiguration config = new WifiConfiguration();
-        config.SSID = mSsid;
+        WifiConfiguration config = null;
         SECURITY_TYPE security = SECURITY_TYPE.valueOf(mSecurityType);
-        log("Security type is " + security.toString());
+        logv("Security type is " + security.toString());
         switch (security) {
             // set network configurations
             case OPEN:
-                config.allowedKeyManagement.set(KeyMgmt.NONE);
+                config = WifiConfigurationHelper.createOpenConfig(mSsid);
                 break;
             case WEP64:
                 assertNotNull("password is empty", mPassword);
-                config.allowedKeyManagement.set(KeyMgmt.NONE);
-                config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
-                config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+                // always use hex pair for WEP-40
+                assertTrue(WifiConfigurationHelper.isHex(mPassword, 10));
+                config = WifiConfigurationHelper.createWepConfig(mSsid, mPassword);
                 config.allowedGroupCiphers.set(GroupCipher.WEP40);
-                if (mPassword != null) {
-                    // always use hex pair for WEP-40
-                    if (isHex(mPassword, 10)) {
-                        config.wepKeys[0] = mPassword;
-                    } else {
-                        fail("password should be 10-character hex");
-                    }
-                }
                 break;
             case WEP128:
                 assertNotNull("password is empty", mPassword);
-                config.allowedKeyManagement.set(KeyMgmt.NONE);
-                config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
-                config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+                // always use hex pair for WEP-104
+                assertTrue(WifiConfigurationHelper.isHex(mPassword, 26));
+                config = WifiConfigurationHelper.createWepConfig(mSsid, mPassword);
                 config.allowedGroupCiphers.set(GroupCipher.WEP104);
-                if (mPassword != null) {
-                    // always use hex pair for WEP-104
-                    if (isHex(mPassword, 26)) {
-                        config.wepKeys[0] = mPassword;
-                    } else {
-                        fail("password should be 26-character hex");
-                    }
-                }
                 break;
             case WPA_TKIP:
                 assertNotNull("password is empty", mPassword);
-                config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+                config = WifiConfigurationHelper.createPskConfig(mSsid, mPassword);
                 config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
                 config.allowedProtocols.set(Protocol.WPA);
                 config.allowedPairwiseCiphers.set(PairwiseCipher.TKIP);
                 config.allowedGroupCiphers.set(GroupCipher.TKIP);
-                if (isHex(mPassword, 64)) {
-                    config.preSharedKey = mPassword;
-                } else {
-                    config.preSharedKey = '"' + mPassword + '"';
-                }
                 break;
             case WPA2_AES:
                 assertNotNull("password is empty", mPassword);
-                config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+                config = WifiConfigurationHelper.createPskConfig(mSsid, mPassword);
                 config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
                 config.allowedProtocols.set(Protocol.RSN);
                 config.allowedPairwiseCiphers.set(PairwiseCipher.CCMP);
                 config.allowedGroupCiphers.set(GroupCipher.CCMP);
-                config.allowedProtocols.set(Protocol.RSN);
-                if (isHex(mPassword, 64)) {
-                    config.preSharedKey = mPassword;
-                } else {
-                    config.preSharedKey = '"' + mPassword + '"';
-                }
                 break;
             default:
                 fail("Not a valid security type: " + mSecurityType);
                 break;
         }
-        Log.v(TAG, "network config: " + config.toString());
+        logv("network config: %s", config.toString());
         connectToWifi(config);
         // verify that connection actually works
         assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
index 740ffb8..b37daa3 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -16,54 +16,38 @@
 
 package com.android.connectivitymanagertest.functional;
 
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo.State;
 import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
+import android.os.SystemClock;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
 
 import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
+import com.android.connectivitymanagertest.WifiConfigurationHelper;
 
-import java.util.ArrayList;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
 import java.util.List;
 
 /**
  * Test Wi-Fi connection with different configuration
  * To run this tests:
- *     adb shell am instrument -e class
- *          com.android.connectivitymanagertest.functional.WifiConnectionTest
- *          -w com.android.connectivitymanagertest/.ConnectivityManagerTestRunner
+ *     adb shell am instrument \
+ *         -e class com.android.connectivitymanagertest.functional.WifiConnectionTest \
+ *         -w com.android.connectivitymanagertest/.ConnectivityManagerTestRunner
  */
-public class WifiConnectionTest
-    extends ConnectivityManagerTestBase {
-    private static final String TAG = "WifiConnectionTest";
-    private static final boolean DEBUG = false;
-    private List<WifiConfiguration> mNetworks = new ArrayList<WifiConfiguration>();
+public class WifiConnectionTest extends ConnectivityManagerTestBase {
+    private static final String WIFI_CONFIG_FILE = "/data/wifi_configs.json";
+    private static final long PAUSE_DURATION_MS = 60 * 1000;
+
+    public WifiConnectionTest() {
+        super(WifiConnectionTest.class.getSimpleName());
+    }
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mNetworks = loadNetworkConfigurations();
-        if (DEBUG) {
-            printNetworkConfigurations();
-        }
-
-        // enable wifi and verify wpa_supplicant is started
-        assertTrue("enable Wifi failed", enableWifi());
-        assertTrue("wifi not connected", waitForNetworkState(
-                ConnectivityManager.TYPE_WIFI, State.CONNECTED, LONG_TIMEOUT));
-        WifiInfo wi = mWifiManager.getConnectionInfo();
-        assertNotNull("no active wifi info", wi);
-        assertTrue("failed to ping wpa_supplicant ", mWifiManager.pingSupplicant());
-    }
-
-    private void printNetworkConfigurations() {
-        log("==== print network configurations parsed from XML file ====");
-        log("number of access points: " + mNetworks.size());
-        for (WifiConfiguration config : mNetworks) {
-            log(config.toString());
-        }
+        assertTrue("Failed to enable wifi", enableWifi());
     }
 
     @Override
@@ -72,25 +56,67 @@
         super.tearDown();
     }
 
-    private void log(String message) {
-        Log.v(TAG, message);
-    }
-
     @LargeTest
     public void testWifiConnections() {
-        for (int i = 0; i < mNetworks.size(); i++) {
-            String ssid = mNetworks.get(i).SSID;
-            log("-- START Wi-Fi connection test to : " + ssid + " --");
-            connectToWifi(mNetworks.get(i));
-            // verify that connection actually works
-            assertTrue("no network connectivity at end of test", checkNetworkConnectivity());
-            log("-- END Wi-Fi connection test to " + ssid + " -- ");
-            log("pausing for 1 minute");
-            try {
-                Thread.sleep(60 * 1000);
-            } catch (InterruptedException e) {
-                // ignore
+        List<WifiConfiguration> wifiConfigs = loadConfigurations();
+
+        printWifiConfigurations(wifiConfigs);
+
+        assertFalse("No configurations to test against", wifiConfigs.isEmpty());
+
+        boolean shouldPause = false;
+        for (WifiConfiguration config : wifiConfigs) {
+            if (shouldPause) {
+                logv("Pausing for %d seconds", PAUSE_DURATION_MS / 1000);
+                SystemClock.sleep(PAUSE_DURATION_MS);
             }
+            logv("Start wifi connection test to: %s", config.SSID);
+            connectToWifi(config);
+
+            // verify that connection actually works
+            assertTrue("No connectivity at end of test", checkNetworkConnectivity());
+
+            // Disconnect and remove the network
+            assertTrue("Unable to remove network", disconnectAP());
+            logv("End wifi connection test to: %s", config.SSID);
+
+            shouldPause = true;
+        }
+    }
+
+    /**
+     * Load the configuration file from the root of the data partition
+     */
+    private List<WifiConfiguration> loadConfigurations() {
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new FileReader(new File(WIFI_CONFIG_FILE)));
+            StringBuffer jsonBuffer = new StringBuffer();
+            String line;
+            while ((line = reader.readLine()) != null) {
+                jsonBuffer.append(line);
+            }
+            return WifiConfigurationHelper.parseJson(jsonBuffer.toString());
+        } catch (IllegalArgumentException | IOException e) {
+            throw new AssertionError("Error parsing file", e);
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException e) {
+                    // Ignore
+                }
+            }
+        }
+    }
+
+    /**
+     * Print the wifi configurations to test against.
+     */
+    private void printWifiConfigurations(List<WifiConfiguration> wifiConfigs) {
+        logv("Wifi configurations to be tested");
+        for (WifiConfiguration config : wifiConfigs) {
+            logv(config.toString());
         }
     }
 }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index aead65b..41f01e6 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -17,16 +17,15 @@
 package com.android.connectivitymanagertest.stress;
 
 
-import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
-import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
-
 import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiManager;
 import android.os.Environment;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
+
+import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
+import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
 
 import java.io.BufferedWriter;
 import java.io.File;
@@ -35,9 +34,7 @@
 /**
  * Stress test setting up device as wifi hotspot
  */
-public class WifiApStress
-    extends ConnectivityManagerTestBase {
-    private final static String TAG = "WifiApStress";
+public class WifiApStress extends ConnectivityManagerTestBase {
     private static String NETWORK_ID = "AndroidAPTest";
     private static String PASSWD = "androidwifi";
     private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
@@ -46,6 +43,10 @@
     private int mLastIteration = 0;
     private boolean mWifiOnlyFlag;
 
+    public WifiApStress() {
+        super(WifiApStress.class.getSimpleName());
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -71,7 +72,7 @@
     @LargeTest
     public void testWifiHotSpot() {
         if (mWifiOnlyFlag) {
-            Log.v(TAG, this.getName() + " is excluded for wi-fi only test");
+            logv(getName() + " is excluded for wi-fi only test");
             return;
         }
         WifiConfiguration config = new WifiConfiguration();
@@ -95,7 +96,7 @@
         }
         int i;
         for (i = 0; i < mTotalIterations; i++) {
-            Log.v(TAG, "iteration: " + i);
+            logv("iteration: " + i);
             mLastIteration = i;
             // enable Wifi tethering
             assertTrue("failed to enable wifi hotspot",
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 6ef4f06..fbd4669 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -19,13 +19,10 @@
 import android.app.Activity;
 import android.content.Context;
 import android.net.ConnectivityManager;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.State;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.os.Environment;
@@ -37,6 +34,7 @@
 
 import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
 import com.android.connectivitymanagertest.ConnectivityManagerTestBase;
+import com.android.connectivitymanagertest.WifiConfigurationHelper;
 
 import java.io.BufferedWriter;
 import java.io.File;
@@ -52,8 +50,6 @@
  *                  -w com.android.connectivitymanagertest/.ConnectivityManagerStressTestRunner
  */
 public class WifiStressTest extends ConnectivityManagerTestBase {
-    private final static String TAG = "WifiStressTest";
-
     private final static long SCREEN_OFF_TIMER = 500; //500ms
     /**
      * Wi-Fi idle time for default sleep policy
@@ -78,6 +74,10 @@
     private BufferedWriter mOutputWriter = null;
     private boolean mWifiOnlyFlag;
 
+    public WifiStressTest() {
+        super(WifiStressTest.class.getSimpleName());
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -89,14 +89,14 @@
         mScanIterations = mRunner.getScanIterations();
         mWifiSleepTime = mRunner.getSleepTime();
         mWifiOnlyFlag = mRunner.isWifiOnly();
-        log(String.format("mReconnectIterations(%d), mSsid(%s), mPassword(%s),"
+        logv(String.format("mReconnectIterations(%d), mSsid(%s), mPassword(%s),"
             + "mScanIterations(%d), mWifiSleepTime(%d)", mReconnectIterations, mSsid,
             mPassword, mScanIterations, mWifiSleepTime));
         mOutputWriter = new BufferedWriter(new FileWriter(new File(
                 Environment.getExternalStorageDirectory(), OUTPUT_FILE), true));
         turnScreenOn();
         if (!mWifiManager.isWifiEnabled()) {
-            log("Enable wi-fi before stress tests.");
+            logv("Enable wi-fi before stress tests.");
             if (!enableWifi()) {
                 tearDown();
                 fail("enable wifi failed.");
@@ -107,7 +107,7 @@
 
     @Override
     protected void tearDown() throws Exception {
-        log("tearDown()");
+        logv("tearDown()");
         if (mOutputWriter != null) {
             mOutputWriter.close();
         }
@@ -115,23 +115,19 @@
     }
 
     private void writeOutput(String s) {
-        log("write message: " + s);
+        logv("write message: " + s);
         if (mOutputWriter == null) {
-            log("no writer attached to file " + OUTPUT_FILE);
+            logv("no writer attached to file " + OUTPUT_FILE);
             return;
         }
         try {
             mOutputWriter.write(s + "\n");
             mOutputWriter.flush();
         } catch (IOException e) {
-            log("failed to write output.");
+            logv("failed to write output.");
         }
     }
 
-    public void log(String message) {
-        Log.v(TAG, message);
-    }
-
     private void sleep(long sometime, String errorMsg) {
         try {
             Thread.sleep(sometime);
@@ -149,7 +145,7 @@
         long scanTimeSum = 0, i, averageScanTime = -1;
         int ssidAppearInScanResultsCount = 0; // count times of given ssid appear in scan results.
         for (i = 1; i <= mScanIterations; i++) {
-            log("testWifiScanning: iteration: " + i);
+            logv("testWifiScanning: iteration: " + i);
             averageScanTime = scanTimeSum / i;
             writeOutput(String.format("iteration %d out of %d", i, mScanIterations));
             writeOutput(String.format("average scanning time is %d", averageScanTime));
@@ -173,9 +169,9 @@
             if (scanResultLocal == null || scanResultLocal.isEmpty()) {
                 fail("Scan results are empty ");
             }
-            log("size of scan result list: " + scanResultLocal.size());
+            logv("size of scan result list: " + scanResultLocal.size());
             for (ScanResult sr : scanResultLocal) {
-                log(String.format("scan result: " + sr.toString()));
+                logv(String.format("scan result: " + sr.toString()));
                 if (mSsid.equals(sr.SSID)) {
                     ssidAppearInScanResultsCount += 1;
                     break;
@@ -208,21 +204,12 @@
         Settings.Global.putLong(mRunner.getContext().getContentResolver(),
                 Settings.Global.WIFI_IDLE_MS, WIFI_IDLE_MS);
 
-        // Connect to a Wi-Fi network
-        WifiConfiguration config = new WifiConfiguration();
-        config.SSID = mSsid;
-        if (mPassword != null) {
-            config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
-            if (isHex(mPassword, 64)) {
-                config.preSharedKey = mPassword;
-            } else {
-                config.preSharedKey = '"' + mPassword + '"';
-            }
+        WifiConfiguration config;
+        if (mPassword == null) {
+            config = WifiConfigurationHelper.createOpenConfig(mSsid);
         } else {
-            config.allowedKeyManagement.set(KeyMgmt.NONE);
+            config = WifiConfigurationHelper.createPskConfig(mSsid, mPassword);
         }
-        config.setIpAssignment(IpAssignment.DHCP);
-        config.setProxySettings(ProxySettings.NONE);
 
         assertTrue("Failed to connect to Wi-Fi network: " + mSsid,
                 connectToWifiWithConfiguration(config));
@@ -240,7 +227,7 @@
             // 5. Wake up the device, verify Wi-Fi is enabled and connected.
             writeOutput(String.format("iteration %d out of %d",
                     i, mReconnectIterations));
-            log("iteration: " + i);
+            logv("iteration: " + i);
             turnScreenOff();
             // Use clock time since boot for intervals.
             long start = SystemClock.uptimeMillis();
@@ -271,7 +258,7 @@
             if (mWifiOnlyFlag) {
                 NetworkInfo ni = mCm.getActiveNetworkInfo();
                 if (ni != null) {
-                    Log.e(TAG, "has active network while in wifi sleep: " + ni.toString());
+                    Log.e(mLogTag, "has active network while in wifi sleep: " + ni.toString());
                     fail("active network detected");
                 }
             } else {
@@ -292,7 +279,7 @@
             long connectionTime = SystemClock.uptimeMillis() - startTime;
             sum += connectionTime;
             avgReconnectTime = sum / i;
-            log("average reconnection time is: " + avgReconnectTime);
+            logv("average reconnection time is: " + avgReconnectTime);
 
             assertTrue("Reconnect to Wi-Fi network, but no data connection.", pingTest(null));
         }
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index d8d8c76..e5161f4 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -29,7 +29,7 @@
 scaling ratio</strong> between the five primary densities (medium, high, x-high, xx-high, and
 xxx-high respectively). For example, consider that the size for a launcher icon is specified to be
 48x48 dp. This means the baseline (MDPI) asset is 48x48 px, and the
-high density (HDPI) asset should be 1.5x the baseline at 72x72 px, and the x-high
+high-density(HDPI) asset should be 1.5x the baseline at 72x72 px, and the x-high
 density (XHDPI) asset should be 2x the baseline at 96x96 px, and so on.</p>
 
 <p class="note"><strong>Note:</strong> Android also supports low-density (LDPI) screens,
@@ -489,11 +489,12 @@
     xhdpi/...
         _pre_production/...
             <em>working_file</em>.psd
-        <em>finished_asset</em>.png</pre>
+        <em>finished_asset</em>.png
     xxhdpi/...
         _pre_production/...
             <em>working_file</em>.psd
-        <em>finished_asset</em>.png</pre>
+        <em>finished_asset</em>.png
+</pre>
 
 <p>Because the structure in your working space is similar to that of the application, you
 can quickly determine which assets should be copied to each
@@ -513,6 +514,8 @@
         <em>finished_asset</em>.png
     drawable-xhdpi/...
         <em>finished_asset</em>.png
+    drawable-xxhdpi/...
+        <em>finished_asset</em>.png
 </pre>
 
 <p>For more information about how to save resources in the application project,
@@ -520,6 +523,21 @@
 </p>
 
 
+<h3 id="xxxhdpi-launcher">Provide an xxx-high-density launcher icon</h3>
+
+<p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest density 
+launcher icon image is already extra-extra-high density, the scaling process will make it appear
+less crisp. So you should provide a higher density launcher icon in the <code>drawable-xxxhdpi
+</code> directory, which the system uses instead of scaling up a smaller version of the icon.</p>
+
+<p class="note"><strong>Note:</strong> the <code>drawable-xxxhdpi</code> qualifier is necessary only
+to provide a launcher icon that can appear larger than usual on an xxhdpi device. You do not need to
+provide xxxhdpi assets for all your app's images.</p>
+
+<p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> for
+more information.</p>
+
+
 <h3>Remove unnecessary metadata from final assets</h3>
 
 <p>Although the Android SDK tools will automatically compress PNGs when packaging
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index dbe6c1a..7ebda53 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -111,15 +111,15 @@
   <dd>Actual physical size, measured as the screen's diagonal.
 
   <p>For simplicity, Android groups all actual screen sizes into four generalized sizes: small,
-normal, large, and extra large.</p></dd>
+normal, large, and extra-large.</p></dd>
 
 <dt><em>Screen density</em></dt>
   <dd>The quantity of pixels within a physical area of the screen; usually referred to as dpi (dots
 per inch). For example, a "low" density screen has fewer pixels within a given physical area,
 compared to a "normal" or "high" density screen.</p>
 
-  <p>For simplicity, Android groups all actual screen densities into four generalized densities:
-low, medium, high, and extra high.</p></dd>
+  <p>For simplicity, Android groups all actual screen densities into six generalized densities:
+low, medium, high, extra-high, extra-extra-high, and extra-extra-extra-high.</p></dd>
 
 <dt><em>Orientation</em></dt>
   <dd>The orientation of the screen from the user's point of view. This is either landscape or
@@ -168,9 +168,15 @@
 href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> for more
 information.</p>
 </li>
-<li>A set of four generalized <strong>densities</strong>: <em>ldpi</em> (low), <em>mdpi</em>
-(medium),
-<em>hdpi</em> (high), and <em>xhdpi</em> (extra high)
+<li>A set of six generalized <strong>densities</strong>:
+  <ul>
+    <li><em>ldpi</em> (low) ~120dpi</li>
+    <li><em>mdpi</em> (medium) ~160dpi</li>
+    <li><em>hdpi</em> (high) ~240dpi</li>
+    <li><em>xhdpi</em> (extra-high) ~320dpi</li>
+    <li><em>xxhdpi</em> (extra-extra-high) ~480dpi</li>
+    <li><em>xxxhdpi</em> (extra-extra-extra-high) ~640dpi</li>
+  </ul>
 </li>
 </ul>
 
@@ -243,14 +249,14 @@
 densities.</p>
 
 <p>Maintaining density independence is important because, without it, a UI element (such as a
-button) appears physically larger on a low density screen and smaller on a high density screen. Such
+button) appears physically larger on a low-density screen and smaller on a high-density screen. Such
 density-related size changes can cause problems in your application layout and usability. Figures 2
 and 3 show the difference between an application when it does not provide density independence and
 when it does, respectively.</p>
 
 <img src="{@docRoot}images/screens_support/density-test-bad.png" alt=""  />
 <p class="img-caption"><strong>Figure 2.</strong> Example application without support for
-different densities, as shown on low, medium, and high density screens.</p>
+different densities, as shown on low, medium, and high-density screens.</p>
 
 <img src="{@docRoot}images/screens_support/density-test-good.png" alt="" />
 <p class="img-caption"><strong>Figure 3.</strong> Example application with good support for
@@ -266,8 +272,8 @@
 </ul>
 
 <p>In figure 2, the text view and bitmap drawable have dimensions specified in pixels ({@code px}
-units), so the views are physically larger on a low density screen and smaller on a high density
-screen. This is because although the actual screen sizes may be the same, the high density screen
+units), so the views are physically larger on a low-density screen and smaller on a high-density
+screen. This is because although the actual screen sizes may be the same, the high-density screen
 has more pixels per inch (the same amount of pixels fit in a smaller area). In figure 3, the layout
 dimensions are specified in density-independent pixels ({@code dp} units). Because the baseline for
 density-independent pixels is a medium-density screen, the device with a medium-density screen looks
@@ -311,7 +317,7 @@
 <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
 &lt;supports-screens&gt;}</a> element in your manifest file.</p>
   </li>
-  
+
   <li><strong>Provide different layouts for different screen sizes</strong>
     <p>By default, Android resizes your application layout to fit the current device screen. In most
 cases, this works fine. In other cases, your UI might not look as good and might need adjustments
@@ -320,7 +326,7 @@
 you might need to adjust sizes so that everything can fit on the screen.</p>
     <p>The configuration qualifiers you can use to provide size-specific resources are
 <code>small</code>, <code>normal</code>, <code>large</code>, and <code>xlarge</code>. For
-example, layouts for an extra large screen should go in {@code layout-xlarge/}.</p>
+example, layouts for an extra-large screen should go in {@code layout-xlarge/}.</p>
     <p>Beginning with Android 3.2 (API level 13), the above size groups are deprecated and you
 should instead use the {@code sw&lt;N&gt;dp} configuration qualifier to define the smallest
 available width required by your layout resources. For example, if your multi-pane tablet layout
@@ -328,7 +334,7 @@
 new techniques for declaring layout resources is discussed further in the section about <a
 href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a>.</p>
   </li>
-  
+
   <li><strong>Provide different bitmap drawables for different screen densities</strong>
     <p>By default, Android scales your bitmap drawables ({@code .png}, {@code .jpg}, and {@code
 .gif} files) and Nine-Patch drawables ({@code .9.png} files) so that they render at the appropriate
@@ -337,10 +343,22 @@
 screen, and scales them down when on a low-density screen. This scaling can cause artifacts in the
 bitmaps. To ensure your bitmaps look their best, you should include alternative versions at
 different resolutions for different screen densities.</p>
-    <p>The configuration qualifiers you can use for density-specific resources are
-<code>ldpi</code> (low), <code>mdpi</code> (medium), <code>hdpi</code> (high), and
-<code>xhdpi</code> (extra high). For example, bitmaps for high-density screens should go in
-{@code drawable-hdpi/}.</p>
+    <p>The <a href="#qualifiers">configuration qualifiers</a> (described in detail below) that you
+can use for density-specific resources are <code>ldpi</code> (low), <code>mdpi</code> (medium),
+<code>hdpi</code> (high), <code>xhdpi</code> extra-high), <code>xxhdpi</code>
+(extra-extra-high), and <code>xxxhdpi</code> (extra-extra-extra-high). For example, bitmaps
+for high-density screens should go in {@code drawable-hdpi/}.</p>
+    <p class="note" id="xxxhdpi-note"><strong>Note:</strong>  the <code>drawable-xxxhdpi</code>
+qualifier is necessary only to provide a launcher icon that can appear larger than usual on an
+xxhdpi device. You do not need to provide xxxhdpi assets for all your app's images.</p>
+    <p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest
+density launcher icon image is already extra-extra-high-density, the scaling process will make it
+appear less crisp. So you should provide a higher density launcher icon in the
+<code>drawable-xxxhdpi</code> directory, which the system uses instead of scaling up a smaller
+version of the icon.</p>
+    <p>See <a href="{@docRoot}design/style/iconography.html#xxxhdpi-launcher">Provide an
+xxx-high-density launcher icon</a> for more information. You should not use the
+<code>xxxhdpi</code> qualifier for UI elements other than the launcher icon.</p>
   </li>
 </ul>
 
@@ -371,14 +389,14 @@
   <p>The "default" resources are those that are not tagged with a configuration qualifier. For
 example, the resources in {@code drawable/} are the default drawable resources. The system
 assumes that default resources are designed for the baseline screen size and density, which is a
-normal screen size and a medium density. As such, the system scales default density
+normal screen size and a medium-density. As such, the system scales default density
 resources up for high-density screens and down for low-density screens, as appropriate.</p>
   <p>However, when the system is looking for a density-specific resource and does not find it in
 the density-specific directory, it won't always use the default resources. The system may
 instead use one of the other density-specific resources in order to provide better results
 when scaling. For example, when looking for a low-density resource and it is not available, the
 system prefers to scale-down the high-density version of the resource, because the
-system can easily scale a high-density resource down to low-density by a factor of 0.5, with 
+system can easily scale a high-density resource down to low-density by a factor of 0.5, with
 fewer artifacts, compared to scaling a medium-density resource by a factor of 0.75.</p>
 </li>
 </ol>
@@ -416,9 +434,9 @@
 files must be named exactly the same as the default resource files.</li>
 </ol>
 
-<p>For example, {@code xlarge} is a configuration qualifier for extra large screens. When you append
+<p>For example, {@code xlarge} is a configuration qualifier for extra-large screens. When you append
 this string to a resource directory name (such as {@code layout-xlarge}), it indicates to the
-system that these resources are to be used on devices that have an extra large screen.</p>
+system that these resources are to be used on devices that have an extra-large screen.</p>
 
 <p class="table-caption"><strong>Table 1.</strong> Configuration qualifiers that allow you to
 provide special resources for different screen configurations.</p>
@@ -445,11 +463,11 @@
 </tr>
 <tr>
 <td><code>xlarge</code></td>
-<td>Resources for <em>extra large</em> size screens.</td>
+<td>Resources for <em>extra-large</em> size screens.</td>
 </tr>
 
 <tr>
-<td rowspan="6">Density</td>
+<td rowspan="8">Density</td>
 <td><code>ldpi</code></td>
 <td>Resources for low-density (<em>ldpi</em>) screens (~120dpi).</td>
 </tr>
@@ -464,7 +482,14 @@
 </tr>
 <tr>
 <td><code>xhdpi</code></td>
-<td>Resources for extra high-density (<em>xhdpi</em>) screens (~320dpi).</td>
+<td>Resources for extra-high-density (<em>xhdpi</em>) screens (~320dpi).</td>
+</tr>
+<td><code>xxhdpi</code></td>
+<td>Resources for extra-extra-high-density (<em>xxhdpi</em>) screens (~480dpi).</td>
+</tr>
+<td><code>xxxhdpi</code></td>
+<td>Resources for extra-extra-extra-high-density (<em>xxxhdpi</em>) uses (~640dpi). Use this for the
+  launcher icon only, see <a href="#xxxhdpi-note">note</a> above.</td>
 </tr>
 <tr>
 <td><code>nodpi</code></td>
@@ -515,18 +540,18 @@
 
 <p>For example, the following is a list of resource directories in an application that
 provides different layout designs for different screen sizes and different bitmap drawables
-for medium, high, and extra high density screens.</p>
+for medium, high, and extra-high-density screens.</p>
 
 <pre class="classic">
-res/layout/my_layout.xml             // layout for normal screen size ("default")
-res/layout-small/my_layout.xml       // layout for small screen size
-res/layout-large/my_layout.xml       // layout for large screen size
-res/layout-xlarge/my_layout.xml      // layout for extra large screen size
-res/layout-xlarge-land/my_layout.xml // layout for extra large in landscape orientation
+res/layout/my_layout.xml              // layout for normal screen size ("default")
+res/layout-large/my_layout.xml        // layout for large screen size
+res/layout-xlarge/my_layout.xml       // layout for extra-large screen size
+res/layout-xlarge-land/my_layout.xml  // layout for extra-large in landscape orientation
 
-res/drawable-mdpi/my_icon.png        // bitmap for medium density
-res/drawable-hdpi/my_icon.png        // bitmap for high density
-res/drawable-xhdpi/my_icon.png       // bitmap for extra high density
+res/drawable-mdpi/my_icon.png         // bitmap for medium-density
+res/drawable-hdpi/my_icon.png         // bitmap for high-density
+res/drawable-xhdpi/my_icon.png        // bitmap for extra-high-density
+res/drawable-xxhdpi/my_icon.png       // bitmap for extra-extra-high-density
 </pre>
 
 <p>For more information about how to use alternative resources and a complete list of
@@ -575,10 +600,10 @@
 screen. For example, a row of buttons might not fit within the width of the screen on a small screen
 device. In this case you should provide an alternative layout for small screens that adjusts the
 size or position of the buttons.</li>
-  <li>When testing on an extra large screen, you might realize that your layout doesn't make
+  <li>When testing on an extra-large screen, you might realize that your layout doesn't make
 efficient use of the big screen and is obviously stretched to fill it.
-In this case, you should provide an alternative layout for extra large screens that provides a
-redesigned UI that is optimized for bigger screens such as tablets. 
+In this case, you should provide an alternative layout for extra-large screens that provides a
+redesigned UI that is optimized for bigger screens such as tablets.
     <p>Although your application should work fine without an alternative layout on big screens, it's
 quite important to users that your application looks as though it's designed specifically for their
 devices. If the UI is obviously stretched, users are more likely to be unsatisfied with the
@@ -598,7 +623,7 @@
 <p>If your UI uses bitmaps that need to fit the size of a view even after the system scales
 the layout (such as the background image for a button), you should use <a
 href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">Nine-Patch</a> bitmap files. A
-Nine-Patch file is basically a PNG file in which you specific two-dimensional regions that are
+Nine-Patch file is basically a PNG file in which you specify two-dimensional regions that are
 stretchable. When the system needs to scale the view in which the bitmap is used, the system
 stretches the Nine-Patch bitmap, but stretches only the specified regions. As such, you don't
 need to provide different drawables for different screen sizes, because the Nine-Patch bitmap can
@@ -621,21 +646,24 @@
 each one, for different densities.</p>
 
 <p class="note"><strong>Note:</strong> You only need to provide density-specific drawables for
-bitmap files ({@code .png}, {@code .jpg}, or {@code .gif}) and Nine-Path files ({@code
+bitmap files ({@code .png}, {@code .jpg}, or {@code .gif}) and Nine-Patch files ({@code
 .9.png}). If you use XML files to define shapes, colors, or other <a
 href="{@docRoot}guide/topics/resources/drawable-resource.html">drawable resources</a>, you should
 put one copy in the default drawable directory ({@code drawable/}).</p>
 
 <p>To create alternative bitmap drawables for different densities, you should follow the
-<b>3:4:6:8 scaling ratio</b> between the four generalized densities. For example, if you have
-a bitmap drawable that's 48x48 pixels for medium-density screen (the size for a launcher icon),
-all the different sizes should be:</p>
+<b>3:4:6:8:12:16 scaling ratio</b> between the six generalized densities. For example, if you have
+a bitmap drawable that's 48x48 pixels for medium-density screens, all the different sizes should be:
+</p>
 
 <ul>
-  <li>36x36 for low-density</li>
-  <li>48x48 for medium-density</li>
-  <li>72x72 for high-density</li>
-  <li>96x96 for extra high-density</li>
+  <li>36x36 (0.75x) for low-density</li>
+  <li>48x48 (1.0x baseline) for medium-density</li>
+  <li>72x72 (1.5x) for high-density</li>
+  <li>96x96 (2.0x) for extra-high-density</li>
+  <li>180x180 (3.0x) for extra-extra-high-density</li>
+  <li>192x192 (4.0x) for extra-extra-extra-high-density (launcher icon only; see
+    <a href="#xxxhdpi-note">note</a> above)</li>
 </ul>
 
 <p>For more information about designing icons, see the <a
@@ -715,7 +743,7 @@
 screen area. Specifically, the device's smallestWidth is the shortest of the screen's available
 height and width (you may also think of it as the "smallest possible width" for the screen). You can
 use this qualifier to ensure that, regardless of the screen's current orientation, your
-application's has at least {@code &lt;N&gt;} dps of width available for it UI.</p>
+application's has at least {@code &lt;N&gt;} dps of width available for its UI.</p>
         <p>For example, if your layout requires that its smallest dimension of screen area be at
 least 600 dp at all times, then you can use this qualifer to create the layout resources, {@code
 res/layout-sw600dp/}. The system will use these resources only when the smallest dimension of
@@ -1011,8 +1039,8 @@
 <p>If you need to control exactly how your application will look on various
 screen configurations, adjust your layouts and bitmap drawables in configuration-specific
 resource directories. For example, consider an icon that you want to display on
-medium and high density screens. Simply create your icon at two different sizes
-(for instance 100x100 for medium density and 150x150 for high density) and put
+medium and high-density screens. Simply create your icon at two different sizes
+(for instance 100x100 for medium-density and 150x150 for high-density) and put
 the two variations in the appropriate directories, using the proper
 qualifiers:</p>
 
@@ -1115,9 +1143,7 @@
 <div class="figure" style="width:300px">
 <img src="{@docRoot}images/screens_support/scale-test.png" alt="" />
 <p class="img-caption"><strong>Figure 5.</strong> Comparison of pre-scaled and auto-scaled
-bitmaps, from <a
-href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/DensityActivity.html">
-ApiDemos</a>.
+bitmaps.
 </p>
 </div>
 
@@ -1153,10 +1179,7 @@
 (120), medium (160) and high (240) density bitmaps on a high-density screen. The differences are
 subtle, because all of the bitmaps are being scaled to match the current screen density, however the
 scaled bitmaps have slightly different appearances depending on whether they are pre-scaled or
-auto-scaled at draw time. You can find the source code for this sample application, which
-demonstrates using pre-scaled and auto-scaled bitmaps, in <a
-href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/DensityActivity.html">
-ApiDemos</a>.</p>
+auto-scaled at draw time.</p>
 
 <p class="note"><strong>Note:</strong> In Android 3.0 and above, there should be no perceivable
 difference between pre-scaled and auto-scaled bitmaps, due to improvements in the graphics
@@ -1172,9 +1195,9 @@
 pixels. Imagine an application in which a scroll or fling gesture is recognized after the user's
 finger has moved by at least 16 pixels. On a baseline screen, a user's must move by {@code 16 pixels
 / 160 dpi}, which equals 1/10th of an inch (or 2.5 mm) before the gesture is recognized. On a device
-with a high density display (240dpi), the user's must move by {@code 16 pixels / 240 dpi}, which
+with a high-density display (240dpi), the user's must move by {@code 16 pixels / 240 dpi}, which
 equals 1/15th of an inch (or 1.7 mm). The distance is much shorter and the application thus appears
-more sensitive to the user.</p> 
+more sensitive to the user.</p>
 
 <p>To fix this issue, the gesture threshold must be expressed in code in <code>dp</code> and then
 converted to actual pixels. For example:</p>
@@ -1194,7 +1217,7 @@
 <p>The {@link android.util.DisplayMetrics#density DisplayMetrics.density} field specifies the scale
 factor you must use to convert {@code dp} units to pixels, according to the current screen density.
 On a medium-density screen, {@link android.util.DisplayMetrics#density DisplayMetrics.density}
-equals 1.0; on a high-density screen it equals 1.5; on an extra high-density screen, it equals 2.0;
+equals 1.0; on a high-density screen it equals 1.5; on an extra-high-density screen, it equals 2.0;
 and on a low-density screen, it equals 0.75. This figure is the factor by which you should multiply
 the {@code dp} units on order to get the actual pixel count for the current screen. (Then add {@code
 0.5f} to round the figure up to the nearest whole number, when converting to an integer.) For more
@@ -1277,7 +1300,7 @@
         <nobr>High density (240), <em>hdpi</em><nobr>
       </th>
       <th>
-        <nobr>Extra high density (320), <em>xhdpi</em><nobr>
+        <nobr>Extra-high-density (320), <em>xhdpi</em><nobr>
       </th>
     </tr>
     <tr>
@@ -1315,7 +1338,7 @@
     </tr>
     <tr>
       <th>
-        <em>Extra Large</em> screen
+        <em>Extra-Large</em> screen
       </th>
       <td>1024x600</td>
       <td><strong>WXGA (1280x800)</strong><sup>&dagger;</sup><br>
@@ -1369,4 +1392,4 @@
 
 <p>For more information about creating AVDs from the command line, see <a
 href="{@docRoot}tools/devices/managing-avds-cmdline.html">Managing AVDs from the
-Command Line</a></p>
+Command Line</a>.</p>
\ No newline at end of file
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index bf16630..6d9527f 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -389,7 +389,7 @@
             <ul>
               <li>240x320 ldpi (QVGA handset)</li>
               <li>320x480 mdpi (handset)</li>
-              <li>480x800 hdpi (high density handset)</li>
+              <li>480x800 hdpi (high-density handset)</li>
             </ul>
           </li>
           <li>480, for screens such as 480x800 mdpi (tablet/handset).</li>
@@ -483,20 +483,20 @@
         <ul class="nolist">
         <li>{@code small}: Screens that are of similar size to a
         low-density QVGA screen. The minimum layout size for a small screen
-        is approximately 320x426 dp units.  Examples are QVGA low density and VGA high
+        is approximately 320x426 dp units.  Examples are QVGA low-density and VGA high
         density.</li>
         <li>{@code normal}: Screens that are of similar size to a
         medium-density HVGA screen. The minimum
         layout size for a normal screen is approximately 320x470 dp units.  Examples
-        of such screens a WQVGA low density, HVGA medium density, WVGA
-        high density.</li>
+        of such screens a WQVGA low-density, HVGA medium-density, WVGA
+        high-density.</li>
         <li>{@code large}: Screens that are of similar size to a
         medium-density VGA screen.
         The minimum layout size for a large screen is approximately 480x640 dp units.
-        Examples are VGA and WVGA medium density screens.</li>
+        Examples are VGA and WVGA medium-density screens.</li>
         <li>{@code xlarge}: Screens that are considerably larger than the traditional
         medium-density HVGA screen. The minimum layout size for an xlarge screen
-        is approximately 720x960 dp units.  In most cases, devices with extra large
+        is approximately 720x960 dp units.  In most cases, devices with extra-large
         screens would be too large to carry in a pocket and would most likely
         be tablet-style devices. <em>Added in API level 9.</em></li>
         </ul>
@@ -613,6 +613,8 @@
         <code>mdpi</code><br/>
         <code>hdpi</code><br/>
         <code>xhdpi</code><br/>
+        <code>xxhdpi</code><br/>
+        <code>xxxhdpi</code><br/>
         <code>nodpi</code><br/>
         <code>tvdpi</code>
       </td>
@@ -622,8 +624,14 @@
           <li>{@code mdpi}: Medium-density (on traditional HVGA) screens; approximately
 160dpi.</li>
           <li>{@code hdpi}: High-density screens; approximately 240dpi.</li>
-          <li>{@code xhdpi}: Extra high-density screens; approximately 320dpi. <em>Added in API
+          <li>{@code xhdpi}: Extra-high-density screens; approximately 320dpi. <em>Added in API
 Level 8</em></li>
+          <li>{@code xxhdpi}: Extra-extra-high-density screens; approximately 480dpi. <em>Added in API
+Level 16</em></li>
+          <li>{@code xxxhdpi}: Extra-extra-extra-high-density uses (launcher icon only, see the 
+            <a href="{@docRoot}guide/practices/screens_support.html#xxxhdpi-note">note</a> 
+            in <em>Supporting Multiple Screens</em>); approximately 640dpi. <em>Added in API
+Level 18</em></li>
           <li>{@code nodpi}: This can be used for bitmap resources that you do not want to be scaled
 to match the device density.</li>
           <li>{@code tvdpi}: Screens somewhere between mdpi and hdpi; approximately 213dpi. This is
@@ -631,8 +639,9 @@
 apps shouldn't need it&mdash;providing mdpi and hdpi resources is sufficient for most apps and
 the system will scale them as appropriate. This qualifier was introduced with API level 13.</li>
         </ul>
-        <p>There is a 3:4:6:8 scaling ratio between the four primary densities (ignoring the
-tvdpi density). So, a 9x9 bitmap in ldpi is 12x12 in mdpi, 18x18 in hdpi and 24x24 in xhdpi.</p>
+        <p>There is a 3:4:6:8:12:16 scaling ratio between the six primary densities (ignoring the
+tvdpi density). So, a 9x9 bitmap in ldpi is 12x12 in mdpi, 18x18 in hdpi, 24x24 in xhdpi and so on.
+</p>
         <p>If you decide that your image resources don't look good enough on a television or
 other certain devices and want to try tvdpi resources, the scaling factor is 1.33*mdpi. For
 example, a 100px x 100px image for mdpi screens should be 133px x 133px for tvdpi.</p>
diff --git a/docs/html/guide/topics/ui/accessibility/services.jd b/docs/html/guide/topics/ui/accessibility/services.jd
index c868080..d69af9f 100644
--- a/docs/html/guide/topics/ui/accessibility/services.jd
+++ b/docs/html/guide/topics/ui/accessibility/services.jd
@@ -71,24 +71,30 @@
 
 <h3 id="service-declaration">Accessibility service declaration</h3>
 
-<p>In order to be treated as an accessibility service, your application must include the
+<p>In order to be treated as an accessibility service, you must include a
 {@code service} element (rather than the {@code activity} element) within the {@code application}
-element in its manifest. In addition, within the {@code service} element, you must also include an
+element in your manifest. In addition, within the {@code service} element, you must also include an
 accessibility service intent filter. For compatiblity with Android 4.1 and higher, the manifest
 must also request the {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission
 as shown in the following sample:</p>
 
 <pre>
-&lt;application&gt;
-  &lt;service android:name=&quot;.MyAccessibilityService&quot;
-      android:label=&quot;@string/accessibility_service_label&quot;
-      android:permission=&quot;android.permission.BIND_ACCESSIBILITY_SERVICE&quot&gt;
-    &lt;intent-filter&gt;
-      &lt;action android:name=&quot;android.accessibilityservice.AccessibilityService&quot; /&gt;
-    &lt;/intent-filter&gt;
-  &lt;/service&gt;
-  &lt;uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" /&gt;
-&lt;/application&gt;
+&lt;manifest&gt;
+  ...
+  &lt;uses-permission ... /&gt;
+  ...
+  &lt;application&gt;
+    ...
+    &lt;service android:name=&quot;.MyAccessibilityService&quot;
+        android:label=&quot;@string/accessibility_service_label&quot;
+        android:permission=&quot;android.permission.BIND_ACCESSIBILITY_SERVICE&quot&gt;
+      &lt;intent-filter&gt;
+        &lt;action android:name=&quot;android.accessibilityservice.AccessibilityService&quot; /&gt;
+      &lt;/intent-filter&gt;
+    &lt;/service&gt;
+    &lt;uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" /&gt;
+  &lt;/application&gt;
+&lt;/manifest&gt;
 </pre>
 
 <p>These declarations are required for all accessibility services deployed on Android 1.6 (API Level
diff --git a/docs/html/images/tools/projectview01.png b/docs/html/images/tools/projectview01.png
new file mode 100644
index 0000000..90589fb
--- /dev/null
+++ b/docs/html/images/tools/projectview01.png
Binary files differ
diff --git a/docs/html/images/tools/projectview03.png b/docs/html/images/tools/projectview03.png
new file mode 100644
index 0000000..f527ff1
--- /dev/null
+++ b/docs/html/images/tools/projectview03.png
Binary files differ
diff --git a/docs/html/sdk/installing/studio-androidview.jd b/docs/html/sdk/installing/studio-androidview.jd
new file mode 100644
index 0000000..09aeaba
--- /dev/null
+++ b/docs/html/sdk/installing/studio-androidview.jd
@@ -0,0 +1,55 @@
+page.title=Using the Android Project View
+
+@jd:body
+
+
+<p>The Android project view in Android Studio shows a flattened version of your project's structure
+that provides quick access to the key source files of Android projects and helps you work with
+the new <a href="{@docRoot}sdk/installing/studio-build.html">Gradle-based build system</a>. The
+Android project view:</p>
+
+<ul>
+<li>Groups the build files for all modules at the top level of the project hierarchy.</li>
+<li>Shows the most important source directories at the top level of the module hierarchy.</li>
+<li>Groups all the manifest files for each module.</li>
+<li>Shows resource files from all Gradle source sets.</li>
+<li>Groups resource files for different locales, orientations, and screen types in a single group
+per resource type.</li>
+</ul>
+
+<div style="float:right;margin-left:30px;width:240px">
+<img src="{@docRoot}images/tools/projectview01.png" alt="" width="220" height="264"/>
+<p class="img-caption"><strong>Figure 1:</strong> Show the Android project view.</p>
+</div>
+
+
+<h2 id="enable-view">Enable the Android Project View</h2>
+
+<p>The Android project view is not yet enabled by default. To show the Android project view,
+click <strong>Project</strong> and select <strong>Android</strong>, as shown in Figure 1.</p>
+
+
+<h2 id="project-view">Use the Android Project View</h2>
+
+<p>The Android project view shows all the build files at the top level of the project hierarchy
+under <strong>Gradle Scripts</strong>. Each project module appears as a folder at the top
+level of the project hierarchy and contains these three elements at the top level:</p>
+
+<ul>
+<li><code>java/</code> - Source files for the module.</li>
+<li><code>manifests/</code> - Manifest files for the module.</li>
+<li><code>res/</code> - Resource files for the module.</li>
+</ul>
+
+<p>Figure 2 shows how the Android project view groups all the instances of the
+<code>ic_launcher.png</code> resource for different screen densities under the same element.</p>
+
+<p class="note"><strong>Note:</strong> The Android project view shows a hierarchy that helps you
+work with Android projects by providing a flattened structure that highlights the most commonly
+used files while developing Android applications. However, the project structure on disk differs
+from this representation.</p>
+
+<img src="{@docRoot}images/tools/projectview03.png" alt=""
+     style="margin-top:10px" width="650" height="508"/>
+<p class="img-caption"><strong>Figure 2:</strong> The traditional project view (left) and the
+Android project view (right).</p>
\ No newline at end of file
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index 93e5976..8eb9cbf 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -24,6 +24,8 @@
           Creating a Project</a></li>
       <li><a href="<?cs var:toroot ?>sdk/installing/studio-tips.html">
           Tips and Tricks</a></li>
+      <li><a href="<?cs var:toroot ?>sdk/installing/studio-androidview.html">
+          Using the Android Project View</a></li>
       <li><a href="<?cs var:toroot ?>sdk/installing/studio-layout.html">
           Using the Layout Editor</a></li>
       <li><a href="<?cs var:toroot ?>sdk/installing/studio-build.html">
diff --git a/docs/html/wear/images/partners/sony.png b/docs/html/wear/images/partners/sony.png
new file mode 100644
index 0000000..e097fbb
--- /dev/null
+++ b/docs/html/wear/images/partners/sony.png
Binary files differ
diff --git a/docs/html/wear/index.jd b/docs/html/wear/index.jd
index 5dd7690..c372395 100644
--- a/docs/html/wear/index.jd
+++ b/docs/html/wear/index.jd
@@ -228,6 +228,9 @@
             <div class="col-4">
               <img src="/wear/images/partners/samsung.png" alt="Samsung">
             </div>
+            <div class="col-4">
+              <img src="/wear/images/partners/sony.png" alt="Sony">
+            </div>
           </div>
         </div> <!-- end .wrap -->
       </div>
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index f18694b..0927ffd 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -203,7 +203,7 @@
      */
     public void setBitmap(@Nullable Bitmap bitmap) {
         if (isHardwareAccelerated()) {
-            throw new RuntimeException("Can't set a bitmap device on a GL canvas");
+            throw new RuntimeException("Can't set a bitmap device on a HW accelerated canvas");
         }
 
         if (bitmap == null) {
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index 5aa7c6a..d28c3d5 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -122,6 +122,11 @@
      * @param canvas  The picture is drawn to this canvas
      */
     public void draw(Canvas canvas) {
+        if (canvas.isHardwareAccelerated()) {
+            throw new IllegalArgumentException(
+                    "Picture playback is only supported on software canvas.");
+        }
+
         if (mRecordingCanvas != null) {
             endRecording();
         }
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index c078c1c..705f5e6 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -60,6 +60,8 @@
      * @see Color
      * @see #getColor()
      * @see #getMode()
+     *
+     * @hide
      */
     public void setColor(int color) {
         mColor = color;
@@ -84,6 +86,8 @@
      * @see PorterDuff
      * @see #getMode()
      * @see #getColor()
+     *
+     * @hide
      */
     public void setMode(PorterDuff.Mode mode) {
         mMode = mode;
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index a20b6d8..384226f 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -86,6 +86,8 @@
             throws XmlPullParserException, IOException {
         final TypedArray a = r.obtainAttributes(attrs, R.styleable.InsetDrawable);
         super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible);
+
+        mInsetState.mDrawable = null;
         updateStateFromTypedArray(a);
 
         // Load inner XML elements.
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index cd919a6..43922b8 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -419,18 +419,22 @@
     private void endSoftwareAnimations() {
         if (mAnimRadius != null) {
             mAnimRadius.end();
+            mAnimRadius = null;
         }
 
         if (mAnimOpacity != null) {
             mAnimOpacity.end();
+            mAnimOpacity = null;
         }
 
         if (mAnimX != null) {
             mAnimX.end();
+            mAnimX = null;
         }
 
         if (mAnimY != null) {
             mAnimY.end();
+            mAnimY = null;
         }
     }
 
@@ -506,18 +510,22 @@
     private void cancelSoftwareAnimations() {
         if (mAnimRadius != null) {
             mAnimRadius.cancel();
+            mAnimRadius = null;
         }
 
         if (mAnimOpacity != null) {
             mAnimOpacity.cancel();
+            mAnimOpacity = null;
         }
 
         if (mAnimX != null) {
             mAnimX.cancel();
+            mAnimX = null;
         }
 
         if (mAnimY != null) {
             mAnimY.cancel();
+            mAnimY = null;
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 40a5e18..80ecea3 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -37,10 +37,8 @@
  */
 class RippleBackground {
     private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
-    private static final TimeInterpolator DECEL_INTERPOLATOR = new LogInterpolator();
 
     private static final float GLOBAL_SPEED = 1.0f;
-    private static final float WAVE_TOUCH_DOWN_ACCELERATION = 1024.0f * GLOBAL_SPEED;
     private static final float WAVE_OPACITY_DECAY_VELOCITY = 3.0f / GLOBAL_SPEED;
     private static final float WAVE_OUTER_OPACITY_EXIT_VELOCITY_MAX = 4.5f * GLOBAL_SPEED;
     private static final float WAVE_OUTER_OPACITY_EXIT_VELOCITY_MIN = 1.5f * GLOBAL_SPEED;
@@ -70,11 +68,6 @@
     /** Screen density used to adjust pixel-based velocities. */
     private float mDensity;
 
-    private float mStartingX;
-    private float mStartingY;
-    private float mClampedStartingX;
-    private float mClampedStartingY;
-
     // Hardware rendering properties.
     private CanvasProperty<Paint> mPropOuterPaint;
     private CanvasProperty<Float> mPropOuterRadius;
@@ -83,8 +76,6 @@
 
     // Software animators.
     private ObjectAnimator mAnimOuterOpacity;
-    private ObjectAnimator mAnimX;
-    private ObjectAnimator mAnimY;
 
     // Temporary paint used for creating canvas properties.
     private Paint mTempPaint;
@@ -94,10 +85,6 @@
     private float mOuterX;
     private float mOuterY;
 
-    // Values used to tween between the start and end positions.
-    private float mTweenX = 0;
-    private float mTweenY = 0;
-
     /** Whether we should be drawing hardware animations. */
     private boolean mHardwareAnimating;
 
@@ -107,18 +94,12 @@
     /** Whether we have an explicit maximum radius. */
     private boolean mHasMaxRadius;
 
-    /** Whether we were canceled externally and should avoid self-removal. */
-    private boolean mCanceled;
-
     /**
      * Creates a new ripple.
      */
-    public RippleBackground(RippleDrawable owner, Rect bounds, float startingX, float startingY) {
+    public RippleBackground(RippleDrawable owner, Rect bounds) {
         mOwner = owner;
         mBounds = bounds;
-
-        mStartingX = startingX;
-        mStartingY = startingY;
     }
 
     public void setup(int maxRadius, int color, float density) {
@@ -136,25 +117,6 @@
         mOuterX = 0;
         mOuterY = 0;
         mDensity = density;
-
-        clampStartingPosition();
-    }
-
-    private void clampStartingPosition() {
-        final float cX = mBounds.exactCenterX();
-        final float cY = mBounds.exactCenterY();
-        final float dX = mStartingX - cX;
-        final float dY = mStartingY - cY;
-        final float r = mOuterRadius;
-        if (dX * dX + dY * dY > r * r) {
-            // Point is outside the circle, clamp to the circumference.
-            final double angle = Math.atan2(dY, dX);
-            mClampedStartingX = cX + (float) (Math.cos(angle) * r);
-            mClampedStartingY = cY + (float) (Math.sin(angle) * r);
-        } else {
-            mClampedStartingX = mStartingX;
-            mClampedStartingY = mStartingY;
-        }
     }
 
     public void onHotspotBoundsChanged() {
@@ -162,8 +124,6 @@
             final float halfWidth = mBounds.width() / 2.0f;
             final float halfHeight = mBounds.height() / 2.0f;
             mOuterRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight);
-
-            clampStartingPosition();
         }
     }
 
@@ -178,28 +138,6 @@
         return mOuterOpacity;
     }
 
-    @SuppressWarnings("unused")
-    public void setXGravity(float x) {
-        mTweenX = x;
-        invalidateSelf();
-    }
-
-    @SuppressWarnings("unused")
-    public float getXGravity() {
-        return mTweenX;
-    }
-
-    @SuppressWarnings("unused")
-    public void setYGravity(float y) {
-        mTweenY = y;
-        invalidateSelf();
-    }
-
-    @SuppressWarnings("unused")
-    public float getYGravity() {
-        return mTweenY;
-    }
-
     /**
      * Draws the ripple centered at (0,0) using the specified paint.
      */
@@ -273,53 +211,23 @@
     }
 
     /**
-     * Specifies the starting position relative to the drawable bounds. No-op if
-     * the ripple has already entered.
-     */
-    public void move(float x, float y) {
-        mStartingX = x;
-        mStartingY = y;
-
-        clampStartingPosition();
-    }
-
-    /**
      * Starts the enter animation.
      */
     public void enter() {
         cancel();
 
-        final int radiusDuration = (int)
-                (1000 * Math.sqrt(mOuterRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensity) + 0.5);
         final int outerDuration = (int) (1000 * 1.0f / WAVE_OUTER_OPACITY_ENTER_VELOCITY);
-
-        final ObjectAnimator cX = ObjectAnimator.ofFloat(this, "xGravity", 1);
-        cX.setAutoCancel(true);
-        cX.setDuration(radiusDuration);
-        cX.setInterpolator(LINEAR_INTERPOLATOR);
-        cX.setStartDelay(RIPPLE_ENTER_DELAY);
-
-        final ObjectAnimator cY = ObjectAnimator.ofFloat(this, "yGravity", 1);
-        cY.setAutoCancel(true);
-        cY.setDuration(radiusDuration);
-        cY.setInterpolator(LINEAR_INTERPOLATOR);
-        cY.setStartDelay(RIPPLE_ENTER_DELAY);
-
         final ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerOpacity", 0, 1);
         outer.setAutoCancel(true);
         outer.setDuration(outerDuration);
         outer.setInterpolator(LINEAR_INTERPOLATOR);
 
         mAnimOuterOpacity = outer;
-        mAnimX = cX;
-        mAnimY = cY;
 
         // Enter animations always run on the UI thread, since it's unlikely
         // that anything interesting is happening until the user lifts their
         // finger.
         outer.start();
-        cX.start();
-        cY.start();
     }
 
     /**
@@ -355,12 +263,6 @@
     private void exitHardware(int opacityDuration, int outerInflection, int inflectionOpacity) {
         mPendingAnimations.clear();
 
-        // TODO: Adjust background by starting position.
-        final float startX = MathUtils.lerp(
-                mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX);
-        final float startY = MathUtils.lerp(
-                mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY);
-
         final Paint outerPaint = getTempPaint();
         outerPaint.setAntiAlias(true);
         outerPaint.setColor(mColor);
@@ -406,6 +308,9 @@
 
         mHardwareAnimating = true;
 
+        // Set up the software values to match the hardware end values.
+        mOuterOpacity = 0;
+
         invalidateSelf();
     }
 
@@ -414,23 +319,14 @@
      * removing the ripple from the list of animating ripples.
      */
     public void jump() {
-        mCanceled = true;
         endSoftwareAnimations();
         endHardwareAnimations();
-        mCanceled = false;
     }
 
     private void endSoftwareAnimations() {
         if (mAnimOuterOpacity != null) {
             mAnimOuterOpacity.end();
-        }
-
-        if (mAnimX != null) {
-            mAnimX.end();
-        }
-
-        if (mAnimY != null) {
-            mAnimY.end();
+            mAnimOuterOpacity = null;
         }
     }
 
@@ -446,7 +342,6 @@
         // listener on a pending animation, we also need to remove ourselves.
         if (!mPendingAnimations.isEmpty()) {
             mPendingAnimations.clear();
-            removeSelf();
         }
 
         mHardwareAnimating = false;
@@ -460,16 +355,6 @@
     }
 
     private void exitSoftware(int opacityDuration, int outerInflection, int inflectionOpacity) {
-        final ObjectAnimator xAnim = ObjectAnimator.ofFloat(this, "xGravity", 1);
-        xAnim.setAutoCancel(true);
-        xAnim.setDuration(opacityDuration);
-        xAnim.setInterpolator(DECEL_INTERPOLATOR);
-
-        final ObjectAnimator yAnim = ObjectAnimator.ofFloat(this, "yGravity", 1);
-        yAnim.setAutoCancel(true);
-        yAnim.setDuration(opacityDuration);
-        yAnim.setInterpolator(DECEL_INTERPOLATOR);
-
         final ObjectAnimator outerOpacityAnim;
         if (outerInflection > 0) {
             // Outer opacity continues to increase for a bit.
@@ -513,12 +398,8 @@
         }
 
         mAnimOuterOpacity = outerOpacityAnim;
-        mAnimX = xAnim;
-        mAnimY = yAnim;
 
         outerOpacityAnim.start();
-        xAnim.start();
-        yAnim.start();
     }
 
     /**
@@ -526,23 +407,14 @@
      * the ripple from the list of animating ripples.
      */
     public void cancel() {
-        mCanceled = true;
         cancelSoftwareAnimations();
         cancelHardwareAnimations(true);
-        mCanceled = false;
     }
 
     private void cancelSoftwareAnimations() {
         if (mAnimOuterOpacity != null) {
             mAnimOuterOpacity.cancel();
-        }
-
-        if (mAnimX != null) {
-            mAnimX.cancel();
-        }
-
-        if (mAnimY != null) {
-            mAnimY.cancel();
+            mAnimOuterOpacity = null;
         }
     }
 
@@ -555,7 +427,6 @@
         for (int i = 0; i < N; i++) {
             runningAnimations.get(i).cancel();
         }
-
         runningAnimations.clear();
 
         if (cancelPending && !mPendingAnimations.isEmpty()) {
@@ -565,13 +436,6 @@
         mHardwareAnimating = false;
     }
 
-    private void removeSelf() {
-        // The owner will invalidate itself.
-        if (!mCanceled) {
-            mOwner.removeBackground(this);
-        }
-    }
-
     private void invalidateSelf() {
         mOwner.invalidateSelf();
     }
@@ -579,7 +443,7 @@
     private final AnimatorListenerAdapter mAnimationListener = new AnimatorListenerAdapter() {
         @Override
         public void onAnimationEnd(Animator animation) {
-            removeSelf();
+            mHardwareAnimating = false;
         }
     };
 
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index b90fd81..fa762b7 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -248,15 +248,14 @@
         boolean pressed = false;
         boolean focused = false;
 
-        final int N = stateSet.length;
-        for (int i = 0; i < N; i++) {
-            if (stateSet[i] == R.attr.state_enabled) {
+        for (int state : stateSet) {
+            if (state == R.attr.state_enabled) {
                 enabled = true;
             }
-            if (stateSet[i] == R.attr.state_focused) {
+            if (state == R.attr.state_focused) {
                 focused = true;
             }
-            if (stateSet[i] == R.attr.state_pressed) {
+            if (state == R.attr.state_pressed) {
                 pressed = true;
             }
         }
@@ -478,10 +477,6 @@
         if (mRipple != null) {
             mRipple.move(x, y);
         }
-
-        if (mBackground != null) {
-            mBackground.move(x, y);
-        }
     }
 
     /**
@@ -489,17 +484,7 @@
      */
     private void tryBackgroundEnter() {
         if (mBackground == null) {
-            final float x;
-            final float y;
-            if (mHasPending) {
-                mHasPending = false;
-                x = mPendingX;
-                y = mPendingY;
-            } else {
-                x = mHotspotBounds.exactCenterX();
-                y = mHotspotBounds.exactCenterY();
-            }
-            mBackground = new RippleBackground(this, mHotspotBounds, x, y);
+            mBackground = new RippleBackground(this, mHotspotBounds);
         }
 
         final int color = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
@@ -628,11 +613,10 @@
 
     @Override
     public void draw(@NonNull Canvas canvas) {
-        final boolean isProjected = isProjected();
         final boolean hasMask = mMask != null;
         final boolean drawNonMaskContent = mLayerState.mNum > (hasMask ? 1 : 0);
         final boolean drawMask = hasMask && mMask.getOpacity() != PixelFormat.OPAQUE;
-        final Rect bounds = isProjected ? getDirtyBounds() : getBounds();
+        final Rect bounds = getDirtyBounds();
 
         // If we have content, draw it into a layer first.
         final int contentLayer = drawNonMaskContent ?
@@ -685,13 +669,6 @@
         }
     }
 
-    void removeBackground(RippleBackground background) {
-        if (mBackground == background) {
-            mBackground = null;
-            invalidateSelf();
-        }
-    }
-
     private int getRippleIndex(Ripple ripple) {
         final Ripple[] ripples = mExitingRipples;
         final int count = mExitingRipplesCount;
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index b5d9729..1072b3c 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -195,6 +195,7 @@
     public Page openPage(int index) {
         throwIfClosed();
         throwIfPageOpened();
+        throwIfPageNotInDocument(index);
         mCurrentPage = new Page(index);
         return mCurrentPage;
     }
@@ -237,6 +238,12 @@
         }
     }
 
+    private void throwIfPageNotInDocument(int pageIndex) {
+        if (pageIndex >= mPageCount) {
+            throw new IllegalArgumentException("Invalid page index");
+        }
+    }
+
     /**
      * This class represents a PDF document page for rendering.
      */
diff --git a/libs/hwui/AnimationContext.cpp b/libs/hwui/AnimationContext.cpp
index d7d9743..716dcf5 100644
--- a/libs/hwui/AnimationContext.cpp
+++ b/libs/hwui/AnimationContext.cpp
@@ -31,11 +31,14 @@
 }
 
 AnimationContext::~AnimationContext() {
+}
+
+void AnimationContext::destroy() {
     startFrame();
     while (mCurrentFrameAnimations.mNextHandle) {
         AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
         AnimatorManager& animators = current->mRenderNode->animators();
-        animators.endAllAnimators();
+        animators.endAllActiveAnimators();
         LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
                 "endAllAnimators failed to remove from current frame list!");
     }
diff --git a/libs/hwui/AnimationContext.h b/libs/hwui/AnimationContext.h
index 900d953..9b3d5f4 100644
--- a/libs/hwui/AnimationContext.h
+++ b/libs/hwui/AnimationContext.h
@@ -98,6 +98,8 @@
 
     ANDROID_API virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener);
 
+    ANDROID_API virtual void destroy();
+
 private:
     friend class AnimationHandle;
     void addAnimationHandle(AnimationHandle* handle);
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index da65f38..4f3a573 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -161,6 +161,13 @@
     return false;
 }
 
+void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
+    if (mPlayState < FINISHED) {
+        mPlayState = FINISHED;
+        callOnFinishedListener(context);
+    }
+}
+
 void BaseRenderNodeAnimator::callOnFinishedListener(AnimationContext& context) {
     if (mListener.get()) {
         context.callOnFinished(this, mListener.get());
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index c52a93f..1ab6235 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -68,6 +68,8 @@
 
     ANDROID_API virtual uint32_t dirtyMask() = 0;
 
+    void forceEndNow(AnimationContext& context);
+
 protected:
     BaseRenderNodeAnimator(float finalValue);
     virtual ~BaseRenderNodeAnimator();
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 678b1ee..e06d800 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -49,6 +49,9 @@
 void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
     LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
     mAnimationHandle = handle;
+    LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
+            "Lost animation handle on %p (%s) with outstanding animators!",
+            &mParent, mParent.getName());
 }
 
 template<typename T>
@@ -62,6 +65,9 @@
 
 void AnimatorManager::pushStaging() {
     if (mNewAnimators.size()) {
+        LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
+                "Trying to start new animators on %p (%s) without an animation handle!",
+                &mParent, mParent.getName());
         // Since this is a straight move, we don't need to inc/dec the ref count
         move_all(mNewAnimators, mAnimators);
     }
@@ -128,22 +134,7 @@
     return functor.dirtyMask;
 }
 
-class EndAnimatorsFunctor {
-public:
-    EndAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
-
-    void operator() (BaseRenderNodeAnimator* animator) {
-        animator->end();
-        animator->pushStaging(mContext);
-        animator->animate(mContext);
-        animator->decStrong(0);
-    }
-
-private:
-    AnimationContext& mContext;
-};
-
-static void endAnimatorsHard(BaseRenderNodeAnimator* animator) {
+static void endStagingAnimator(BaseRenderNodeAnimator* animator) {
     animator->end();
     if (animator->listener()) {
         animator->listener()->onAnimationFinished(animator);
@@ -151,24 +142,34 @@
     animator->decStrong(0);
 }
 
-void AnimatorManager::endAllAnimators() {
-    if (mNewAnimators.size()) {
-        // Since this is a straight move, we don't need to inc/dec the ref count
-        move_all(mNewAnimators, mAnimators);
+void AnimatorManager::endAllStagingAnimators() {
+    ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
+    // This works because this state can only happen on the UI thread,
+    // which means we're already on the right thread to invoke listeners
+    for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
+    mNewAnimators.clear();
+}
+
+class EndActiveAnimatorsFunctor {
+public:
+    EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
+
+    void operator() (BaseRenderNodeAnimator* animator) {
+        animator->forceEndNow(mContext);
+        animator->decStrong(0);
     }
-    // First try gracefully ending them
-    if (mAnimationHandle) {
-        EndAnimatorsFunctor functor(mAnimationHandle->context());
-        for_each(mAnimators.begin(), mAnimators.end(), functor);
-        mAnimators.clear();
-        mAnimationHandle->release();
-    } else {
-        // We have no context, so bust out the sledgehammer
-        // This works because this state can only happen on the UI thread,
-        // which means we're already on the right thread to invoke listeners
-        for_each(mAnimators.begin(), mAnimators.end(), endAnimatorsHard);
-        mAnimators.clear();
-    }
+
+private:
+    AnimationContext& mContext;
+};
+
+void AnimatorManager::endAllActiveAnimators() {
+    ALOGD("endAllStagingAnimators on %p (%s) with handle %p",
+            &mParent, mParent.getName(), mAnimationHandle);
+    EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
+    for_each(mAnimators.begin(), mAnimators.end(), functor);
+    mAnimators.clear();
+    mAnimationHandle->release();
 }
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/AnimatorManager.h b/libs/hwui/AnimatorManager.h
index d5f56ed..d03d427 100644
--- a/libs/hwui/AnimatorManager.h
+++ b/libs/hwui/AnimatorManager.h
@@ -50,8 +50,12 @@
 
     void animateNoDamage(TreeInfo& info);
 
-    // Hard-ends all animators. Used for cleanup if the root is being destroyed.
-    ANDROID_API void endAllAnimators();
+    // Hard-ends all animators. May only be called on the UI thread.
+    ANDROID_API void endAllStagingAnimators();
+
+    // Hard-ends all animators that have been pushed. Used for cleanup if
+    // the ActivityContext is being destroyed
+    void endAllActiveAnimators();
 
     bool hasAnimators() { return mAnimators.size(); }
 
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 5689e17..9855f71 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -24,6 +24,7 @@
 #include "Properties.h"
 #include "LayerRenderer.h"
 #include "ShadowTessellator.h"
+#include "RenderState.h"
 
 namespace android {
 
@@ -49,7 +50,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 Caches::Caches(): Singleton<Caches>(),
-        mExtensions(Extensions::getInstance()), mInitialized(false) {
+        mExtensions(Extensions::getInstance()), mInitialized(false), mRenderState(NULL) {
     init();
     initFont();
     initConstraints();
@@ -267,8 +268,11 @@
     log.appendFormat("Current memory usage / total memory usage (bytes):\n");
     log.appendFormat("  TextureCache         %8d / %8d\n",
             textureCache.getSize(), textureCache.getMaxSize());
-    log.appendFormat("  LayerCache           %8d / %8d\n",
-            layerCache.getSize(), layerCache.getMaxSize());
+    log.appendFormat("  LayerCache           %8d / %8d (numLayers = %zu)\n",
+            layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount());
+    log.appendFormat("  Garbage layers       %8zu\n", mLayerGarbage.size());
+    log.appendFormat("  Active layers        %8zu\n",
+            mRenderState ? mRenderState->mActiveLayers.size() : 0);
     log.appendFormat("  RenderBufferCache    %8d / %8d\n",
             renderBufferCache.getSize(), renderBufferCache.getMaxSize());
     log.appendFormat("  GradientCache        %8d / %8d\n",
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 0482430..726b74d 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -107,6 +107,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 class RenderNode;
+class RenderState;
 
 class ANDROID_API Caches: public Singleton<Caches> {
     Caches();
@@ -132,6 +133,8 @@
      */
     bool initProperties();
 
+    void setRenderState(RenderState* renderState) { mRenderState = renderState; }
+
     /**
      * Flush the cache.
      *
@@ -431,6 +434,8 @@
     GLuint mBoundTextures[REQUIRED_TEXTURE_UNITS_COUNT];
 
     OverdrawColorSet mOverdrawDebugColorSet;
+
+    RenderState* mRenderState;
 }; // class Caches
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index e6bc4db..25caae3 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -54,6 +54,7 @@
     convexMask = NULL;
     caches.resourceCache.incrementRefcount(this);
     rendererLightPosDirty = true;
+    wasBuildLayered = false;
     renderState.registerLayer(this);
 }
 
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 38c29c7..911b99880 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -306,6 +306,7 @@
     Rect dirtyRect;
     bool debugDrawUpdate;
     bool hasDrawnSinceUpdate;
+    bool wasBuildLayered;
 
 private:
     void requireRenderer();
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 13869aa..efa30ac 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -49,6 +49,10 @@
 // Size management
 ///////////////////////////////////////////////////////////////////////////////
 
+size_t LayerCache::getCount() {
+    return mCache.size();
+}
+
 uint32_t LayerCache::getSize() {
     return mSize;
 }
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index 1b0fc2c..6b93e8f 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -87,6 +87,8 @@
      */
     uint32_t getSize();
 
+    size_t getCount();
+
     /**
      * Prints out the content of the cache.
      */
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 0f36c06..dbd273d 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -605,6 +605,12 @@
     AutoFence fence;
 }
 
+void OpenGLRenderer::markLayersAsBuildLayers() {
+    for (size_t i = 0; i < mLayerUpdates.size(); i++) {
+        mLayerUpdates[i]->wasBuildLayered = true;
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // State management
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index e9ca5d9..e295b1a 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -150,6 +150,7 @@
     void cancelLayerUpdate(Layer* layer);
     void clearLayerUpdates();
     void flushLayerUpdates();
+    void markLayersAsBuildLayers();
 
     virtual int saveLayer(float left, float top, float right, float bottom,
             const SkPaint* paint, int flags) {
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index c802b18..a8b8b16 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -88,7 +88,7 @@
         "varying vec2 ditherTexCoords;\n",
 };
 const char* gVS_Header_Varyings_HasRoundRectClip =
-        "varying vec2 roundRectPos;\n";
+        "varying highp vec2 roundRectPos;\n";
 const char* gVS_Main =
         "\nvoid main(void) {\n";
 const char* gVS_Main_OutTexCoords =
@@ -328,8 +328,7 @@
         "",
         // Matrix
         "    fragColor *= colorMatrix;\n"
-        "    fragColor += colorMatrixVector;\n"
-        "    fragColor.rgb *= fragColor.a;\n",
+        "    fragColor += colorMatrixVector;\n",
         // PorterDuff
         "    fragColor = blendColors(colorBlend, fragColor);\n"
 };
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 6a92a6e..a10e70f 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -58,6 +58,19 @@
     fflush(file);
 }
 
+void RenderNode::debugDumpLayers(const char* prefix) {
+    if (mLayer) {
+        ALOGD("%sNode %p (%s) has layer %p (fbo = %u, wasBuildLayered = %s)",
+                prefix, this, getName(), mLayer, mLayer->getFbo(),
+                mLayer->wasBuildLayered ? "true" : "false");
+    }
+    if (mDisplayListData) {
+        for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
+            mDisplayListData->children()[i]->mRenderNode->debugDumpLayers(prefix);
+        }
+    }
+}
+
 RenderNode::RenderNode()
         : mDirtyPropertyFields(0)
         , mNeedsDisplayListDataSync(false)
@@ -413,7 +426,7 @@
         handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
     }
 
-    // TODO: support both reveal clip and outline clip simultaneously
+    // TODO: support nesting round rect clips
     if (mProperties.getRevealClip().willClip()) {
         Rect bounds;
         mProperties.getRevealClip().getBounds(&bounds);
@@ -421,7 +434,6 @@
     } else if (mProperties.getOutline().willClip()) {
         renderer.setClippingOutline(handler.allocator(), &(mProperties.getOutline()));
     }
-
 }
 
 /**
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index d897997..f329283 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -102,6 +102,7 @@
     };
 
     ANDROID_API static void outputLogBuffer(int fd);
+    void debugDumpLayers(const char* prefix);
 
     ANDROID_API void setStagingDisplayList(DisplayListData* newData);
 
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
index 50b8f39..a7c5e85 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/RenderState.cpp
@@ -15,6 +15,8 @@
  */
 #include "RenderState.h"
 
+#include "renderthread/CanvasContext.h"
+
 namespace android {
 namespace uirenderer {
 
@@ -32,10 +34,25 @@
     // This is delayed because the first access of Caches makes GL calls
     mCaches = &Caches::getInstance();
     mCaches->init();
+    mCaches->setRenderState(this);
 }
 
 void RenderState::onGLContextDestroyed() {
-    LOG_ALWAYS_FATAL_IF(!mActiveLayers.empty(), "layers have survived gl context destruction");
+    if (CC_UNLIKELY(!mActiveLayers.empty())) {
+        mCaches->dumpMemoryUsage();
+        for (std::set<renderthread::CanvasContext*>::iterator cit = mRegisteredContexts.begin();
+                cit != mRegisteredContexts.end(); cit++) {
+            renderthread::CanvasContext* context = *cit;
+            ALOGD("Context: %p (root = %p)", context, context->mRootRenderNode.get());
+            ALOGD("  Prefeteched layers: %zu", context->mPrefetechedLayers.size());
+            for (std::set<RenderNode*>::iterator pit = context->mPrefetechedLayers.begin();
+                    pit != context->mPrefetechedLayers.end(); pit++) {
+                (*pit)->debugDumpLayers("    ");
+            }
+            context->mRootRenderNode->debugDumpLayers("  ");
+        }
+        LOG_ALWAYS_FATAL("layers have survived gl context destruction");
+    }
 }
 
 void RenderState::setViewport(GLsizei width, GLsizei height) {
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
index cd71c73..c7ab197 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/RenderState.h
@@ -29,6 +29,7 @@
 namespace uirenderer {
 
 namespace renderthread {
+class CanvasContext;
 class RenderThread;
 }
 
@@ -57,8 +58,17 @@
         mActiveLayers.erase(layer);
     }
 
+    void registerCanvasContext(renderthread::CanvasContext* context) {
+        mRegisteredContexts.insert(context);
+    }
+
+    void unregisterCanvasContext(renderthread::CanvasContext* context) {
+        mRegisteredContexts.erase(context);
+    }
+
 private:
     friend class renderthread::RenderThread;
+    friend class Caches;
 
     void interruptForFunctorInvoke();
     void resumeFromFunctorInvoke();
@@ -68,6 +78,7 @@
 
     Caches* mCaches;
     std::set<const Layer*> mActiveLayers;
+    std::set<renderthread::CanvasContext*> mRegisteredContexts;
 
     GLsizei mViewportWidth;
     GLsizei mViewportHeight;
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index ecc47d2..cf8229f 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -216,14 +216,22 @@
 // Clipping round rect
 ///////////////////////////////////////////////////////////////////////////////
 
-void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius) {
+void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds,
+        float radius, bool highPriority) {
     if (bounds.isEmpty()) {
         clipRect->setEmpty();
         return;
     }
 
+    if (roundRectClipState && roundRectClipState->highPriority) {
+        // ignore, don't replace, already have a high priority clip
+        return;
+    }
+
     RoundRectClipState* state = new (allocator) RoundRectClipState;
 
+    state->highPriority = highPriority;
+
     // store the inverse drawing matrix
     Matrix4 roundRectDrawingMatrix;
     roundRectDrawingMatrix.load(getOrthoMatrix());
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index ad4ee9d..549de9b 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -55,6 +55,7 @@
                 || rect.intersects(dangerRects[3]);
     }
 
+    bool highPriority;
     Matrix4 matrix;
     Rect dangerRects[4];
     Rect innerRect;
@@ -166,8 +167,11 @@
 
     /**
      * Sets (and replaces) the current clipping outline
+     *
+     * If the current round rect clip is high priority, the incoming clip is ignored.
      */
-    void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius);
+    void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds,
+            float radius, bool highPriority);
 
     /**
      * Indicates whether this snapshot should be ignored. A snapshot
diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp
index 3e1aed3..12b8c8d 100644
--- a/libs/hwui/StatefulBaseRenderer.cpp
+++ b/libs/hwui/StatefulBaseRenderer.cpp
@@ -198,13 +198,13 @@
         clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkRegion::kIntersect_Op);
     }
     if (outlineIsRounded) {
-        setClippingRoundRect(allocator, bounds, radius);
+        setClippingRoundRect(allocator, bounds, radius, false);
     }
 }
 
 void StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator,
-        const Rect& rect, float radius) {
-    mSnapshot->setClippingRoundRect(allocator, rect, radius);
+        const Rect& rect, float radius, bool highPriority) {
+    mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority);
 }
 
 
diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h
index c6974b4..745e48a 100644
--- a/libs/hwui/StatefulBaseRenderer.h
+++ b/libs/hwui/StatefulBaseRenderer.h
@@ -97,7 +97,7 @@
      */
     void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
     void setClippingRoundRect(LinearAllocator& allocator,
-            const Rect& rect, float radius);
+            const Rect& rect, float radius, bool highPriority = true);
 
     inline const mat4* currentTransform() const {
         return mSnapshot->transform;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 491a295..4129a89 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -48,16 +48,20 @@
         , mHaveNewSurface(false)
         , mRootRenderNode(rootRenderNode) {
     mAnimationContext = contextFactory->createAnimationContext(mRenderThread.timeLord());
+    mRenderThread.renderState().registerCanvasContext(this);
 }
 
 CanvasContext::~CanvasContext() {
-    destroyCanvasAndSurface();
-    mRenderThread.removeFrameCallback(this);
+    destroy();
     delete mAnimationContext;
-    freePrefetechedLayers();
+    mRenderThread.renderState().unregisterCanvasContext(this);
 }
 
-void CanvasContext::destroyCanvasAndSurface() {
+void CanvasContext::destroy() {
+    stopDrawing();
+    freePrefetechedLayers();
+    destroyHardwareResources();
+    mAnimationContext->destroy();
     if (mCanvas) {
         delete mCanvas;
         mCanvas = 0;
@@ -110,8 +114,7 @@
 }
 
 void CanvasContext::pauseSurface(ANativeWindow* window) {
-    // TODO: For now we just need a fence, in the future suspend any animations
-    // and such to prevent from trying to render into this surface
+    stopDrawing();
 }
 
 void CanvasContext::setup(int width, int height, const Vector3& lightCenter, float lightRadius,
@@ -298,6 +301,7 @@
     // purposes when the frame is actually drawn
     node->setPropertyFieldsDirty(RenderNode::GENERIC);
 
+    mCanvas->markLayersAsBuildLayers();
     mCanvas->flushLayerUpdates();
 
     node->incStrong(0);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 7c27190..2460f6b 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -42,6 +42,7 @@
 class OpenGLRenderer;
 class Rect;
 class Layer;
+class RenderState;
 
 namespace renderthread {
 
@@ -66,7 +67,7 @@
     void processLayerUpdate(DeferredLayerUpdater* layerUpdater);
     void prepareTree(TreeInfo& info);
     void draw();
-    void destroyCanvasAndSurface();
+    void destroy();
 
     // IFrameCallback, Chroreographer-driven frame callback entry point
     virtual void doFrame();
@@ -95,6 +96,9 @@
 
 private:
     friend class RegisterFrameCallbackTask;
+    // TODO: Replace with something better for layer & other GL object
+    // lifecycle tracking
+    friend class android::uirenderer::RenderState;
 
     void setSurface(ANativeWindow* window);
     void swapBuffers();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 3d04316..9528874 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -194,13 +194,13 @@
     return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos);
 }
 
-CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) {
-    args->context->destroyCanvasAndSurface();
+CREATE_BRIDGE1(destroy, CanvasContext* context) {
+    args->context->destroy();
     return NULL;
 }
 
-void RenderProxy::destroyCanvasAndSurface() {
-    SETUP_TASK(destroyCanvasAndSurface);
+void RenderProxy::destroy() {
+    SETUP_TASK(destroy);
     args->context = mContext;
     // destroyCanvasAndSurface() needs a fence as when it returns the
     // underlying BufferQueue is going to be released from under
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 9e6bcf5..8b8d99c 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -73,7 +73,7 @@
     ANDROID_API void setOpaque(bool opaque);
     ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
             float density);
-    ANDROID_API void destroyCanvasAndSurface();
+    ANDROID_API void destroy();
 
     ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
 
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 0b91e9d..c461f3a 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -40,6 +40,7 @@
 
 namespace renderthread {
 
+class CanvasContext;
 class DispatchFrameCallbacks;
 class EglManager;
 class RenderProxy;
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index bdd1195..fcf222b 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.SystemApi;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -771,6 +772,7 @@
      * @see #makeComplete
      * @hide
      */
+    @SystemApi
     public boolean isComplete() {
         if (mProvider == null) return false;
         if (!mHasAccuracy) return false;
@@ -788,6 +790,7 @@
      * @see #isComplete
      * @hide
      */
+    @SystemApi
     public void makeComplete() {
         if (mProvider == null) mProvider = "?";
         if (!mHasAccuracy) {
@@ -957,6 +960,7 @@
      * @param isFromMockProvider true if this Location came from a mock provider, false otherwise
      * @hide
      */
+    @SystemApi
     public void setIsFromMockProvider(boolean isFromMockProvider) {
         mIsFromMockProvider = isFromMockProvider;
     }
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index c9162fe..271f2bb 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -84,6 +85,7 @@
  *
  * @hide
  */
+@SystemApi
 public final class LocationRequest implements Parcelable {
     /**
      * Used with {@link #setQuality} to request the most accurate locations available.
@@ -166,6 +168,7 @@
     }
 
     /** @hide */
+    @SystemApi
     public static LocationRequest createFromDeprecatedProvider(String provider, long minTime,
             float minDistance, boolean singleShot) {
         if (minTime < 0) minTime = 0;
@@ -191,6 +194,7 @@
     }
 
     /** @hide */
+    @SystemApi
     public static LocationRequest createFromDeprecatedCriteria(Criteria criteria, long minTime,
             float minDistance, boolean singleShot) {
         if (minTime < 0) minTime = 0;
@@ -475,6 +479,7 @@
 
 
     /** @hide */
+    @SystemApi
     public LocationRequest setProvider(String provider) {
         checkProvider(provider);
         mProvider = provider;
@@ -482,11 +487,13 @@
     }
 
     /** @hide */
+    @SystemApi
     public String getProvider() {
         return mProvider;
     }
 
     /** @hide */
+    @SystemApi
     public LocationRequest setSmallestDisplacement(float meters) {
         checkDisplacement(meters);
         mSmallestDisplacement = meters;
@@ -494,6 +501,7 @@
     }
 
     /** @hide */
+    @SystemApi
     public float getSmallestDisplacement() {
         return mSmallestDisplacement;
     }
@@ -508,11 +516,13 @@
      * @param workSource WorkSource defining power blame for this location request.
      * @hide
      */
+    @SystemApi
     public void setWorkSource(WorkSource workSource) {
         mWorkSource = workSource;
     }
 
     /** @hide */
+    @SystemApi
     public WorkSource getWorkSource() {
         return mWorkSource;
     }
@@ -531,11 +541,13 @@
      * @see android.app.AppOpsManager
      * @hide
      */
+    @SystemApi
     public void setHideFromAppOps(boolean hideFromAppOps) {
         mHideFromAppOps = hideFromAppOps;
     }
 
     /** @hide */
+    @SystemApi
     public boolean getHideFromAppOps() {
         return mHideFromAppOps;
     }
diff --git a/location/java/android/location/SettingInjectorService.java b/location/java/android/location/SettingInjectorService.java
index 98c7864..fcd2cde 100644
--- a/location/java/android/location/SettingInjectorService.java
+++ b/location/java/android/location/SettingInjectorService.java
@@ -196,10 +196,7 @@
      * @deprecated not called any more
      */
     @Deprecated
-    protected String onGetSummary() {
-        // Do not delete until no callers have @Override annotations for this method
-        return null;
-    }
+    protected abstract String onGetSummary();
 
     /**
      * Returns the {@link android.preference.Preference#isEnabled()} value. Should not perform
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
index 8d2c172..9db4994 100644
--- a/media/java/android/media/AudioPortEventHandler.java
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -47,10 +47,7 @@
         mListeners = new ArrayList<AudioManager.OnAudioPortUpdateListener>();
 
         // find the looper for our new event handler
-        Looper looper = Looper.myLooper();
-        if (looper == null) {
-            looper = Looper.getMainLooper();
-        }
+        Looper looper = Looper.getMainLooper();
 
         if (looper != null) {
             mHandler = new Handler(looper) {
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 10fa404..329033c 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -544,6 +544,9 @@
         MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = SystemProperties.getInt(
             "ro.config.vc_call_vol_steps",
            MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]);
+        MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = SystemProperties.getInt(
+            "ro.config.media_vol_steps",
+           MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]);
 
         sSoundEffectVolumeDb = context.getResources().getInteger(
                 com.android.internal.R.integer.config_soundEffectVolumeDb);
@@ -1564,6 +1567,9 @@
                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
             return;
         }
+        if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
+            return;
+        }
 
         AudioSystem.muteMicrophone(on);
         // Post a persist microphone msg.
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1861bd7..f37cbe5 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1286,7 +1286,7 @@
 
     public int write(short[] audioData, int offsetInShorts, int sizeInShorts) {
 
-        if (mState == STATE_UNINITIALIZED || mAudioFormat != AudioFormat.ENCODING_PCM_16BIT) {
+        if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
             return ERROR_INVALID_OPERATION;
         }
 
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 6a4bf07..958ffab 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -2131,7 +2131,7 @@
             if (mVolume != volume) {
                 mVolume = volume;
                 if (mSvp != null) {
-                    mSvp.notifyVolumeChanged();
+                    mSvp.setCurrentVolume(mVolume);
                 }
                 dispatchRouteVolumeChanged(this);
                 if (mGroup != null) {
@@ -2217,7 +2217,7 @@
                 // Only register a new listener if necessary
                 if (mSvp == null || mSvp.getVolumeControl() != volumeControl
                         || mSvp.getMaxVolume() != mVolumeMax) {
-                    mSvp = new SessionVolumeProvider(volumeControl, mVolumeMax);
+                    mSvp = new SessionVolumeProvider(volumeControl, mVolumeMax, mVolume);
                     session.setPlaybackToRemote(mSvp);
                 }
             } else {
@@ -2231,13 +2231,8 @@
 
         class SessionVolumeProvider extends VolumeProvider {
 
-            public SessionVolumeProvider(int volumeControl, int maxVolume) {
-                super(volumeControl, maxVolume);
-            }
-
-            @Override
-            public int onGetCurrentVolume() {
-                return mVcb == null ? 0 : mVcb.route.mVolume;
+            public SessionVolumeProvider(int volumeControl, int maxVolume, int currentVolume) {
+                super(volumeControl, maxVolume, currentVolume);
             }
 
             @Override
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index f378cef..fbfac89 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -789,8 +789,12 @@
     void startListeningToSessions() {
         final ComponentName listenerComponent = new ComponentName(mContext,
                 mOnClientUpdateListener.getClass());
+        Handler handler = null;
+        if (Looper.myLooper() == null) {
+            handler = new Handler(Looper.getMainLooper());
+        }
         mSessionManager.addOnActiveSessionsChangedListener(mSessionListener, listenerComponent,
-                UserHandle.myUserId(), null);
+                UserHandle.myUserId(), handler);
         mSessionListener.onActiveSessionsChanged(mSessionManager
                 .getActiveSessions(listenerComponent));
         if (DEBUG) {
diff --git a/media/java/android/media/VolumeProvider.java b/media/java/android/media/VolumeProvider.java
index 9bda1d4..5d1e004 100644
--- a/media/java/android/media/VolumeProvider.java
+++ b/media/java/android/media/VolumeProvider.java
@@ -19,7 +19,9 @@
 
 /**
  * Handles requests to adjust or set the volume on a session. This is also used
- * to push volume updates back to the session after a request has been handled.
+ * to push volume updates back to the session. The provider must call
+ * {@link #setCurrentVolume(int)} each time the volume being provided changes.
+ * <p>
  * You can set a volume provider on a session by calling
  * {@link MediaSession#setPlaybackToRemote}.
  */
@@ -46,29 +48,26 @@
 
     private final int mControlType;
     private final int mMaxVolume;
+    private int mCurrentVolume;
     private Callback mCallback;
 
     /**
      * Create a new volume provider for handling volume events. You must specify
-     * the type of volume control and the maximum volume that can be used.
+     * the type of volume control, the maximum volume that can be used, and the
+     * current volume on the output.
      *
      * @param volumeControl The method for controlling volume that is used by
      *            this provider.
      * @param maxVolume The maximum allowed volume.
+     * @param currentVolume The current volume on the output.
      */
-    public VolumeProvider(int volumeControl, int maxVolume) {
+    public VolumeProvider(int volumeControl, int maxVolume, int currentVolume) {
         mControlType = volumeControl;
         mMaxVolume = maxVolume;
+        mCurrentVolume = currentVolume;
     }
 
     /**
-     * Get the current volume of the remote playback.
-     *
-     * @return The current volume.
-     */
-    public abstract int onGetCurrentVolume();
-
-    /**
      * Get the volume control type that this volume provider uses.
      *
      * @return The volume control type for this volume provider
@@ -87,9 +86,23 @@
     }
 
     /**
-     * Notify the system that the volume has been changed.
+     * Gets the current volume. This will be the last value set by
+     * {@link #setCurrentVolume(int)}.
+     *
+     * @return The current volume.
      */
-    public final void notifyVolumeChanged() {
+    public final int getCurrentVolume() {
+        return mCurrentVolume;
+    }
+
+    /**
+     * Notify the system that the current volume has been changed. This must be
+     * called every time the volume changes to ensure it is displayed properly.
+     *
+     * @param currentVolume The current volume on the output.
+     */
+    public final void setCurrentVolume(int currentVolume) {
+        mCurrentVolume = currentVolume;
         if (mCallback != null) {
             mCallback.onVolumeChanged(this);
         }
@@ -97,6 +110,8 @@
 
     /**
      * Override to handle requests to set the volume of the current output.
+     * After the volume has been modified {@link #setCurrentVolume} must be
+     * called to notify the system.
      *
      * @param volume The volume to set the output to.
      */
@@ -107,7 +122,9 @@
      * Override to handle requests to adjust the volume of the current output.
      * Direction will be one of {@link AudioManager#ADJUST_LOWER},
      * {@link AudioManager#ADJUST_RAISE}, {@link AudioManager#ADJUST_SAME}.
-     * 
+     * After the volume has been modified {@link #setCurrentVolume} must be
+     * called to notify the system.
+     *
      * @param direction The direction to change the volume in.
      */
     public void onAdjustVolume(int direction) {
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 9641f83..4d4d646 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -47,8 +47,9 @@
  * receive updates from the session, such as metadata and play state changes.
  * <p>
  * A MediaController can be created through {@link MediaSessionManager} if you
- * hold the "android.permission.MEDIA_CONTENT_CONTROL" permission or directly if
- * you have a {@link MediaSession.Token} from the session owner.
+ * hold the "android.permission.MEDIA_CONTENT_CONTROL" permission or are an
+ * enabled notification listener or by getting a {@link MediaSession.Token}
+ * directly from the session owner.
  * <p>
  * MediaController objects are thread-safe.
  */
@@ -612,14 +613,18 @@
 
         /**
          * Request that the player start playback for a specific search query.
+         * An empty or null query should be treated as a request to play any
+         * music.
          *
          * @param query The search query.
-         * @param extras Optional extras that can include extra information about the query.
+         * @param extras Optional extras that can include extra information
+         *            about the query.
          */
         public void playFromSearch(String query, Bundle extras) {
-            if (TextUtils.isEmpty(query)) {
-                throw new IllegalArgumentException(
-                        "You must specify a non-empty search query for playFromSearch.");
+            if (query == null) {
+                // This is to remain compatible with
+                // INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH
+                query = "";
             }
             try {
                 mSessionBinder.playFromSearch(query, extras);
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index ae8ce4b..8cb039a 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -300,7 +300,7 @@
         try {
             mBinder.setPlaybackToRemote(volumeProvider.getVolumeControl(),
                     volumeProvider.getMaxVolume());
-            mBinder.setCurrentVolume(volumeProvider.onGetCurrentVolume());
+            mBinder.setCurrentVolume(volumeProvider.getCurrentVolume());
         } catch (RemoteException e) {
             Log.wtf(TAG, "Failure in setPlaybackToRemote.", e);
         }
@@ -478,7 +478,7 @@
             return;
         }
         try {
-            mBinder.setCurrentVolume(provider.onGetCurrentVolume());
+            mBinder.setCurrentVolume(provider.getCurrentVolume());
         } catch (RemoteException e) {
             Log.e(TAG, "Error in notifyVolumeChanged", e);
         }
@@ -771,7 +771,10 @@
         }
 
         /**
-         * Override to handle requests to begin playback from a search query.
+         * Override to handle requests to begin playback from a search query. An
+         * empty query indicates that the app may play any music. The
+         * implementation should attempt to make a smart choice about what to
+         * play.
          */
         public void onPlayFromSearch(String query, Bundle extras) {
         }
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 58e46f0..b8cdc4b 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -41,6 +41,8 @@
 public class ITvInputSessionWrapper extends ITvInputSession.Stub implements HandlerCaller.Callback {
     private static final String TAG = "TvInputSessionWrapper";
 
+    private static final int MESSAGE_HANDLING_DURATION_THRESHOLD_MILLIS = 50;
+
     private static final int DO_RELEASE = 1;
     private static final int DO_SET_MAIN = 2;
     private static final int DO_SET_SURFACE = 3;
@@ -77,6 +79,7 @@
             return;
         }
 
+        long startTime = System.currentTimeMillis();
         switch (msg.what) {
             case DO_RELEASE: {
                 mTvInputSessionImpl.release();
@@ -89,71 +92,76 @@
                     mChannel.dispose();
                     mChannel = null;
                 }
-                return;
+                break;
             }
             case DO_SET_MAIN: {
                 mTvInputSessionImpl.setMain((Boolean) msg.obj);
-                return;
+                break;
             }
             case DO_SET_SURFACE: {
                 mTvInputSessionImpl.setSurface((Surface) msg.obj);
-                return;
+                break;
             }
             case DO_DISPATCH_SURFACE_CHANGED: {
                 SomeArgs args = (SomeArgs) msg.obj;
                 mTvInputSessionImpl.dispatchSurfaceChanged(args.argi1, args.argi2, args.argi3);
                 args.recycle();
-                return;
+                break;
             }
             case DO_SET_STREAM_VOLUME: {
                 mTvInputSessionImpl.setStreamVolume((Float) msg.obj);
-                return;
+                break;
             }
             case DO_TUNE: {
                 SomeArgs args = (SomeArgs) msg.obj;
                 mTvInputSessionImpl.tune((Uri) args.arg1, (Bundle) args.arg2);
                 args.recycle();
-                return;
+                break;
             }
             case DO_SET_CAPTION_ENABLED: {
                 mTvInputSessionImpl.setCaptionEnabled((Boolean) msg.obj);
-                return;
+                break;
             }
             case DO_SELECT_TRACK: {
                 SomeArgs args = (SomeArgs) msg.obj;
                 mTvInputSessionImpl.selectTrack((Integer) args.arg1, (String) args.arg2);
                 args.recycle();
-                return;
+                break;
             }
             case DO_APP_PRIVATE_COMMAND: {
                 SomeArgs args = (SomeArgs) msg.obj;
                 mTvInputSessionImpl.appPrivateCommand((String) args.arg1, (Bundle) args.arg2);
                 args.recycle();
-                return;
+                break;
             }
             case DO_CREATE_OVERLAY_VIEW: {
                 SomeArgs args = (SomeArgs) msg.obj;
                 mTvInputSessionImpl.createOverlayView((IBinder) args.arg1, (Rect) args.arg2);
                 args.recycle();
-                return;
+                break;
             }
             case DO_RELAYOUT_OVERLAY_VIEW: {
                 mTvInputSessionImpl.relayoutOverlayView((Rect) msg.obj);
-                return;
+                break;
             }
             case DO_REMOVE_OVERLAY_VIEW: {
                 mTvInputSessionImpl.removeOverlayView(true);
-                return;
+                break;
             }
             case DO_REQUEST_UNBLOCK_CONTENT: {
                 mTvInputSessionImpl.unblockContent((String) msg.obj);
-                return;
+                break;
             }
             default: {
                 Log.w(TAG, "Unhandled message code: " + msg.what);
-                return;
+                break;
             }
         }
+        long duration = System.currentTimeMillis() - startTime;
+        if (duration > MESSAGE_HANDLING_DURATION_THRESHOLD_MILLIS) {
+            Log.w(TAG, "Handling message (" + msg.what + ") took too long time (duration="
+                    + duration + "ms)");
+        }
     }
 
     @Override
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index d5bf38c..7d1c7c6 100644
--- a/media/java/android/media/tv/TvContentRating.java
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -44,45 +44,47 @@
  * {@literal
  * <rating-system-definitions xmlns:android="http://schemas.android.com/apk/res/android"
  *     android:versionCode="1">
- *     <!-- TV content rating system for US TV -->
  *     <rating-system-definition android:name="US_TV"
- *         android:title="US-TV"
- *         android:description="@string/description_ustv"
- *         android:country="US">
+ *         android:country="US"
+ *         android:description="@string/description_us_tv">
  *         <sub-rating-definition android:name="US_TV_D"
  *             android:title="D"
- *             android:description="@string/description_ustv_d" />
+ *             android:description="@string/description_us_tv_d" />
  *         <sub-rating-definition android:name="US_TV_L"
  *             android:title="L"
- *             android:description="@string/description_ustv_l" />
+ *             android:description="@string/description_us_tv_l" />
  *         <sub-rating-definition android:name="US_TV_S"
  *             android:title="S"
- *             android:description="@string/description_ustv_s" />
+ *             android:description="@string/description_us_tv_s" />
  *         <sub-rating-definition android:name="US_TV_V"
  *             android:title="V"
- *             android:description="@string/description_ustv_v" />
+ *             android:description="@string/description_us_tv_v" />
  *         <sub-rating-definition android:name="US_TV_FV"
  *             android:title="FV"
- *             android:description="@string/description_ustv_fv" />
+ *             android:description="@string/description_us_tv_fv" />
  *
  *         <rating-definition android:name="US_TV_Y"
  *             android:title="TV-Y"
- *             android:description="@string/description_ustv_y"
- *             android:ageHint="0" />
+ *             android:description="@string/description_us_tv_y"
+ *             android:icon="@drawable/icon_us_tv_y"
+ *             android:contentAgeHint="0" />
  *         <rating-definition android:name="US_TV_Y7"
  *             android:title="TV-Y7"
- *             android:description="@string/description_ustv_y7"
- *             android:ageHint="7">
+ *             android:description="@string/description_us_tv_y7"
+ *             android:icon="@drawable/icon_us_tv_y7"
+ *             android:contentAgeHint="7">
  *             <sub-rating android:name="US_TV_FV" />
  *         </rating-definition>
  *         <rating-definition android:name="US_TV_G"
  *             android:title="TV-G"
- *             android:description="@string/description_ustv_g"
- *             android:ageHint="0" />
+ *             android:description="@string/description_us_tv_g"
+ *             android:icon="@drawable/icon_us_tv_g"
+ *             android:contentAgeHint="0" />
  *         <rating-definition android:name="US_TV_PG"
  *             android:title="TV-PG"
- *             android:description="@string/description_ustv_pg"
- *             android:ageHint="14">
+ *             android:description="@string/description_us_tv_pg"
+ *             android:icon="@drawable/icon_us_tv_pg"
+ *             android:contentAgeHint="14">
  *             <sub-rating android:name="US_TV_D" />
  *             <sub-rating android:name="US_TV_L" />
  *             <sub-rating android:name="US_TV_S" />
@@ -90,8 +92,9 @@
  *         </rating-definition>
  *         <rating-definition android:name="US_TV_14"
  *             android:title="TV-14"
- *             android:description="@string/description_ustv_14"
- *             android:ageHint="14">
+ *             android:description="@string/description_us_tv_14"
+ *             android:icon="@drawable/icon_us_tv_14"
+ *             android:contentAgeHint="14">
  *             <sub-rating android:name="US_TV_D" />
  *             <sub-rating android:name="US_TV_L" />
  *             <sub-rating android:name="US_TV_S" />
@@ -99,8 +102,9 @@
  *         </rating-definition>
  *         <rating-definition android:name="US_TV_MA"
  *             android:title="TV-MA"
- *             android:description="@string/description_ustv_ma"
- *             android:ageHint="17">
+ *             android:description="@string/description_us_tv_ma"
+ *             android:icon="@drawable/icon_us_tv_ma"
+ *             android:contentAgeHint="17">
  *             <sub-rating android:name="US_TV_L" />
  *             <sub-rating android:name="US_TV_S" />
  *             <sub-rating android:name="US_TV_V" />
@@ -175,8 +179,12 @@
  *         <td>TV content rating system for Brazil</td>
  *     </tr>
  *     <tr>
- *         <td>CA_TV</td>
- *         <td>TV content rating system for Canada</td>
+ *         <td>CA_TV_CA</td>
+ *         <td>TV content rating system for Canada (Canadian)</td>
+ *     </tr>
+ *     <tr>
+ *         <td>CA_TV_QC</td>
+ *         <td>TV content rating system for Canada (Quebec)</td>
  *     </tr>
  *     <tr>
  *         <td>CH_TV</td>
@@ -503,42 +511,67 @@
  *         <td>Content suitable for viewers over the age of 18</td>
  *     </tr>
  *     <tr>
- *         <td valign="top" rowspan="7">CA_TV</td>
- *         <td>CA_TV_EXEMPT</td>
- *         <td>Shows which are exempt from ratings (such as news and sports programming) will not
- *         display an on-screen rating at all</td>
+ *         <td valign="top" rowspan="7">CA_TV_CA</td>
+ *         <td>CA_TV_CA_EXEMPT</td>
+ *         <td>Exempt from ratings and won't display an on-screen rating</td>
  *     </tr>
  *     <tr>
- *         <td>CA_TV_C</td>
- *         <td>Programming suitable for children ages of 2-7 years. No profanity or sexual content
- *         of any level allowed. Contains little violence</td>
+ *         <td>CA_TV_CA_C</td>
+ *         <td>Suitable for children ages 2-7. May contain mild violence</td>
  *     </tr>
  *     <tr>
- *         <td>CA_TV_C8</td>
- *         <td>Suitable for children ages 8+. Low level violence and fantasy horror is allowed. No
- *         foul language is allowed, but occasional "socially offensive and discriminatory" language
- *         is allowed if in the context of the story. No sexual content of any level allowed</td>
+ *         <td>CA_TV_CA_C8</td>
+ *         <td>Suitable for children ages 8 and older. May contain mild violence, fantasy horror,
+ *         and socially offensive language</td>
  *     </tr>
  *     <tr>
- *         <td>CA_TV_G</td>
- *         <td>Suitable for general audiences. Programming suitable for the entire family with mild
- *         violence, and mild profanity and/or censored language</td>
+ *         <td>CA_TV_CA_G</td>
+ *         <td>Suitable for the entire family and may contain mild violence, profanity, and censored
+ *         language</td>
  *     </tr>
  *     <tr>
- *         <td>CA_TV_PG</td>
- *         <td>Parental guidance. Moderate violence and moderate profanity is allowed, as is brief
- *         nudity and sexual references if important to the context of the story</td>
+ *         <td>CA_TV_CA_PG</td>
+ *         <td>May contain moderate violence, profanity, nudity, and sexual references</td>
  *     </tr>
  *     <tr>
- *         <td>CA_TV_14</td>
- *         <td>Programming intended for viewers ages 14 and older. May contain strong violence and
- *         strong profanity, and depictions of sexual activity as long as they are within the
- *         context of a story</td>
+ *         <td>CA_TV_CA_14</td>
+ *         <td>Intended for viewers ages 14 and older. May contain strong violence and profanity,
+ *         and depictions of sexual activity</td>
  *     </tr>
  *     <tr>
- *         <td>CA_TV_18</td>
- *         <td>Programming intended for viewers ages 18 and older. May contain explicit violence and
- *         sexual activity</td>
+ *         <td>CA_TV_CA_18</td>
+ *         <td>Intended for viewers ages 18 and older. May contain explicit violence and sexual
+ *         activity</td>
+ *     </tr>
+ *     <tr>
+ *         <td valign="top" rowspan="6">CA_TV_QC</td>
+ *         <td>CA_TV_QC_E</td>
+ *         <td>Exempt from ratings and won't display an on-screen rating</td>
+ *     </tr>
+ *     <tr>
+ *         <td>CA_TV_QC_G</td>
+ *         <td>Appropriate for all ages and must contain little or no violence and little to no
+ *         sexual content</td>
+ *     </tr>
+ *     <tr>
+ *         <td>CA_TV_QC_8</td>
+ *         <td>Appropriate for children 8 and may contain with little violence, language, and little
+ *         to no sexual situations</td>
+ *     </tr>
+ *     <tr>
+ *         <td>CA_TV_QC_13</td>
+ *         <td>Suitable for children 13 and may contain with moderate violence, language, and some
+ *         sexual situations</td>
+ *     </tr>
+ *     <tr>
+ *         <td>CA_TV_QC_16</td>
+ *         <td>Recommended for children over the age of 16 and may contain with strong violence,
+ *         strong language, and strong sexual content</td>
+ *     </tr>
+ *     <tr>
+ *         <td>CA_TV_QC_18</td>
+ *         <td>Only to be viewed by adults and may contain extreme violence and graphic sexual
+ *         content. It is mostly used for 18+ movies and pornography</td>
  *     </tr>
  *     <tr>
  *         <td valign="top" rowspan="2">CH_TV</td>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index b08fdab..36bb72f 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -17,10 +17,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="2783841764617238354">"Dokumenty"</string>
-    <string name="title_open" msgid="4353228937663917801">"Otevřít z"</string>
+    <string name="title_open" msgid="4353228937663917801">"Otevřít"</string>
     <string name="title_save" msgid="2433679664882857999">"Uložit do"</string>
     <string name="menu_create_dir" msgid="5947289605844398389">"Vytvořit složku"</string>
-    <string name="menu_grid" msgid="6878021334497835259">"Mřížka"</string>
+    <string name="menu_grid" msgid="6878021334497835259">"Mřížkové zobrazení"</string>
     <string name="menu_list" msgid="7279285939892417279">"Seznam"</string>
     <string name="menu_sort" msgid="7677740407158414452">"Řadit podle"</string>
     <string name="menu_search" msgid="3816712084502856974">"Hledat"</string>
@@ -34,7 +34,7 @@
     <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>
     <string name="menu_advanced_hide" product="default" msgid="4845869969015718848">"Skrýt SD kartu"</string>
-    <string name="menu_file_size_show" msgid="3240323619260823076">"Zobr. velikost souboru"</string>
+    <string name="menu_file_size_show" msgid="3240323619260823076">"Zobrazit velikost souboru"</string>
     <string name="menu_file_size_hide" msgid="8881975928502581042">"Skrýt velikost souboru"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Vybráno: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Podle názvu"</string>
diff --git a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
index 78b5746..a083f89 100644
--- a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
+++ b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
@@ -40,39 +40,19 @@
         android:visibility="gone"
         androidprv:allCaps="@bool/kg_use_all_caps" />
 
-    <LinearLayout
-        android:layout_width="match_parent"
+    <com.android.keyguard.EmergencyButton
+        android:id="@+id/emergency_call_button"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_weight="1"
         android:layout_marginTop="@dimen/eca_overlap"
-        style="?android:attr/buttonBarStyle"
-        android:orientation="horizontal"
-        android:gravity="center"
-        android:weightSum="2">
-
-        <com.android.keyguard.EmergencyButton
-            android:id="@+id/emergency_call_button"
-            android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:drawableLeft="@drawable/lockscreen_emergency_button"
-            android:text="@string/kg_emergency_call_label"
-            style="?android:attr/buttonBarButtonStyle"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textSize="@dimen/kg_status_line_font_size"
-            android:textColor="?android:attr/textColorSecondary"
-            android:drawablePadding="8dip" 
-            android:textAllCaps="@bool/kg_use_all_caps" />
-
-        <Button android:id="@+id/forgot_password_button"
-            android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            style="?android:attr/buttonBarButtonStyle"
-            android:textSize="@dimen/kg_status_line_font_size"
-            android:textColor="?android:attr/textColorSecondary"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:visibility="gone"
-            android:textAllCaps="@bool/kg_use_all_caps" />
-    </LinearLayout>
+        android:drawableLeft="@drawable/lockscreen_emergency_button"
+        android:text="@string/kg_emergency_call_label"
+        style="?android:attr/buttonBarButtonStyle"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="@dimen/kg_status_line_font_size"
+        android:textColor="?android:attr/textColorSecondary"
+        android:drawablePadding="8dip"
+        android:textAllCaps="@bool/kg_use_all_caps" />
 
 </com.android.keyguard.EmergencyCarrierArea>
diff --git a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area_empty.xml b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area_empty.xml
deleted file mode 100644
index 2f4adae..0000000
--- a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area_empty.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** 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.
-*/
--->
-
-<!-- This is a blank layout to simplify implementation on landscape on phones
-     it is referenced indirectly by keyguard_eca -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="0dip"
-    android:layout_height="0dip"
-    android:orientation="vertical"
-    android:gravity="center"
-    android:layout_gravity="center_horizontal"
-    android:layout_alignParentBottom="true">
-
-</LinearLayout>
diff --git a/packages/Keyguard/res/values-land/alias.xml b/packages/Keyguard/res/values-land/alias.xml
deleted file mode 100644
index 7aac5b4..0000000
--- a/packages/Keyguard/res/values-land/alias.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/colors.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.
-*/
--->
-<resources>
-    <!-- Alias used to reference one of two possible layouts in keyguard.  -->
-    <item type="layout" name="keyguard_eca">@layout/keyguard_emergency_carrier_area_empty</item>
-</resources>
diff --git a/packages/Keyguard/res/values-port/alias.xml b/packages/Keyguard/res/values-port/alias.xml
deleted file mode 100644
index c3ecbb9..0000000
--- a/packages/Keyguard/res/values-port/alias.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/colors.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.
-*/
--->
-<resources>
-    <!-- Alias used to reference one of two possible layouts in keyguard.  -->
-    <item type="layout" name="keyguard_eca">@layout/keyguard_emergency_carrier_area</item>
-</resources>
diff --git a/packages/Keyguard/res/values-ta-rIN/strings.xml b/packages/Keyguard/res/values-ta-rIN/strings.xml
index e4b81db..b763457 100644
--- a/packages/Keyguard/res/values-ta-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ta-rIN/strings.xml
@@ -21,14 +21,14 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="719438068451601849">"விசைப்பாதுகாப்பு"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN குறியீட்டை உள்ளிடவும்"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"SIM PUK மற்றும் புதிய PIN குறியீட்டைத் தட்டச்சு செய்யவும்"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK குறியீடு"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="3201151840570492538">"புதிய SIM PIN குறியீடு"</string>
+    <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"பின் குறியீட்டை உள்ளிடவும்"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"சிம் PUK மற்றும் புதிய பின் குறியீட்டைத் தட்டச்சு செய்யவும்"</string>
+    <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"சிம் PUK குறியீடு"</string>
+    <string name="keyguard_password_enter_pin_prompt" msgid="3201151840570492538">"புதிய சிம் பின் குறியீடு"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"கடவுச்சொல்லை உள்ளிட, தொடவும்"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"திறக்க, கடவுச்சொல்லை உள்ளிடவும்"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"திறக்க, PIN ஐ உள்ளிடவும்"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"தவறான PIN குறியீடு."</string>
+    <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"திறக்க, பின்னை உள்ளிடவும்"</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"தவறான பின் குறியீடு."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"தடைநீக்க, மெனுவை அழுத்தி பின்பு 0 ஐ அழுத்தவும்."</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"முகம் திறப்பதற்கான அதிகபட்ச முயற்சிகள் கடந்தன"</string>
     <string name="keyguard_charged" msgid="3272223906073492454">"சார்ஜ் செய்யப்பட்டது"</string>
@@ -36,16 +36,16 @@
     <string name="keyguard_low_battery" msgid="8143808018719173859">"உங்கள் சார்ஜரை இணைக்கவும்."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"திறக்க, மெனுவை அழுத்தவும்."</string>
     <string name="keyguard_network_locked_message" msgid="9169717779058037168">"பிணையம் பூட்டப்பட்டது"</string>
-    <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"SIM கார்டு இல்லை"</string>
-    <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"டேப்லெட்டில் SIM கார்டு இல்லை."</string>
-    <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"தொலைபேசியில் SIM கார்டு இல்லை."</string>
-    <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"SIM கார்டைச் செருகவும்."</string>
-    <string name="keyguard_missing_sim_instructions_long" msgid="5968985489463870358">"SIM கார்டு இல்லை அல்லது படிக்கக்கூடியதாக இல்லை. SIM கார்டைச் செருகவும்."</string>
-    <string name="keyguard_permanent_disabled_sim_message_short" msgid="8340813989586622356">"SIM கார்டைப் பயன்படுத்த முடியாது."</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="5892940909699723544">"உங்கள் SIM கார்டு நிரந்தரமாக முடக்கப்பட்டது.\n மற்றொரு SIM கார்டிற்காக உங்கள் வயர்லெஸ் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string>
-    <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM கார்டு பூட்டப்பட்டுள்ளது."</string>
-    <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM கார்டு PUK ஆல் பூட்டப்பட்டது."</string>
-    <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM கார்டின் தடையைநீக்குகிறது..."</string>
+    <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"சிம் கார்டு இல்லை"</string>
+    <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"டேப்லெட்டில் சிம் கார்டு இல்லை."</string>
+    <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"தொலைபேசியில் சிம் கார்டு இல்லை."</string>
+    <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"சிம் கார்டைச் செருகவும்."</string>
+    <string name="keyguard_missing_sim_instructions_long" msgid="5968985489463870358">"சிம் கார்டு இல்லை அல்லது படிக்கக்கூடியதாக இல்லை. சிம் கார்டைச் செருகவும்."</string>
+    <string name="keyguard_permanent_disabled_sim_message_short" msgid="8340813989586622356">"சிம் கார்டைப் பயன்படுத்த முடியாது."</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="5892940909699723544">"உங்கள் சிம் கார்டு நிரந்தரமாக முடக்கப்பட்டது.\n மற்றொரு சிம் கார்டிற்காக உங்கள் வயர்லெஸ் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string>
+    <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"சிம் கார்டு பூட்டப்பட்டுள்ளது."</string>
+    <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"சிம் கார்டு PUK ஆல் பூட்டப்பட்டது."</string>
+    <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"சிம் கார்டின் தடையைநீக்குகிறது..."</string>
     <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. விட்ஜெட் %2$d / %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"விட்ஜெட்டைச் சேர்க்கவும்."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"காலியானது"</string>
@@ -103,20 +103,20 @@
     <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"வடிவத்தை மறந்துவிட்டீர்களா"</string>
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"தவறான வடிவம்"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"தவறான கடவுச்சொல்"</string>
-    <string name="kg_wrong_pin" msgid="1131306510833563801">"தவறான PIN"</string>
+    <string name="kg_wrong_pin" msgid="1131306510833563801">"தவறான பின்"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"உங்கள் வடிவத்தை வரையவும்"</string>
-    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PIN ஐ உள்ளிடவும்"</string>
-    <string name="kg_pin_instructions" msgid="2377242233495111557">"PIN ஐ உள்ளிடுக"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"சிம் பின்னை உள்ளிடவும்"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"பின்னை உள்ளிடுக"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"கடவுச்சொல்லை உள்ளிடவும்"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு மொபைல் நிறுவனங்களைத் தொடர்புகொள்ளவும்."</string>
-    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"விரும்பிய PIN குறியீட்டை உள்ளிடவும்"</string>
-    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"விரும்பிய PIN குறியீட்டை உறுதிப்படுத்தவும்"</string>
-    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM கார்டின் தடையைநீக்குகிறது..."</string>
-    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 இலிருந்து 8 எண்கள் வரையுள்ள PIN ஐ உள்ளிடவும்."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு மொபைல் நிறுவனங்களைத் தொடர்புகொள்ளவும்."</string>
+    <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"விரும்பிய பின் குறியீட்டை உள்ளிடவும்"</string>
+    <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"விரும்பிய பின் குறியீட்டை உறுதிப்படுத்தவும்"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"சிம் கார்டின் தடையைநீக்குகிறது..."</string>
+    <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 இலிருந்து 8 எண்கள் வரையுள்ள பின்னை உள்ளிடவும்."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK குறியீட்டில் 8 எண்கள் அல்லது அதற்கு மேல் இருக்க வேண்டும்."</string>
-    <string name="kg_invalid_puk" msgid="3638289409676051243">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் SIM ஐ நிரந்தரமாக முடக்கிவிடும்."</string>
-    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN குறியீடுகள் பொருந்தவில்லை"</string>
+    <string name="kg_invalid_puk" msgid="3638289409676051243">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் சிம் ஐ நிரந்தரமாக முடக்கிவிடும்."</string>
+    <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"பின் குறியீடுகள் பொருந்தவில்லை"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"அதிகமான வடிவ முயற்சிகள்"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"திறக்க, உங்கள் Google கணக்கு மூலம் உள்நுழையவும்."</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"பயனர்பெயர் (மின்னஞ்சல்)"</string>
@@ -125,7 +125,7 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"தவறான பயனர்பெயர் அல்லது கடவுச்சொல்."</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"உங்கள் பயனர்பெயர் அல்லது கடவுச்சொல்லை மறந்துவிட்டீர்களா?\n"<b>"google.com/accounts/recovery"</b>" ஐப் பார்வையிடவும்."</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"கணக்கைச் சரிபார்க்கிறது…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"உங்கள் PIN ஐ <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகளில் மீண்டும் முயற்சிக்கவும்."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"டேப்லெட்டைத் திறக்க <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக முயற்சித்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, டேப்லெட்டானது ஆரம்பநிலைக்கு மீட்டமைக்கப்பட்டு, எல்லா பயனர் தரவையும் இழப்பீர்கள்."</string>
@@ -136,18 +136,18 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். மேலும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, மின்னஞ்சல் கணக்கைப் பயன்படுத்தி உங்கள் மொபைலைத் திறக்கக் கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"அகற்று"</string>
-    <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM PIN குறியீடு தவறானது, உங்கள் சாதனத்தின் தடையை நீக்க, உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ள வேண்டும்."</string>
+    <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"சிம் பின் குறியீடு தவறானது, உங்கள் சாதனத்தின் தடையை நீக்க, உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ள வேண்டும்."</string>
   <plurals name="kg_password_wrong_pin_code">
-    <item quantity="one" msgid="8134313997799638254">"SIM PIN குறியீடு தவறானது, உங்கள் சாதனத்தைத் திறக்க, உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளும் முன், மேலும் <xliff:g id="NUMBER">%d</xliff:g> முறை முயர்ச்சிக்கலாம்."</item>
-    <item quantity="other" msgid="2215723361575359486">"SIM PIN குறியீடு தவறானது, மேலும் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
+    <item quantity="one" msgid="8134313997799638254">"சிம் பின் குறியீடு தவறானது, உங்கள் சாதனத்தைத் திறக்க, உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளும் முன், மேலும் <xliff:g id="NUMBER">%d</xliff:g> முறை முயர்ச்சிக்கலாம்."</item>
+    <item quantity="other" msgid="2215723361575359486">"சிம் பின் குறியீடு தவறானது, மேலும் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
   </plurals>
-    <string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM பயன்பாட்டிற்கு உகந்தது அல்ல. உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
+    <string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"சிம் பயன்பாட்டிற்கு உகந்தது அல்ல. உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
   <plurals name="kg_password_wrong_puk_code">
-    <item quantity="one" msgid="3256893607561060649">"SIM PUK குறியீடு தவறானது, சிம் நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயர்ச்சிக்கலாம்."</item>
-    <item quantity="other" msgid="5477305226026342036">"SIM PUK குறியீடு தவறானது, SIM நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
+    <item quantity="one" msgid="3256893607561060649">"சிம் PUK குறியீடு தவறானது, சிம் நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயர்ச்சிக்கலாம்."</item>
+    <item quantity="other" msgid="5477305226026342036">"சிம் PUK குறியீடு தவறானது, சிம் நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
   </plurals>
-    <string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN செயல்பாடு தோல்வி!"</string>
-    <string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK செயல்பாடு தோல்வி!"</string>
+    <string name="kg_password_pin_failed" msgid="6268288093558031564">"சிம் பின் செயல்பாடு தோல்வி!"</string>
+    <string name="kg_password_puk_failed" msgid="2838824369502455984">"சிம் PUK செயல்பாடு தோல்வி!"</string>
     <string name="kg_pin_accepted" msgid="1448241673570020097">"குறியீடு ஏற்கப்பட்டது!"</string>
     <string name="keyguard_transport_prev_description" msgid="8229108430245669854">"முந்தைய டிராக்கிற்கான பொத்தான்"</string>
     <string name="keyguard_transport_next_description" msgid="4299258300283778305">"அடுத்த டிராக்கிற்கான பொத்தான்"</string>
diff --git a/packages/Keyguard/res/values/alias.xml b/packages/Keyguard/res/values/alias.xml
index e6657a1..09e9591 100644
--- a/packages/Keyguard/res/values/alias.xml
+++ b/packages/Keyguard/res/values/alias.xml
@@ -49,4 +49,6 @@
     <!-- Alias used to reference framework activity duration.  -->
     <item type="integer" name="config_activityDefaultDur">@*android:integer/config_activityDefaultDur</item>
 
+    <!-- Alias used to reference one of two possible layouts in keyguard.  -->
+    <item type="layout" name="keyguard_eca">@layout/keyguard_emergency_carrier_area</item>
 </resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 73b11f3..e0507a8 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -99,8 +99,7 @@
         // TODO: implement a shorter timeout once new PowerManager API is ready.
         // should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT)
         mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
-        if (TelephonyManager.getDefault().getCallState()
-                == TelephonyManager.CALL_STATE_OFFHOOK) {
+        if (mLockPatternUtils.isInCall()) {
             mLockPatternUtils.resumeCall();
         } else {
             final boolean bypassHandler = true;
@@ -115,7 +114,7 @@
 
     private void updateEmergencyCallButton(State simState, int phoneState) {
         boolean enabled = false;
-        if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
+        if (mLockPatternUtils.isInCall()) {
             enabled = true; // always show "return to call" if phone is off-hook
         } else if (mLockPatternUtils.isEmergencyCallCapable()) {
             boolean simLocked = KeyguardUpdateMonitor.getInstance(mContext).isSimLocked();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 65c4ce2..0e01a27 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -15,38 +15,27 @@
  */
 package com.android.keyguard;
 
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerCallback;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.os.Bundle;
 import android.os.CountDownTimer;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
-import android.widget.Button;
 import android.widget.LinearLayout;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternView;
 
-import java.io.IOException;
 import java.util.List;
 
 public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView,
@@ -70,9 +59,7 @@
     private CountDownTimer mCountdownTimer = null;
     private LockPatternUtils mLockPatternUtils;
     private LockPatternView mLockPatternView;
-    private Button mForgotPatternButton;
     private KeyguardSecurityCallback mCallback;
-    private boolean mEnableFallback;
 
     /**
      * Keeps track of the last time we poked the wake lock during dispatching of the touch event.
@@ -144,20 +131,8 @@
         // vibrate mode will be the same for the life of this screen
         mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
 
-        mForgotPatternButton = (Button) findViewById(R.id.forgot_password_button);
-        // note: some configurations don't have an emergency call area
-        if (mForgotPatternButton != null) {
-            mForgotPatternButton.setText(R.string.kg_forgot_pattern_button_text);
-            mForgotPatternButton.setOnClickListener(new OnClickListener() {
-                public void onClick(View v) {
-                    mCallback.showBackupSecurity();
-                }
-            });
-        }
-
         setFocusableInTouchMode(true);
 
-        maybeEnableFallback(mContext);
         mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
         mEcaView = findViewById(R.id.keyguard_selector_fade_container);
         View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
@@ -169,24 +144,6 @@
         mHelpMessage = (KeyguardMessageArea) findViewById(R.id.keyguard_message_area);
     }
 
-    private void updateFooter(FooterMode mode) {
-        if (mForgotPatternButton == null) return; // no ECA? no footer
-
-        switch (mode) {
-            case Normal:
-                if (DEBUG) Log.d(TAG, "mode normal");
-                mForgotPatternButton.setVisibility(View.GONE);
-                break;
-            case ForgotLockPattern:
-                if (DEBUG) Log.d(TAG, "mode ForgotLockPattern");
-                mForgotPatternButton.setVisibility(View.VISIBLE);
-                break;
-            case VerifyUnlocked:
-                if (DEBUG) Log.d(TAG, "mode VerifyUnlocked");
-                mForgotPatternButton.setVisibility(View.GONE);
-        }
-    }
-
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         boolean result = super.onTouchEvent(ev);
@@ -217,18 +174,6 @@
         } else {
             displayDefaultSecurityMessage();
         }
-
-        // the footer depends on how many total attempts the user has failed
-        if (mCallback.isVerifyUnlockOnly()) {
-            updateFooter(FooterMode.VerifyUnlocked);
-        } else if (mEnableFallback &&
-                (mKeyguardUpdateMonitor.getFailedUnlockAttempts()
-                        >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
-            updateFooter(FooterMode.ForgotLockPattern);
-        } else {
-            updateFooter(FooterMode.Normal);
-        }
-
     }
 
     private void displayDefaultSecurityMessage() {
@@ -291,68 +236,10 @@
         }
     }
 
-    private void maybeEnableFallback(Context context) {
-        // Ask the account manager if we have an account that can be used as a
-        // fallback in case the user forgets his pattern.
-        AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context));
-        accountAnalyzer.start();
-    }
-
-    private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
-        private final AccountManager mAccountManager;
-        private final Account[] mAccounts;
-        private int mAccountIndex;
-
-        private AccountAnalyzer(AccountManager accountManager) {
-            mAccountManager = accountManager;
-            mAccounts = accountManager.getAccountsByTypeAsUser("com.google",
-                    new UserHandle(mLockPatternUtils.getCurrentUser()));
-        }
-
-        private void next() {
-            // if we are ready to enable the fallback or if we depleted the list of accounts
-            // then finish and get out
-            if (mEnableFallback || mAccountIndex >= mAccounts.length) {
-                return;
-            }
-
-            // lookup the confirmCredentials intent for the current account
-            mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this,
-                    null, new UserHandle(mLockPatternUtils.getCurrentUser()));
-        }
-
-        public void start() {
-            mEnableFallback = false;
-            mAccountIndex = 0;
-            next();
-        }
-
-        public void run(AccountManagerFuture<Bundle> future) {
-            try {
-                Bundle result = future.getResult();
-                if (result.getParcelable(AccountManager.KEY_INTENT) != null) {
-                    mEnableFallback = true;
-                }
-            } catch (OperationCanceledException e) {
-                // just skip the account if we are unable to query it
-            } catch (IOException e) {
-                // just skip the account if we are unable to query it
-            } catch (AuthenticatorException e) {
-                // just skip the account if we are unable to query it
-            } finally {
-                mAccountIndex++;
-                next();
-            }
-        }
-    }
-
     private void handleAttemptLockout(long elapsedRealtimeDeadline) {
         mLockPatternView.clearPattern();
         mLockPatternView.setEnabled(false);
         final long elapsedRealtime = SystemClock.elapsedRealtime();
-        if (mEnableFallback) {
-            updateFooter(FooterMode.ForgotLockPattern);
-        }
 
         mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
 
@@ -367,12 +254,6 @@
             public void onFinish() {
                 mLockPatternView.setEnabled(true);
                 displayDefaultSecurityMessage();
-                // TODO mUnlockIcon.setVisibility(View.VISIBLE);
-                if (mEnableFallback) {
-                    updateFooter(FooterMode.ForgotLockPattern);
-                } else {
-                    updateFooter(FooterMode.Normal);
-                }
             }
 
         }.start();
@@ -489,13 +370,6 @@
             // Also animate the Emergency call
             mAppearAnimationUtils.createAnimation(mEcaView, delay, duration, startTranslationY,
             interpolator, null);
-
-            // And the forgot pattern button
-            if (mForgotPatternButton != null
-                    && mForgotPatternButton.getVisibility() == View.VISIBLE) {
-                mAppearAnimationUtils.createAnimation(mForgotPatternButton, delay, duration,
-                        startTranslationY, interpolator, null);
-            }
         }
         animator.start();
         mLockPatternView.invalidate();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index a0fab42..8898f9e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -128,16 +128,19 @@
                 getResources().getDimensionPixelSize(R.dimen.widget_label_font_size));
     }
 
-    protected void refresh() {
-        AlarmManager.AlarmClockInfo nextAlarm = mLockPatternUtils.getNextAlarm();
-        Patterns.update(mContext, nextAlarm != null);
-
+    public void refreshTime() {
         mDateView.setFormat24Hour(Patterns.dateView);
         mDateView.setFormat12Hour(Patterns.dateView);
 
         mClockView.setFormat12Hour(Patterns.clockView12);
         mClockView.setFormat24Hour(Patterns.clockView24);
+    }
 
+    private void refresh() {
+        AlarmManager.AlarmClockInfo nextAlarm = mLockPatternUtils.getNextAlarm();
+        Patterns.update(mContext, nextAlarm != null);
+
+        refreshTime();
         refreshAlarmStatus(nextAlarm);
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2da3b27..1c6dc2c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -648,7 +648,7 @@
                         @Override
                         public void onUserSwitchComplete(int newUserId) throws RemoteException {
                             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
-                                    newUserId));
+                                    newUserId, 0));
                             mSwitchingUser = false;
                         }
                     });
diff --git a/packages/PrintSpooler/Android.mk b/packages/PrintSpooler/Android.mk
index 3fbd4d8..c4a55d1 100644
--- a/packages/PrintSpooler/Android.mk
+++ b/packages/PrintSpooler/Android.mk
@@ -19,9 +19,13 @@
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES += src/com/android/printspooler/renderer/IPdfRenderer.aidl
 
 LOCAL_PACKAGE_NAME := PrintSpooler
 
+LOCAL_JNI_SHARED_LIBRARIES := libprintspooler_jni
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 android-support-v7-recyclerview
 
 include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
\ No newline at end of file
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 540a2f3..9efda2f 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -53,6 +53,11 @@
             android:permission="android.permission.BIND_PRINT_SPOOLER_SERVICE">
         </service>
 
+        <service
+            android:name=".renderer.PdfRendererService"
+            android:isolatedProcess="true">
+        </service>
+
         <activity
             android:name=".ui.PrintActivity"
             android:configChanges="orientation|screenSize"
diff --git a/packages/PrintSpooler/jni/Android.mk b/packages/PrintSpooler/jni/Android.mk
new file mode 100644
index 0000000..fe7d06b
--- /dev/null
+++ b/packages/PrintSpooler/jni/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    com_android_printspooler_util_BitmapSerializeUtils.cpp \
+
+LOCAL_C_INCLUDES += \
+    $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := \
+    libnativehelper \
+    libjnigraphics \
+    liblog
+
+LOCAL_MODULE := libprintspooler_jni
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp b/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
new file mode 100644
index 0000000..57281c8
--- /dev/null
+++ b/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BitmapSerializeUtils"
+
+#include <jni.h>
+#include <JNIHelp.h>
+
+#include <android/bitmap.h>
+#include <android/log.h>
+
+namespace android {
+
+#define RGBA_8888_COLOR_DEPTH 4
+
+static bool writeAllBytes(const int fd, void* buffer, const size_t byteCount) {
+    char* writeBuffer = static_cast<char*>(buffer);
+    size_t remainingBytes = byteCount;
+    while (remainingBytes > 0) {
+        ssize_t writtenByteCount = write(fd, writeBuffer, remainingBytes);
+        if (writtenByteCount == -1) {
+            if (errno == EINTR) {
+                continue;
+            }
+            __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Error writing to buffer: %d", errno);
+            return false;
+        }
+        remainingBytes -= writtenByteCount;
+        writeBuffer += writtenByteCount;
+    }
+    return true;
+}
+
+static bool readAllBytes(const int fd, void* buffer, const size_t byteCount) {
+    char* readBuffer = static_cast<char*>(buffer);
+    size_t remainingBytes = byteCount;
+    while (remainingBytes > 0) {
+        ssize_t readByteCount = read(fd, readBuffer, remainingBytes);
+        if (readByteCount == -1) {
+            if (errno == EINTR) {
+                continue;
+            }
+            __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Error reading from buffer: %d", errno);
+            return false;
+        }
+        remainingBytes -= readByteCount;
+        readBuffer += readByteCount;
+    }
+    return true;
+}
+
+static void throwException(JNIEnv* env, const char* className, const char* message) {
+    jclass exceptionClass = env->FindClass(className);
+    env->ThrowNew(exceptionClass, message);
+}
+
+static void throwIllegalStateException(JNIEnv* env, char *message) {
+    const char* className = "java/lang/IllegalStateException";
+    throwException(env, className, message);
+}
+
+static void throwIllegalArgumentException(JNIEnv* env, char* message) {
+    const char* className = "java/lang/IllegalArgumentException";
+    throwException(env, className, message);
+}
+
+static void readBitmapPixels(JNIEnv* env, jclass clazz, jobject jbitmap, jint fd) {
+    // Read the info.
+    AndroidBitmapInfo readInfo;
+    bool read = readAllBytes(fd, (void*) &readInfo, sizeof(AndroidBitmapInfo));
+    if (!read) {
+        throwIllegalStateException(env, (char*) "Cannot read bitmap info");
+        return;
+    }
+
+    // Get the info of the target bitmap.
+    AndroidBitmapInfo targetInfo;
+    int result = AndroidBitmap_getInfo(env, jbitmap, &targetInfo);
+    if (result < 0) {
+        throwIllegalStateException(env, (char*) "Cannot get bitmap info");
+        return;
+    }
+
+    // Enforce we can reuse the bitmap.
+    if (readInfo.width != targetInfo.width || readInfo.height != targetInfo.height
+            || readInfo.stride != targetInfo.stride || readInfo.format != targetInfo.format
+            || readInfo.flags != targetInfo.flags) {
+        throwIllegalArgumentException(env, (char*) "Cannot reuse bitmap");
+        return;
+    }
+
+    // Lock the pixels.
+    void* pixels;
+    result = AndroidBitmap_lockPixels(env, jbitmap, &pixels);
+    if (result < 0) {
+        throwIllegalStateException(env, (char*) "Cannot lock bitmap pixels");
+        return;
+    }
+
+    // Read the pixels.
+    size_t byteCount = readInfo.stride * readInfo.height;
+    read = readAllBytes(fd, (void*) pixels, byteCount);
+    if (!read) {
+        throwIllegalStateException(env, (char*) "Cannot read bitmap pixels");
+        return;
+    }
+
+    // Unlock the pixels.
+    result = AndroidBitmap_unlockPixels(env, jbitmap);
+    if (result < 0) {
+        throwIllegalStateException(env, (char*) "Cannot unlock bitmap pixels");
+    }
+}
+
+static void writeBitmapPixels(JNIEnv* env, jclass clazz, jobject jbitmap, jint fd) {
+    // Get the info.
+    AndroidBitmapInfo info;
+    int result = AndroidBitmap_getInfo(env, jbitmap, &info);
+    if (result < 0) {
+        throwIllegalStateException(env, (char*) "Cannot get bitmap info");
+        return;
+    }
+
+    // Write the info.
+    bool written = writeAllBytes(fd, (void*) &info, sizeof(AndroidBitmapInfo));
+    if (!written) {
+        throwIllegalStateException(env, (char*) "Cannot write bitmap info");
+        return;
+    }
+
+    // Lock the pixels.
+    void* pixels;
+    result = AndroidBitmap_lockPixels(env, jbitmap, &pixels);
+    if (result < 0) {
+        throwIllegalStateException(env, (char*) "Cannot lock bitmap pixels");
+        return;
+    }
+
+    // Write the pixels.
+    size_t byteCount = info.stride * info.height;
+    written = writeAllBytes(fd, (void*) pixels, byteCount);
+    if (!written) {
+        throwIllegalStateException(env, (char*) "Cannot write bitmap pixels");
+        return;
+    }
+
+    // Unlock the pixels.
+    result = AndroidBitmap_unlockPixels(env, jbitmap);
+    if (result < 0) {
+        throwIllegalStateException(env, (char*) "Cannot unlock bitmap pixels");
+    }
+}
+
+static JNINativeMethod sMethods[] = {
+    {"nativeReadBitmapPixels", "(Landroid/graphics/Bitmap;I)V", (void *) readBitmapPixels},
+    {"nativeWriteBitmapPixels", "(Landroid/graphics/Bitmap;I)V", (void *) writeBitmapPixels},
+};
+
+int register_com_android_printspooler_util_BitmapSerializeUtils(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "com/android/printspooler/util/BitmapSerializeUtils",
+        sMethods, NELEM(sMethods));
+}
+
+}
+
+jint JNI_OnLoad(JavaVM* jvm, void*) {
+    JNIEnv *env = NULL;
+    if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6)) {
+        return JNI_ERR;
+    }
+
+    if (android::register_com_android_printspooler_util_BitmapSerializeUtils(env) == -1) {
+        return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_6;
+}
diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml
index 761d58a..30b9629 100644
--- a/packages/PrintSpooler/res/layout/print_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_activity.xml
@@ -33,7 +33,7 @@
 
         <Spinner
             android:id="@+id/destination_spinner"
-            android:layout_width="wrap_content"
+            android:layout_width="@dimen/preview_destination_spinner_width"
             android:layout_height="wrap_content"
             android:layout_marginTop="4dip"
             android:dropDownWidth="wrap_content"
diff --git a/packages/PrintSpooler/res/values-sw600dp-land/constants.xml b/packages/PrintSpooler/res/values-sw600dp-land/constants.xml
index f60d8e4..f7f8a18 100644
--- a/packages/PrintSpooler/res/values-sw600dp-land/constants.xml
+++ b/packages/PrintSpooler/res/values-sw600dp-land/constants.xml
@@ -17,6 +17,9 @@
 <resources>
 
     <integer name="print_option_column_count">6</integer>
+
     <integer name="preview_page_per_row_count">4</integer>
 
+    <dimen name="preview_destination_spinner_width">256dip</dimen>
+
 </resources>
diff --git a/packages/PrintSpooler/res/values/constants.xml b/packages/PrintSpooler/res/values/constants.xml
index b4e4777..357d3e1 100644
--- a/packages/PrintSpooler/res/values/constants.xml
+++ b/packages/PrintSpooler/res/values/constants.xml
@@ -45,4 +45,6 @@
     <dimen name="preview_page_footer_height">32dip</dimen>
     <dimen name="preview_page_min_width">128dip</dimen>
 
+    <dimen name="preview_destination_spinner_width">192dip</dimen>
+
 </resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index c3ddad9..a581e8a 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -17,23 +17,30 @@
 package com.android.printspooler.model;
 
 import android.app.ActivityManager;
+import android.content.ComponentName;
 import android.content.Context;
-import android.content.res.Configuration;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.graphics.Bitmap;
 import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
-import android.graphics.pdf.PdfRenderer;
 import android.os.AsyncTask;
+import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.print.PrintAttributes;
 import android.print.PrintAttributes.MediaSize;
 import android.print.PrintAttributes.Margins;
 import android.print.PrintDocumentInfo;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.View;
+import com.android.internal.annotations.GuardedBy;
+import com.android.printspooler.renderer.IPdfRenderer;
+import com.android.printspooler.renderer.PdfRendererService;
+import com.android.printspooler.util.BitmapSerializeUtils;
 import dalvik.system.CloseGuard;
+import libcore.io.IoUtils;
 
 import java.io.IOException;
 import java.util.Iterator;
@@ -55,9 +62,6 @@
 
     private static final int BYTES_PER_MEGABYTE = 1048576;
 
-    private static final int MILS_PER_INCH = 1000;
-    private static final int POINTS_IN_INCH = 72;
-
     private final CloseGuard mCloseGuard = CloseGuard.get();
 
     private final ArrayMap<Integer, PageContentProvider> mPageContentProviders =
@@ -115,7 +119,6 @@
         if (DEBUG) {
             Log.i(LOG_TAG, "STATE_DESTROYED");
         }
-        throwIfNotClosed();
         doDestroy();
     }
 
@@ -351,15 +354,14 @@
     public static final class RenderSpec {
         final int bitmapWidth;
         final int bitmapHeight;
-        final MediaSize mediaSize;
-        final Margins minMargins;
+        final PrintAttributes printAttributes = new PrintAttributes.Builder().build();
 
         public RenderSpec(int bitmapWidth, int bitmapHeight,
                 MediaSize mediaSize, Margins minMargins) {
             this.bitmapWidth = bitmapWidth;
             this.bitmapHeight = bitmapHeight;
-            this.mediaSize = mediaSize;
-            this.minMargins = minMargins;
+            printAttributes.setMediaSize(mediaSize);
+            printAttributes.setMinMargins(minMargins);
         }
 
         @Override
@@ -380,18 +382,11 @@
             if (bitmapWidth != other.bitmapWidth) {
                 return false;
             }
-            if (mediaSize != null) {
-                if (!mediaSize.equals(other.mediaSize)) {
+            if (printAttributes != null) {
+                if (!printAttributes.equals(other.printAttributes)) {
                     return false;
                 }
-            } else if (other.mediaSize != null) {
-                return false;
-            }
-            if (minMargins != null) {
-                if (!minMargins.equals(other.minMargins)) {
-                    return false;
-                }
-            } else if (other.minMargins != null) {
+            } else if (other.printAttributes != null) {
                 return false;
             }
             return true;
@@ -407,8 +402,7 @@
         public int hashCode() {
             int result = bitmapWidth;
             result = 31 * result + bitmapHeight;
-            result = 31 * result + (mediaSize != null ? mediaSize.hashCode() : 0);
-            result = 31 * result + (minMargins != null ? minMargins.hashCode() : 0);
+            result = 31 * result + (printAttributes != null ? printAttributes.hashCode() : 0);
             return result;
         }
     }
@@ -440,13 +434,11 @@
         }
     }
 
-    private static int pointsFromMils(int mils) {
-        return (int) (((float) mils / MILS_PER_INCH) * POINTS_IN_INCH);
-    }
-
-    private static class AsyncRenderer {
+    private static final class AsyncRenderer implements ServiceConnection {
         private static final int MALFORMED_PDF_FILE_ERROR = -2;
 
+        private final Object mLock = new Object();
+
         private final Context mContext;
 
         private final PageContentLruCache mPageContentCache;
@@ -457,8 +449,10 @@
 
         private int mPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
 
-        // Accessed only by the executor thread.
-        private PdfRenderer mRenderer;
+        @GuardedBy("mLock")
+        private IPdfRenderer mRenderer;
+
+        private boolean mBoundToService;
 
         public AsyncRenderer(Context context, OnMalformedPdfFileListener malformedPdfFileListener) {
             mContext = context;
@@ -470,6 +464,22 @@
             mPageContentCache = new PageContentLruCache(cacheSizeInBytes);
         }
 
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            mBoundToService = true;
+            synchronized (mLock) {
+                mRenderer = IPdfRenderer.Stub.asInterface(service);
+                mLock.notifyAll();
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            synchronized (mLock) {
+                mRenderer = null;
+            }
+        }
+
         public void open(final ParcelFileDescriptor source, final Runnable callback) {
             // Opening a new document invalidates the cache as it has pages
             // from the last document. We keep the cache even when the document
@@ -479,13 +489,31 @@
 
             new AsyncTask<Void, Void, Integer>() {
                 @Override
+                protected void onPreExecute() {
+                    Intent intent = new Intent(mContext, PdfRendererService.class);
+                    mContext.bindService(intent, AsyncRenderer.this, Context.BIND_AUTO_CREATE);
+                }
+
+                @Override
                 protected Integer doInBackground(Void... params) {
-                    try {
-                        mRenderer = new PdfRenderer(source);
-                        return mRenderer.getPageCount();
-                    } catch (IOException ioe) {
-                        Log.e(LOG_TAG, "Cannot open PDF document");
-                        return MALFORMED_PDF_FILE_ERROR;
+                    synchronized (mLock) {
+                        while (mRenderer == null) {
+                            try {
+                                mLock.wait();
+                            } catch (InterruptedException ie) {
+                                /* ignore */
+                            }
+                        }
+                        try {
+                            return mRenderer.openDocument(source);
+                        } catch (RemoteException re) {
+                            Log.e(LOG_TAG, "Cannot open PDF document");
+                            return MALFORMED_PDF_FILE_ERROR;
+                        } finally {
+                            // Close the fd as we passed it to another process
+                            // which took ownership.
+                            IoUtils.closeQuietly(source);
+                        }
                     }
                 }
 
@@ -510,7 +538,13 @@
             new AsyncTask<Void, Void, Void>() {
                 @Override
                 protected Void doInBackground(Void... params) {
-                    mRenderer.close();
+                    synchronized (mLock) {
+                        try {
+                            mRenderer.closeDocument();
+                        } catch (RemoteException re) {
+                            /* ignore */
+                        }
+                    }
                     return null;
                 }
 
@@ -525,8 +559,22 @@
         }
 
         public void destroy() {
-            mPageContentCache.invalidate();
-            mPageContentCache.clear();
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    return null;
+                }
+
+                @Override
+                public void onPostExecute(Void result) {
+                    if (mBoundToService) {
+                        mBoundToService = false;
+                        mContext.unbindService(AsyncRenderer.this);
+                    }
+                    mPageContentCache.invalidate();
+                    mPageContentCache.clear();
+                }
+            }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
         }
 
         public void startPreload(int firstShownPage, int lastShownPage, RenderSpec renderSpec) {
@@ -752,62 +800,28 @@
                     return mRenderedPage;
                 }
 
-                PdfRenderer.Page page = mRenderer.openPage(mPageIndex);
-
-                if (isCancelled()) {
-                    page.close();
-                    return mRenderedPage;
-                }
-
                 Bitmap bitmap = mRenderedPage.content.getBitmap();
 
-                final int srcWidthPts = page.getWidth();
-                final int srcHeightPts = page.getHeight();
+                ParcelFileDescriptor[] pipe = null;
+                try {
+                    pipe = ParcelFileDescriptor.createPipe();
+                    ParcelFileDescriptor source = pipe[0];
+                    ParcelFileDescriptor destination = pipe[1];
 
-                final int dstWidthPts = pointsFromMils(mRenderSpec.mediaSize.getWidthMils());
-                final int dstHeightPts = pointsFromMils(mRenderSpec.mediaSize.getHeightMils());
+                    mRenderer.renderPage(mPageIndex, bitmap.getWidth(), bitmap.getHeight(),
+                            mRenderSpec.printAttributes, destination);
 
-                final boolean scaleContent = mRenderer.shouldScaleForPrinting();
-                final boolean contentLandscape = !mRenderSpec.mediaSize.isPortrait();
+                    // We passed the file descriptor to the other side which took
+                    // ownership, so close our copy for the write to complete.
+                    destination.close();
 
-                final float displayScale;
-                Matrix matrix = new Matrix();
-
-                if (scaleContent) {
-                    displayScale = Math.min((float) bitmap.getWidth() / srcWidthPts,
-                            (float) bitmap.getHeight() / srcHeightPts);
-                } else {
-                    if (contentLandscape) {
-                        displayScale = (float) bitmap.getHeight() / dstHeightPts;
-                    } else {
-                        displayScale = (float) bitmap.getWidth() / dstWidthPts;
-                    }
+                    BitmapSerializeUtils.readBitmapPixels(bitmap, source);
+                } catch (IOException|RemoteException e) {
+                    Log.e(LOG_TAG, "Error rendering page:" + mPageIndex, e);
+                } finally {
+                    IoUtils.closeQuietly(pipe[0]);
+                    IoUtils.closeQuietly(pipe[1]);
                 }
-                matrix.postScale(displayScale, displayScale);
-
-                Configuration configuration = mContext.getResources().getConfiguration();
-                if (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
-                    matrix.postTranslate(bitmap.getWidth() - srcWidthPts * displayScale, 0);
-                }
-
-                final int paddingLeftPts = pointsFromMils(mRenderSpec.minMargins.getLeftMils());
-                final int paddingTopPts = pointsFromMils(mRenderSpec.minMargins.getTopMils());
-                final int paddingRightPts = pointsFromMils(mRenderSpec.minMargins.getRightMils());
-                final int paddingBottomPts = pointsFromMils(mRenderSpec.minMargins.getBottomMils());
-
-                Rect clip = new Rect();
-                clip.left = (int) (paddingLeftPts * displayScale);
-                clip.top = (int) (paddingTopPts * displayScale);
-                clip.right = (int) (bitmap.getWidth() - paddingRightPts * displayScale);
-                clip.bottom = (int) (bitmap.getHeight() - paddingBottomPts * displayScale);
-
-                if (DEBUG) {
-                    Log.i(LOG_TAG, "Rendering page:" + mPageIndex + " of " + mPageCount);
-                }
-
-                page.render(bitmap, clip, matrix, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
-
-                page.close();
 
                 return mRenderedPage;
             }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index d1aa33b..09e8b39 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -55,7 +55,7 @@
 public final class RemotePrintDocument {
     private static final String LOG_TAG = "RemotePrintDocument";
 
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     private static final int STATE_INITIAL = 0;
     private static final int STATE_STARTED = 1;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl
new file mode 100644
index 0000000..1fba2b1
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.printspooler.renderer;
+
+import android.graphics.Rect;
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+
+/**
+ * Interface for communication with a remote pdf renderer.
+ */
+interface IPdfRenderer {
+    int openDocument(in ParcelFileDescriptor source);
+    oneway void renderPage(int pageIndex, int bitmapWidth, int bitmapHeight,
+        in PrintAttributes attributes, in ParcelFileDescriptor destination);
+    oneway void closeDocument();
+    oneway void writePages(in PageRange[] pages);
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfRendererService.java b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfRendererService.java
new file mode 100644
index 0000000..4d02c01
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfRendererService.java
@@ -0,0 +1,197 @@
+/*
+ * 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.printspooler.renderer;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.pdf.PdfRenderer;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.util.Log;
+import android.view.View;
+import libcore.io.IoUtils;
+import com.android.printspooler.util.BitmapSerializeUtils;
+import java.io.IOException;
+
+/**
+ * Service for rendering PDF documents in an isolated process.
+ */
+public final class PdfRendererService extends Service {
+    private static final String LOG_TAG = "PdfRendererService";
+    private static final boolean DEBUG = false;
+
+    private static final int MILS_PER_INCH = 1000;
+    private static final int POINTS_IN_INCH = 72;
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return new PdfRendererImpl();
+    }
+
+    private final class PdfRendererImpl extends IPdfRenderer.Stub {
+        private final Object mLock = new Object();
+
+        private Bitmap mBitmap;
+        private PdfRenderer mRenderer;
+
+        @Override
+        public int openDocument(ParcelFileDescriptor source) throws RemoteException {
+            synchronized (mLock) {
+                throwIfOpened();
+                if (DEBUG) {
+                    Log.i(LOG_TAG, "openDocument()");
+                }
+                try {
+                    mRenderer = new PdfRenderer(source);
+                    return mRenderer.getPageCount();
+                } catch (IOException ioe) {
+                    throw new RemoteException("Cannot open file");
+                }
+            }
+        }
+
+        @Override
+        public void renderPage(int pageIndex, int bitmapWidth, int bitmapHeight,
+                PrintAttributes attributes, ParcelFileDescriptor destination) {
+            synchronized (mLock) {
+                try {
+                    throwIfNotOpened();
+
+                    PdfRenderer.Page page = mRenderer.openPage(pageIndex);
+
+                    final int srcWidthPts = page.getWidth();
+                    final int srcHeightPts = page.getHeight();
+
+                    final int dstWidthPts = pointsFromMils(
+                            attributes.getMediaSize().getWidthMils());
+                    final int dstHeightPts = pointsFromMils(
+                            attributes.getMediaSize().getHeightMils());
+
+                    final boolean scaleContent = mRenderer.shouldScaleForPrinting();
+                    final boolean contentLandscape = !attributes.getMediaSize().isPortrait();
+
+                    final float displayScale;
+                    Matrix matrix = new Matrix();
+
+                    if (scaleContent) {
+                        displayScale = Math.min((float) bitmapWidth / srcWidthPts,
+                                (float) bitmapHeight / srcHeightPts);
+                    } else {
+                        if (contentLandscape) {
+                            displayScale = (float) bitmapHeight / dstHeightPts;
+                        } else {
+                            displayScale = (float) bitmapWidth / dstWidthPts;
+                        }
+                    }
+                    matrix.postScale(displayScale, displayScale);
+
+                    Configuration configuration = PdfRendererService.this.getResources()
+                            .getConfiguration();
+                    if (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+                        matrix.postTranslate(bitmapWidth - srcWidthPts * displayScale, 0);
+                    }
+
+                    Margins minMargins = attributes.getMinMargins();
+                    final int paddingLeftPts = pointsFromMils(minMargins.getLeftMils());
+                    final int paddingTopPts = pointsFromMils(minMargins.getTopMils());
+                    final int paddingRightPts = pointsFromMils(minMargins.getRightMils());
+                    final int paddingBottomPts = pointsFromMils(minMargins.getBottomMils());
+
+                    Rect clip = new Rect();
+                    clip.left = (int) (paddingLeftPts * displayScale);
+                    clip.top = (int) (paddingTopPts * displayScale);
+                    clip.right = (int) (bitmapWidth - paddingRightPts * displayScale);
+                    clip.bottom = (int) (bitmapHeight - paddingBottomPts * displayScale);
+
+                    if (DEBUG) {
+                        Log.i(LOG_TAG, "Rendering page:" + pageIndex);
+                    }
+
+                    Bitmap bitmap = getBitmapForSize(bitmapWidth, bitmapHeight);
+                    page.render(bitmap, clip, matrix, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
+
+                    page.close();
+
+                    BitmapSerializeUtils.writeBitmapPixels(bitmap, destination);
+                } finally {
+                    IoUtils.closeQuietly(destination);
+                }
+            }
+        }
+
+        @Override
+        public void closeDocument() {
+            synchronized (mLock) {
+                throwIfNotOpened();
+                if (DEBUG) {
+                    Log.i(LOG_TAG, "openDocument()");
+                }
+                mRenderer.close();
+                mRenderer = null;
+            }
+        }
+
+        @Override
+        public void writePages(PageRange[] pages) {
+            synchronized (mLock) {
+                throwIfNotOpened();
+                if (DEBUG) {
+                    Log.i(LOG_TAG, "writePages()");
+                }
+                // TODO: Implement dropping undesired pages.
+            }
+        }
+
+        private Bitmap getBitmapForSize(int width, int height) {
+            if (mBitmap != null) {
+                if (mBitmap.getWidth() == width && mBitmap.getHeight() == height) {
+                    mBitmap.eraseColor(Color.WHITE);
+                    return mBitmap;
+                }
+                mBitmap.recycle();
+            }
+            mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+            mBitmap.eraseColor(Color.WHITE);
+            return mBitmap;
+        }
+
+        private void throwIfOpened() {
+            if (mRenderer != null) {
+                throw new IllegalStateException("Already opened");
+            }
+        }
+
+        private void throwIfNotOpened() {
+            if (mRenderer == null) {
+                throw new IllegalStateException("Not opened");
+            }
+        }
+    }
+
+    private static int pointsFromMils(int mils) {
+        return (int) (((float) mils / MILS_PER_INCH) * POINTS_IN_INCH);
+    }
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 01c9746..022e0d0 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -319,6 +319,7 @@
 
             mProgressMessageController.cancel();
             mPrinterRegistry.setTrackedPrinter(null);
+            mPrintPreviewController.destroy();
             mSpoolerProvider.destroy();
             mPrintedDocument.finish();
             mPrintedDocument.destroy();
@@ -2185,4 +2186,4 @@
             updateOptionsUi();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
index 4a23ec4..2b5b41b 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
@@ -24,6 +24,7 @@
 import android.print.PrintAttributes.MediaSize;
 import android.print.PrintAttributes.Margins;
 import android.print.PrintDocumentInfo;
+import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.OrientationHelper;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.ViewHolder;
@@ -51,7 +52,7 @@
     private final MyHandler mHandler;
 
     private final PageAdapter mPageAdapter;
-    private final StaggeredGridLayoutManager mLayoutManger;
+    private final GridLayoutManager mLayoutManger;
 
     private final PrintOptionsLayout mPrintOptionsLayout;
     private final RecyclerView mRecyclerView;
@@ -73,7 +74,7 @@
         final int columnCount = mActivity.getResources().getInteger(
                 R.integer.preview_page_per_row_count);
 
-        mLayoutManger = new StaggeredGridLayoutManager(columnCount, OrientationHelper.VERTICAL);
+        mLayoutManger = new GridLayoutManager(mActivity, columnCount);
 
         mRecyclerView = (RecyclerView) activity.findViewById(R.id.preview_content);
         mRecyclerView.setLayoutManager(mLayoutManger);
@@ -191,6 +192,9 @@
     }
 
     public void destroy() {
+        if (mPageAdapter.isOpened()) {
+            mPageAdapter.close(null);
+        }
         mPageAdapter.destroy();
     }
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/util/BitmapSerializeUtils.java b/packages/PrintSpooler/src/com/android/printspooler/util/BitmapSerializeUtils.java
new file mode 100644
index 0000000..a1845f6
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/util/BitmapSerializeUtils.java
@@ -0,0 +1,60 @@
+/*
+ * 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.printspooler.util;
+
+import android.graphics.Bitmap;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Helper for serialization of bitmaps in the very specific
+ * use case of having the same bitmap on both ends and just
+ * marshaling the pixels from one side to the other.
+ */
+public final class BitmapSerializeUtils {
+
+    static {
+        System.loadLibrary("printspooler_jni");
+    }
+
+    private BitmapSerializeUtils() {
+        /* do nothing */
+    }
+
+    /**
+     * Reads a bitmap pixels from a file descriptor.
+     *
+     * @param bitmap A bitmap whose pixels to populate.
+     * @param source The source file descriptor.
+     */
+    public static void readBitmapPixels(Bitmap bitmap, ParcelFileDescriptor source) {
+        nativeReadBitmapPixels(bitmap, source.getFd());
+    }
+
+    /**
+     * Writes a bitmap pixels to a file descriptor.
+     *
+     * @param bitmap The bitmap.
+     * @param destination The destination file descriptor.
+     */
+    public static void writeBitmapPixels(Bitmap bitmap, ParcelFileDescriptor destination) {
+        nativeWriteBitmapPixels(bitmap, destination.getFd());
+    }
+
+    private static native void nativeReadBitmapPixels(Bitmap bitmap, int fd);
+
+    private static native void nativeWriteBitmapPixels(Bitmap bitmap, int fd);
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
index 8365373..23a01bd 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
@@ -43,10 +43,13 @@
     private PageContentProvider mProvider;
 
     private MediaSize mMediaSize;
+
     private Margins mMinMargins;
 
     private boolean mContentRequested;
 
+    private boolean mNeedsLayout;
+
     public PageContentView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -68,14 +71,14 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
+        mNeedsLayout = false;
         requestPageContentIfNeeded();
     }
 
     @Override
     public void onPageContentAvailable(BitmapDrawable content) {
-        if (getBackground() != content) {
-            setBackground(content);
-        }
+        assert (getBackground() != content);
+        setBackground(content);
     }
 
     public PageContentProvider getPageContentProvider() {
@@ -83,16 +86,23 @@
     }
 
     public void init(PageContentProvider provider, MediaSize mediaSize, Margins minMargins) {
-        if (mProvider == provider
-                && ((mMediaSize == null) ? mediaSize == null : mMediaSize.equals(mediaSize))
-                && ((mMinMargins == null) ? minMargins == null : mMinMargins.equals(minMargins))) {
+        final boolean providerChanged = (mProvider == null)
+                ? provider != null : !mProvider.equals(provider);
+        final boolean mediaSizeChanged = (mMediaSize == null)
+                ? mediaSize != null : !mMediaSize.equals(mediaSize);
+        final boolean marginsChanged = (mMinMargins == null)
+                ? minMargins != null : !mMinMargins.equals(minMargins);
+
+        if (!providerChanged && !mediaSizeChanged && !marginsChanged) {
             return;
         }
 
         mProvider = provider;
         mMediaSize = mediaSize;
         mMinMargins = minMargins;
+
         mContentRequested = false;
+        mNeedsLayout = mNeedsLayout || mediaSizeChanged || marginsChanged;
 
         // If there is no provider we want immediately to switch to
         // the empty state, so pages with no content appear blank.
@@ -104,10 +114,11 @@
     }
 
     private void requestPageContentIfNeeded() {
-        if (getWidth() > 0 && getHeight() > 0 && !mContentRequested && mProvider != null) {
+        if (getWidth() > 0 && getHeight() > 0 && !mContentRequested
+                && mProvider != null && !mNeedsLayout) {
             mContentRequested = true;
-            mProvider.getPageContent(new RenderSpec(getWidth(), getHeight(), mMediaSize,
-                    mMinMargins), this);
+            mProvider.getPageContent(new RenderSpec(getWidth(), getHeight(),
+                    mMediaSize, mMinMargins), this);
         }
     }
 }
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
deleted file mode 100644
index 2fa0293..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png
deleted file mode 100644
index d43d1dc..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
deleted file mode 100644
index dcf86c0..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_flightmode.png
deleted file mode 100644
index 5171333..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_flightmode.png
deleted file mode 100644
index 1b45762..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_flightmode.png
deleted file mode 100644
index fcbfac1..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_flightmode.png
deleted file mode 100644
index 4555731..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
deleted file mode 100644
index d7a48f2..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png
deleted file mode 100644
index 61d7511..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
deleted file mode 100644
index 14d1060..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-xhdpi/stat_notify_more.png
deleted file mode 100644
index 64327ba..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_notify_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png
deleted file mode 100644
index 192d3f7..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png
deleted file mode 100644
index 95c217c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-xxhdpi/stat_notify_more.png
deleted file mode 100644
index 3c33a56..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_notify_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png
deleted file mode 100644
index 1e5f15f..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_flightmode.png
deleted file mode 100644
index 155c222..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_flightmode.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_info.xml b/packages/SystemUI/res/drawable/ic_info.xml
new file mode 100644
index 0000000..65e7bf5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_info.xml
@@ -0,0 +1,24 @@
+<!--
+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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM13.000000,17.000000l-2.000000,0.000000l0.000000,-6.000000l2.000000,0.000000L13.000000,17.000000zM13.000000,9.000000l-2.000000,0.000000L11.000000,7.000000l2.000000,0.000000L13.000000,9.000000z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_no_sim.xml b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
similarity index 94%
rename from packages/SystemUI/res/drawable/stat_sys_no_sim.xml
rename to packages/SystemUI/res/drawable/ic_qs_no_sim.xml
index 22d1d4b..bd46012 100644
--- a/packages/SystemUI/res/drawable/stat_sys_no_sim.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="32dp"
+        android:height="32dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
 
diff --git a/packages/SystemUI/res/drawable/notification_material_bg_dim.xml b/packages/SystemUI/res/drawable/notification_material_bg_dim.xml
index b04394d..6581942 100644
--- a/packages/SystemUI/res/drawable/notification_material_bg_dim.xml
+++ b/packages/SystemUI/res/drawable/notification_material_bg_dim.xml
@@ -14,7 +14,11 @@
   ~ 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/notification_material_background_dimmed_color" />
-    <corners android:radius="@dimen/notification_material_rounded_rect_radius" />
-</shape>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape>
+            <solid android:color="@color/notification_material_background_dimmed_color" />
+            <corners android:radius="@dimen/notification_material_rounded_rect_radius" />
+        </shape>
+    </item>
+</ripple>
diff --git a/packages/SystemUI/res/drawable/stat_notify_more.xml b/packages/SystemUI/res/drawable/stat_notify_more.xml
new file mode 100644
index 0000000..50f1286
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_notify_more.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ 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="16dp"
+        android:height="16dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M22.000000,3.000000L7.000000,3.000000C6.300000,3.000000 5.800000,3.400000 5.400000,3.900000L0.000000,12.000000l5.400000,8.100000c0.400000,0.500000 1.000000,0.900000 1.700000,0.900000L22.000000,21.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L24.000000,5.000000C24.000000,3.900000 23.100000,3.000000 22.000000,3.000000zM9.000000,13.500000c-0.800000,0.000000 -1.500000,-0.700000 -1.500000,-1.500000s0.700000,-1.500000 1.500000,-1.500000c0.800000,0.000000 1.500000,0.700000 1.500000,1.500000S9.800000,13.500000 9.000000,13.500000zM14.000000,13.500000c-0.800000,0.000000 -1.500000,-0.700000 -1.500000,-1.500000s0.700000,-1.500000 1.500000,-1.500000c0.800000,0.000000 1.500000,0.700000 1.500000,1.500000S14.800000,13.500000 14.000000,13.500000zM19.000000,13.500000c-0.800000,0.000000 -1.500000,-0.700000 -1.500000,-1.500000s0.700000,-1.500000 1.500000,-1.500000c0.800000,0.000000 1.500000,0.700000 1.500000,1.500000S19.799999,13.500000 19.000000,13.500000z"
+        android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_airplane_mode.xml b/packages/SystemUI/res/drawable/stat_sys_airplane_mode.xml
new file mode 100644
index 0000000..433da5f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_airplane_mode.xml
@@ -0,0 +1,28 @@
+<!--
+  ~ 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="17.25dp"
+        android:height="18dp"
+        android:viewportWidth="46.0"
+        android:viewportHeight="48.0">
+
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M20.4,18.0"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M42.0,32.0l0.0,-4.0L26.0,18.0L26.0,7.0c0.0,-1.7 -1.3,-3.0 -3.0,-3.0c-1.7,0.0 -3.0,1.3 -3.0,3.0l0.0,11.0L4.0,28.0l0.0,4.0l16.0,-5.0l0.0,11.0l-4.0,3.0l0.0,3.0l7.0,-2.0l7.0,2.0l0.0,-3.0l-4.0,-3.0L26.0,27.0L42.0,32.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_alarm.xml b/packages/SystemUI/res/drawable/stat_sys_alarm.xml
index 3b2bc31..5754569 100644
--- a/packages/SystemUI/res/drawable/stat_sys_alarm.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_alarm.xml
@@ -13,13 +13,17 @@
   ~ 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="18dp"
-    android:height="18dp"
-    android:viewportWidth="24.0"
-    android:viewportHeight="24.0">
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetLeft="2.5dp"
+    android:insetRight="2.5dp">
+    <vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="22dp"
+        android:height="17dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
 
-    <path
-        android:fillColor="#ffffffff"
-        android:pathData="M22.0,5.7l-4.6,-3.9l-1.3,1.5l4.6,3.9L22.0,5.7zM7.9,3.4L6.6,1.9L2.0,5.7l1.3,1.5L7.9,3.4zM12.5,8.0L11.0,8.0l0.0,6.0l4.7,2.9l0.8,-1.2l-4.0,-2.4L12.5,8.0zM12.0,4.0c-5.0,0.0 -9.0,4.0 -9.0,9.0c0.0,5.0 4.0,9.0 9.0,9.0s9.0,-4.0 9.0,-9.0C21.0,8.0 17.0,4.0 12.0,4.0zM12.0,20.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.9 3.1,-7.0 7.0,-7.0c3.9,0.0 7.0,3.1 7.0,7.0C19.0,16.9 15.9,20.0 12.0,20.0z"/>
-</vector>
+        <path
+            android:fillColor="#ffffffff"
+            android:pathData="M22.0,5.7l-4.6,-3.9l-1.3,1.5l4.6,3.9L22.0,5.7zM7.9,3.4L6.6,1.9L2.0,5.7l1.3,1.5L7.9,3.4zM12.5,8.0L11.0,8.0l0.0,6.0l4.7,2.9l0.8,-1.2l-4.0,-2.4L12.5,8.0zM12.0,4.0c-5.0,0.0 -9.0,4.0 -9.0,9.0c0.0,5.0 4.0,9.0 9.0,9.0s9.0,-4.0 9.0,-9.0C21.0,8.0 17.0,4.0 12.0,4.0zM12.0,20.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.9 3.1,-7.0 7.0,-7.0c3.9,0.0 7.0,3.1 7.0,7.0C19.0,16.9 15.9,20.0 12.0,20.0z"/>
+    </vector>
+</inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_cast.xml b/packages/SystemUI/res/drawable/stat_sys_cast.xml
index c9e65e0..df28638 100644
--- a/packages/SystemUI/res/drawable/stat_sys_cast.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_cast.xml
@@ -13,13 +13,16 @@
     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="18dp"
-        android:height="18dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetLeft="2.5dp"
+    android:insetRight="2.5dp">
+    <vector android:width="22dp"
+            android:height="17dp"
+            android:viewportWidth="48.0"
+            android:viewportHeight="48.0">
 
-    <path
-        android:fillColor="#FFFFFFFF"
-        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>
+        <path
+            android:fillColor="#FFFFFFFF"
+            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>
+</inset>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_bluetooth.xml b/packages/SystemUI/res/drawable/stat_sys_data_bluetooth.xml
index f53f0e4..e2d3539 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_bluetooth.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_bluetooth.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="48.0"
         android:viewportHeight="48.0">
 
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_bluetooth_connected.xml b/packages/SystemUI/res/drawable/stat_sys_data_bluetooth_connected.xml
index 2aac4ee..94c40ba 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_bluetooth_connected.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_bluetooth_connected.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="48.0"
         android:viewportHeight="48.0">
 
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
index 26d2632..d7463a4 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="9.0dp"
-        android:height="18dp"
+        android:width="8.5dp"
+        android:height="17dp"
         android:viewportWidth="12.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
index 5aaf93b..6309b6d 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="9.75dp"
-        android:height="18dp"
+        android:width="9.208dp"
+        android:height="17dp"
         android:viewportWidth="13.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
index b7d84f0..4067ae5 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="9.0dp"
-        android:height="18dp"
+        android:width="8.5dp"
+        android:height="17dp"
         android:viewportWidth="12.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
index 7111457..acaa9b1 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="3.75dp"
-        android:height="18dp"
+        android:width="3.541dp"
+        android:height="17dp"
         android:viewportWidth="5.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
index 97962b2..7985237 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="5.25dp"
-        android:height="18dp"
+        android:width="4.958dp"
+        android:height="17dp"
         android:viewportWidth="7.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
index 4859c14..fda8761 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="4.5dp"
-        android:height="18dp"
+        android:width="4.25dp"
+        android:height="17dp"
         android:viewportWidth="6.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
index d6446db..c08ff20 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="9.75dp"
-        android:height="18dp"
+        android:width="9.208dp"
+        android:height="17dp"
         android:viewportWidth="13.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_roam.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_roam.xml
index 7f7d5fc..363e231 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_roam.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_roam.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="4.5dp"
-        android:height="18dp"
+        android:width="4.25dp"
+        android:height="17dp"
         android:viewportWidth="6.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_location.xml b/packages/SystemUI/res/drawable/stat_sys_location.xml
new file mode 100644
index 0000000..433f73b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_location.xml
@@ -0,0 +1,29 @@
+<!--
+  ~ 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
+  -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetLeft="1.5dp"
+    android:insetRight="1.5dp">
+        <vector
+            android:width="20dp"
+            android:height="17dp"
+            android:viewportWidth="48.0"
+            android:viewportHeight="48.0">
+
+        <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M24.0,4.0c-7.7,0.0 -14.0,6.3 -14.0,14.0c0.0,10.5 14.0,26.0 14.0,26.0s14.0,-15.5 14.0,-26.0C38.0,10.3 31.7,4.0 24.0,4.0zM24.0,23.0c-2.8,0.0 -5.0,-2.2 -5.0,-5.0s2.2,-5.0 5.0,-5.0c2.8,0.0 5.0,2.2 5.0,5.0S26.8,23.0 24.0,23.0z"/>
+        </vector>
+</inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml b/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml
index 352d86f..f017d58 100644
--- a/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml
@@ -13,13 +13,16 @@
     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="20dp"
-        android:height="20dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetLeft="3dp"
+    android:insetRight="3dp">
+    <vector android:width="24dp"
+            android:height="18dp"
+            android:viewportWidth="24.0"
+            android:viewportHeight="24.0">
 
-    <path
-        android:fillColor="#FFFFFFFF"
-        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>
+        <path
+            android:fillColor="#FFFFFFFF"
+            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>
+</inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
index 67d9259..e1e81fd 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
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 3bbb800..c0dfcf4 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
index 55f764a..a53e946 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
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 b82e428..6bc55cd 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
index ca0eeb3..537c788 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
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 abc8dd1..7d9376e 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
index 2b3e571..09fe33a 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
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 d47f167..8ec5500 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
index 7d4dd8a..bb98541 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
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 5b1bac3..a468410 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_null.xml b/packages/SystemUI/res/drawable/stat_sys_signal_null.xml
index 45d34a2..d25fc1c 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_null.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_null.xml
@@ -15,8 +15,8 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:autoMirrored="true"
-        android:width="18dp"
-        android:height="18dp"
+        android:width="17dp"
+        android:height="17dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
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 4965674..be930e8 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
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 e9cad0e..b2691f6 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
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
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 7d588a3..dde781d 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
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 348f963..65931f4 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
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
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 4fbdd69..63d9dca 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
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 66588f0..7ba4895 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
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
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 1f3de74..7d393b4 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
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 aa5d2ed..e2cde53 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
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
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 ca53b56..ec8137f 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
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 1c7a539..9d02980 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
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
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 c68fb49..95c6531 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20dp"
-        android:height="18dp"
+        android:width="18.41dp"
+        android:height="17dp"
         android:viewportWidth="26.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/SystemUI/res/drawable/stat_sys_zen_important.xml b/packages/SystemUI/res/drawable/stat_sys_zen_important.xml
index 73d7cba..9dabb03 100644
--- a/packages/SystemUI/res/drawable/stat_sys_zen_important.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_zen_important.xml
@@ -13,13 +13,16 @@
     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="20dp"
-        android:height="20dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetLeft="2.5dp"
+    android:insetRight="2.5dp">
+    <vector android:width="23dp"
+            android:height="18dp"
+            android:viewportWidth="24.0"
+            android:viewportHeight="24.0">
 
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M12.0,17.273l6.1800003,3.7269993 -1.6350002,-7.0290003 5.455,-4.7269993 -7.191,-0.6170006 -2.809,-6.627 -2.809,6.627 -7.191,0.6170006 5.455,4.7269993 -1.6349998,7.0290003z"/>
-</vector>
+        <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M12.0,17.273l6.1800003,3.7269993 -1.6350002,-7.0290003 5.455,-4.7269993 -7.191,-0.6170006 -2.809,-6.627 -2.809,6.627 -7.191,0.6170006 5.455,4.7269993 -1.6349998,7.0290003z"/>
+    </vector>
+</inset>
diff --git a/packages/SystemUI/res/drawable/stat_sys_zen_none.xml b/packages/SystemUI/res/drawable/stat_sys_zen_none.xml
index d8ab078..7573de0 100644
--- a/packages/SystemUI/res/drawable/stat_sys_zen_none.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_zen_none.xml
@@ -13,13 +13,16 @@
     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="19dp"
-        android:height="19dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetLeft="2.5dp"
+    android:insetRight="2.5dp">
+    <vector android:width="22dp"
+            android:height="17dp"
+            android:viewportWidth="48.0"
+            android:viewportHeight="48.0">
 
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M24.0,4.0C13.0,4.0 4.0,13.0 4.0,24.0c0.0,11.0 9.0,20.0 20.0,20.0c11.0,0.0 20.0,-9.0 20.0,-20.0C44.0,13.0 35.0,4.0 24.0,4.0zM24.0,40.0c-8.8,0.0 -16.0,-7.2 -16.0,-16.0c0.0,-3.7 1.3,-7.1 3.4,-9.8l22.4,22.4C31.1,38.7 27.7,40.0 24.0,40.0zM36.6,33.8L14.2,11.4C16.9,9.3 20.3,8.0 24.0,8.0c8.8,0.0 16.0,7.2 16.0,16.0C40.0,27.7 38.7,31.1 36.6,33.8z"/>
-</vector>
+        <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M24.0,4.0C13.0,4.0 4.0,13.0 4.0,24.0c0.0,11.0 9.0,20.0 20.0,20.0c11.0,0.0 20.0,-9.0 20.0,-20.0C44.0,13.0 35.0,4.0 24.0,4.0zM24.0,40.0c-8.8,0.0 -16.0,-7.2 -16.0,-16.0c0.0,-3.7 1.3,-7.1 3.4,-9.8l22.4,22.4C31.1,38.7 27.7,40.0 24.0,40.0zM36.6,33.8L14.2,11.4C16.9,9.3 20.3,8.0 24.0,8.0c8.8,0.0 16.0,7.2 16.0,16.0C40.0,27.7 38.7,31.1 36.6,33.8z"/>
+    </vector>
+</inset>
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index faa2820..b5f917a 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -44,7 +44,7 @@
         android:layout_toStartOf="@id/multi_user_switch"
         android:layout_alignWithParentIfMissing="true"
         android:layout_marginStart="16dp"
-        android:paddingEnd="2dp">
+        android:paddingEnd="@dimen/system_icons_keyguard_padding_end">
         <FrameLayout android:id="@+id/system_icons_container"
             android:layout_width="wrap_content"
             android:layout_height="@dimen/status_bar_height"
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index ac8af1b..d52c274 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -77,13 +77,23 @@
         </LinearLayout>
 
         <ImageButton style="@android:style/Widget.Material.Light.Button.Borderless.Small"
+                 android:id="@+id/notification_inspect_app_provided_settings"
+                 android:layout_width="52dp"
+                 android:layout_height="match_parent"
+                 android:layout_weight="0"
+                 android:gravity="center"
+                 android:src="@drawable/ic_settings"
+                 android:visibility="gone"
+                />
+
+        <ImageButton style="@android:style/Widget.Material.Light.Button.Borderless.Small"
                 android:id="@+id/notification_inspect_item"
                 android:layout_width="52dp"
                 android:layout_height="match_parent"
                 android:layout_weight="0"
                 android:gravity="center"
                 android:contentDescription="@string/status_bar_notification_inspect_item_title"
-                android:src="@drawable/ic_settings"
+                android:src="@drawable/ic_info"
                 />
     </LinearLayout>
 </com.android.systemui.statusbar.NotificationGuts>
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index ae54f8c..347c8a9 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -36,21 +36,10 @@
             android:layout_width="wrap_content"
             />
     </FrameLayout>
-    <View
-        android:layout_height="6dp"
-        android:layout_width="6dp"
-        android:visibility="gone"
-        android:id="@+id/spacer"
-        />
     <FrameLayout
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
         >
-        <View
-            android:layout_height="6dp"
-            android:layout_width="6dp"
-            android:visibility="invisible"
-            />
         <FrameLayout
             android:id="@+id/mobile_combo"
             android:layout_width="wrap_content"
@@ -68,6 +57,12 @@
                 />
         </FrameLayout>
     </FrameLayout>
+    <View
+        android:id="@+id/wifi_airplane_spacer"
+        android:layout_width="4dp"
+        android:layout_height="4dp"
+        android:visibility="gone"
+        />
     <ImageView
         android:id="@+id/airplane"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index beb8e00..0d414f9 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -43,8 +43,8 @@
     <LinearLayout android:id="@+id/status_bar_contents"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:paddingStart="6dip"
-        android:paddingEnd="6dip"
+        android:paddingStart="6dp"
+        android:paddingEnd="8dp"
         android:orientation="horizontal"
         >
 
@@ -91,7 +91,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:singleLine="true"
-                android:paddingStart="6dip"
+                android:paddingStart="7dp"
                 android:gravity="center_vertical|start"
                 />
         </com.android.systemui.statusbar.AlphaOptimizedLinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 7ad3a89..34e062c 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -60,7 +60,7 @@
         android:layout_alignWithParentIfMissing="true"
         android:layout_marginStart="16dp"
         android:background="@drawable/ripple_drawable"
-        android:paddingEnd="2dp" >
+        android:paddingEnd="4dp" >
         <FrameLayout android:id="@+id/system_icons_container"
             android:layout_width="wrap_content"
             android:layout_height="@dimen/status_bar_height"
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
index 351177b..ef85847 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -64,9 +64,4 @@
             />
     </LinearLayout>
 
-    <com.android.systemui.statusbar.NotificationScrimView
-        android:id="@+id/scrim_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
 </com.android.systemui.statusbar.NotificationOverflowContainer>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index ef4e27c..6b829e5 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -59,9 +59,4 @@
         android:layout_height="match_parent"
         />
 
-    <com.android.systemui.statusbar.NotificationScrimView
-        android:id="@+id/scrim_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
 </com.android.systemui.statusbar.ExpandableNotificationRow>
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 09e541f..29fec41 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -26,24 +26,6 @@
     android:fitsSystemWindows="true"
     android:descendantFocusability="afterDescendants">
 
-    <FrameLayout android:id="@+id/brightness_mirror"
-            android:layout_width="@dimen/notification_panel_width"
-            android:layout_height="wrap_content"
-            android:layout_gravity="@integer/notification_panel_layout_gravity"
-            android:paddingLeft="@dimen/notification_side_padding"
-            android:paddingRight="@dimen/notification_side_padding"
-            android:visibility="gone">
-        <FrameLayout
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:elevation="2dp"
-                android:background="@drawable/brightness_mirror_background">
-            <include layout="@layout/quick_settings_brightness_dialog"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content" />
-        </FrameLayout>
-    </FrameLayout>
-
     <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
             android:id="@+id/backdrop"
             android:layout_width="match_parent"
@@ -69,6 +51,24 @@
         android:layout_width="match_parent"
         android:layout_height="@dimen/status_bar_height" />
 
+    <FrameLayout android:id="@+id/brightness_mirror"
+                 android:layout_width="@dimen/notification_panel_width"
+                 android:layout_height="wrap_content"
+                 android:layout_gravity="@integer/notification_panel_layout_gravity"
+                 android:paddingLeft="@dimen/notification_side_padding"
+                 android:paddingRight="@dimen/notification_side_padding"
+                 android:visibility="gone">
+        <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:elevation="2dp"
+                android:background="@drawable/brightness_mirror_background">
+            <include layout="@layout/quick_settings_brightness_dialog"
+                     android:layout_width="match_parent"
+                     android:layout_height="wrap_content" />
+        </FrameLayout>
+    </FrameLayout>
+
     <com.android.systemui.statusbar.phone.PanelHolder
         android:id="@+id/panel_holder"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/system_icons.xml b/packages/SystemUI/res/layout/system_icons.xml
index 69f9c14..8f25d99 100644
--- a/packages/SystemUI/res/layout/system_icons.xml
+++ b/packages/SystemUI/res/layout/system_icons.xml
@@ -30,12 +30,12 @@
         android:id="@+id/signal_cluster"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginStart="2dp"/>
+        android:layout_marginStart="2.5dp"/>
 
     <!-- battery must be padded below to match assets -->
     <com.android.systemui.BatteryMeterView android:id="@+id/battery"
-        android:layout_height="16dp"
-        android:layout_width="10.5dp"
-        android:layout_marginBottom="0.33dp"
-        android:layout_marginStart="4dip"/>
+        android:layout_height="14.5dp"
+        android:layout_width="9.5dp"
+        android:layout_marginBottom="@dimen/battery_margin_bottom"
+        android:layout_marginStart="7dp"/>
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index df6e9fd..ee27bb2 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Това у-во се управлява от:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПотр. ви профил се управлява от:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдминистр. ви може да наблюдава акт. ви в мрежата, вкл. имейлите, прилож. и защитените уебсайтове. За още информация се свържете с него.\n\nСъщо така дадохте на <xliff:g id="APPLICATION">%3$s</xliff:g> разрешение да настрои връзка с VPN. Приложението може да наблюдава и акт. в мрежата."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"У-вото се управлява от:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПотр. ви профил се управлява от:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдминистраторът ви може да наблюдава акт. ви в мрежата, вкл. имейлите, прилож. и защитените уебсайтове. За още информация се свържете с него.\n\nСъщо така сте свързани с VPN (<xliff:g id="APPLICATION">%3$s</xliff:g>). Доставчикът ви на услуги за VPN може да наблюдава и акт. ви в мрежата."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Устройството ще остане заключено, докато не го отключите ръчно"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Получавайте известия по-бързо"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Вижте известията, преди да отключите"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Няма нужда"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Настройване"</string>
     <string name="muted_by" msgid="6147073845094180001">"Заглушено от <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 83a6ba9..812b19c 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"এই ডিভাইসটি পরিচালনা করছে:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nআপনার প্রোফাইলটি পরিচালনা করছে:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nআপনার প্রশাসক ইমেল,অ্যাপ্লিকেশান ও নিরাপদ ওয়েবসাইটগুলি সহ আপনার নেটওয়ার্ক ক্রিয়াকলাপ নিরীক্ষণ করতে সক্ষম। আরো তথ্যের জন্য, আপনার প্রশাসকের সঙ্গে যোগাযোগ করুন।\n\nআপনি \"<xliff:g id="APPLICATION">%3$s</xliff:g>\"-কে একটি VPN সংযোগ সেট আপ করার অনুমতিও দিয়েছেন। এই অ্যাপ্লিকেশান নেটওয়ার্ক ক্রিয়াকলাপও নিরীক্ষণ করতে পারে।"</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"এই ডিভাইসটি পরিচালনা করছে:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nআপনার প্রোফাইলটি পরিচালনা করছে:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nআপনার প্রশাসক ইমেল,অ্যাপ্লিকেশান ও নিরাপদ ওয়েবসাইটগুলি সহ আপনার নেটওয়ার্ক ক্রিয়াকলাপ নিরীক্ষণ করতে সক্ষম। আরো তথ্যের জন্য, আপনার প্রশাসকের সঙ্গে যোগাযোগ করুন।\n\nএছাড়াও, আপনি একটি VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") এ সংযুক্ত আছেন। আপনার VPN পরিষেবা প্রদানকারী নেটওয়ার্ক ক্রিয়াকলাপও নিরীক্ষণ করতে পারে।"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"আপনি নিজে আনলক না করা পর্যন্ত ডিভাইসটি লক হয়ে থাকবে"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"বিজ্ঞপ্তিগুলি আরো দ্রুত পান"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"আপনি আনলক করার আগে ওগুলো দেখুন"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"না থাক"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"সেট আপ"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> দ্বারা নিঃশব্দ করা হয়েছে"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2197cbd..89911ad 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -69,7 +69,7 @@
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_text" msgid="2419718443411738818">"Probíhá ukládání snímku obrazovky."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky zachycen."</string>
+    <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky Snímek obrazovky pořízen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Snímek obrazovky zobrazíte dotykem."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Snímek obrazovky se nepodařilo zachytit."</string>
     <string name="screenshot_failed_text" msgid="1260203058661337274">"Snímek obrazovky nelze pořídit kvůli nedostatku místa, nebo to aplikace či vaše organizace zakazuje."</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 126b3f6..5226b9c 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -348,20 +348,16 @@
     <string name="monitoring_description_legacy_vpn" msgid="4740349017929725435">"VPN sarera konektatuta zaude (\"<xliff:g id="APPLICATION">%1$s</xliff:g>\").\n\nVPN zerbitzu-hornitzaileak gailua eta sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne."</string>
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne.Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN konexio bat ezartzeko baimena eman diozu \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" aplikazioari. Aplikazioak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
-    <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak gailua eta sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan."</string>
-    <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak gailua eta sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune segurak barne.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan."</string>
-    <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN konexioa konfiguratzeko \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" baimena eman duzu. Aplikazio horrek ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
-    <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
-    <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN konexioa konfiguratzeko \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" baimena eman duzu. Aplikazio horrek ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
-    <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
+    <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak gailua eta sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne.\n\nInformazio gehiago lortzeko, jo administratzailearengana."</string>
+    <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak gailua eta sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne.\n\nInformazio gehiago lortzeko, jo administratzailearengana."</string>
+    <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne. Info. gehiago lortzeko, jo administratzailearengana.\n\nGainera, VPN konexioa konfiguratzeko \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" baimena eman duzu. Aplikazio horrek ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
+    <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne. Info. gehiago lortzeko, jo administratzailearengana.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
+    <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne. Info. gehiago lortzeko, jo administratzailearengana.\n\nGainera, VPN konexioa konfiguratzeko \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" baimena eman duzu. Aplikazio horrek ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
+    <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne. Info. gehiago lortzeko, jo administratzailearengana.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Gailua blokeatuta egongo da eskuz desblokeatu arte"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Eskuratu jakinarazpenak azkarrago"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Ikusi desblokeatu baino lehen"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ez, eskerrik asko"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Konfiguratu"</string>
     <string name="muted_by" msgid="6147073845094180001">"Audioa desaktibatu da (<xliff:g id="THIRD_PARTY">%1$s</xliff:g>)"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index f3479af..9f63781 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"‏مدیریت این دستگاه توسط:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nمدیریت نمایه‌تان توسط:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nسرپرستتان می‌تواند فعالیت شبکه‌تان را کنترل کند از جمله ایمیل‌ها، برنامه‌ها و وب‌سایت‌های ایمن. برای کسب اطلاعات بیشتر، با سرپرستتان تماس بگیرید.\n\nهمچنین، به «<xliff:g id="APPLICATION">%3$s</xliff:g>» اجازه دادید اتصال VPN را تنظیم کند. این برنامه می‌تواند فعالیت شبکه‌ را نیز کنترل کند."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"‏مدیریت این دستگاه توسط:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nمدیریت نمایه‌تان توسط:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nسرپرستتان می‌تواند فعالیت شبکه‌تان را کنترل کند از جمله ایمیل‌ها، برنامه‌ها و وب‌سایت‌های ایمن. برای کسب اطلاعات بیشتر، با سرپرستتان تماس بگیرید.\n\nهمچنین، به VPN ‏(«<xliff:g id="APPLICATION">%3$s</xliff:g>») وصل هستید. ارائه‌دهنده سرویس VPN شما می‌تواند فعالیت شبکه را نیز کنترل کند."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"دستگاه قفل باقی می‌ماند تا زمانی که قفل آن را به صورت دستی باز کنید"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"دریافت سریع‌تر اعلان‌ها"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"قبل از باز کردن قفل آنها را مشاهده کنید"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"خیر، سپاسگزارم"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"راه‌اندازی"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> آن را بی‌صدا کرد"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4e595df..e2dd843 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -357,13 +357,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Laitteen hallinnoija: \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfiilisi hallinnoija: \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nJärjestelmänvalvoja voi valvoa toimiasi verkossa, esimerkiksi sähköpostin, sovellusten ja turvallisten verkkosivustojen käyttöä. Saat lisätietoja järjestelmänvalvojalta.\n\nAnnoit sovellukselle <xliff:g id="APPLICATION">%3$s</xliff:g> luvan VPN-yhteyden määrittämiseen. Myös se voi valvoa toimiasi."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Laitteen hallinnoija: \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfiilisi hallinnoija: \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nJärjestelmänvalvoja voi valvoa toimiasi verkossa, esimerkiksi sähköpostin, sovellusten ja turvallisten verkkosivustojen käyttöä. Saat lisätietoja järjestelmänvalvojalta.\n\nKäytät VPN-yhteyttä (<xliff:g id="APPLICATION">%3$s</xliff:g>). VPN-palveluntarjoaja voi myös valvoa toimiasi."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Laite pysyy lukittuna, kunnes se avataan käsin"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Näe ilmoitukset nopeammin"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Näytä ennen lukituksen avaamista"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ei kiitos"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Määritä asetukset"</string>
     <string name="muted_by" msgid="6147073845094180001">"Mykistänyt <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 0282d02..71f042d 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -338,7 +338,7 @@
     <string name="media_projection_action_text" msgid="8470872969457985954">"Commencer maintenant"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Aucune notification"</string>
     <string name="device_owned_footer" msgid="3802752663326030053">"Il est possible que cet appareil soit surveillé."</string>
-    <string name="profile_owned_footer" msgid="8021888108553696069">"Ce profil peut être contrôlé"</string>
+    <string name="profile_owned_footer" msgid="8021888108553696069">"le profil peut être contrôlé"</string>
     <string name="vpn_footer" msgid="2388611096129106812">"Le réseau peut être surveillé"</string>
     <string name="monitoring_title_device_owned" msgid="7121079311903859610">"Surveillance d\'appareils"</string>
     <string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Contrôle de profil"</string>
@@ -357,13 +357,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Appareil géré par : \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil géré par : \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nVotre administrateur peut surveiller votre activité réseau (courriels, applications et sites sécurisés). Communiquez avec votre administrateur.\n\nEn outre, vous avez autorisé <xliff:g id="APPLICATION">%3$s</xliff:g> à créer une connexion RPV. Cette application peut aussi surveiller l\'activité réseau."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Appareil géré par : \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil géré par : \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nVotre administrateur peut surveiller l\'act. de votre appareil et votre act. réseau (courriels, applications et sites sécurisés). Communiquez avec votre administrateur.\n\nVous êtes aussi connecté à un RPV (<xliff:g id="APPLICATION">%3$s</xliff:g>). Votre admin RPV peut lui aussi surveiller votre act. réseau."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"L\'appareil restera verrouillé jusqu\'à ce que vous le déverrouilliez manuellement"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Voir les notifications plus rapidement"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Afficher les notifications avant de déverrouiller l\'appareil"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Non, merci"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Configurer"</string>
     <string name="muted_by" msgid="6147073845094180001">"Mis en sourdine par <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index daaace4..a85b209 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -357,13 +357,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Appareil géré par :\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil géré par :\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nVotre administrateur peut contrôler votre activité réseau (e-mails, applications et sites sécurisés). Pour en savoir plus, contactez votre admin.\n\nVous avez donné à l\'appli \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" l\'autorisation de configurer une connexion VPN. Cette appli peut contrôler votre activité réseau."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Appareil géré par :\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil géré par :\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nVotre administrateur peut contrôler votre activité réseau (e-mails, applications et sites sécurisés). Pour en savoir plus, contactez votre administrateur.\n\nVous êtes aussi connecté à un VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). Votre fournisseur de services VPN peut également contrôler l\'activité réseau."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"L\'appareil restera verrouillé jusqu\'à ce que vous le déverrouilliez manuellement."</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Recevoir les notifications plus vite"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Afficher les notifications avant de déverrouiller l\'appareil"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Non, merci"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Configurer"</string>
     <string name="muted_by" msgid="6147073845094180001">"Son coupé par : <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hdpi/dimens.xml b/packages/SystemUI/res/values-hdpi/dimens.xml
new file mode 100644
index 0000000..10b00eb
--- /dev/null
+++ b/packages/SystemUI/res/values-hdpi/dimens.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>
+    <!-- Margin on the right side of the system icon group on Keyguard. -->
+    <fraction name="battery_button_height_fraction">10.5%</fraction>
+
+    <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this
+         fraction of a pixel.-->
+    <fraction name="battery_subpixel_smoothing_left">20%</fraction>
+    <fraction name="battery_subpixel_smoothing_right">12%</fraction>
+
+    <dimen name="battery_margin_bottom">1px</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 11f3aa8..af20b98 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Սարքի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nՊրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, ծրագրերը և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ադմինիստրատորին:\n\nԴուք նաև «<xliff:g id="APPLICATION">%3$s</xliff:g>»-ին թույլատրել եք ստեղծել VPN: Այն նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Սարքի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nՊրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, ծրագրերը և վստահելի կայքերը: Այլ տեղեկությունների համար դիմեք ադմինիստրատորին:\n\nԴուք նաև միացած եք VPN-ին («<xliff:g id="APPLICATION">%3$s</xliff:g>»): VPN ծառայություն մատուցողը նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Սարքը կմնա արգելափակված՝ մինչև ձեռքով չբացեք"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Ստանալ ծանուցումներն ավելի արագ"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Տեսեք դրանք՝ մինչև ապակողպելը"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ոչ, շնորհակալություն"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Կարգավորել"</string>
     <string name="muted_by" msgid="6147073845094180001">"Համրեցվել է <xliff:g id="THIRD_PARTY">%1$s</xliff:g>-ի կողմից"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 0404ce5..f1aa72c 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -355,15 +355,11 @@
     <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"このプロフィールは次の組織によって管理されています。\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN接続を設定する権限を「<xliff:g id="APPLICATION">%2$s</xliff:g>」に付与しているため、このアプリもネットワークアクティビティを監視できます。"</string>
     <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"このプロフィールは次の組織によって管理されています。\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN(「<xliff:g id="APPLICATION">%2$s</xliff:g>」)に接続しているため、VPNサービスプロバイダもネットワークアクティビティを監視できます。"</string>
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"この端末は次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nあなたのプロフィールは次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN接続を設定する権限を「<xliff:g id="APPLICATION">%3$s</xliff:g>」に付与しているため、このアプリもネットワークアクティビティを監視できます。"</string>
-    <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"この端末は次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nあなたのプロフィールは次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN(「<xliff:g id="APPLICATION">%3$s</xliff:g>」)に接続しているため、VPNサービスプロバイダもあなたのネットワークアクティビティを監視できます。"</string>
+    <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"この端末は次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nあなたのプロフィールは次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN(「<xliff:g id="APPLICATION">%3$s</xliff:g>」)に接続しているため、VPNサービスプロバイダもネットワークアクティビティを監視できます。"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"手動でロックを解除するまでロックされたままとなります"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"通知をすばやく確認できます"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"ロックを解除する前にご確認ください"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"キャンセル"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"設定"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>によりミュートになっています"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 30b6d67..e7b272b 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"ამ მოწყობილობის მმართველია:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nთქვენი პროფილის მმართველია:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი მოწყობილობისა და ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით ადმინისტრატორს.\n\nასევე, თქვენ მიანიჭეთ „<xliff:g id="APPLICATION">%3$s</xliff:g>“-ს VPN კავშირის დაყენება. ამ აპს ასევე შეუძლია ქსელის მონიტორინგი."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"ამ მოწყობილობის მმართველია:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nთქვენი პროფილის მმართველია:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი მოწყობილობისა და ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით ადმინისტრატორს.\n\nასევე, თქვენ დაკავშირებული ხართ VPN-თან („<xliff:g id="APPLICATION">%3$s</xliff:g>“). თქვენს VPN სერვისის მომწოდებელს ასევე შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"მოწყობილობის დარჩება ჩაკეტილი, სანამ ხელით არ გახსნით"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"შეტყობინებების უფრო სწრაფად მიღება"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"იხილეთ განბლოკვამდე"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"არა, გმადლობთ"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"დაყენება"</string>
     <string name="muted_by" msgid="6147073845094180001">"დადუმებულია <xliff:g id="THIRD_PARTY">%1$s</xliff:g>-ის მიერ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 055bee6..e7e7119 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Бұл құрылғыны басқаратын:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПрофиліңізді басқаратын:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nӘкімші желілік белс-ті, соның ішінде, эл. хаб-ды, қол-ды және қорғалған веб-сайттарды бақылай алады. Қосымша ақпар. алу үшін әкімшіге хаб-з.\n\nСондай-ақ, сіз «<xliff:g id="APPLICATION">%3$s</xliff:g>» VPN байланысын орнату рұқсатын бердіңіз. Бұл қолданба да желілік белсенділікті бақылай алады."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Бұл құр. басқаратын:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПрофиліңізді басқаратын:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nӘкімші желілік белсенділікті, соның ішінде, эл. хаб-ды, қолд-ды және қорғалған веб-сайттарды бақылай алады. Қосымша ақпарат алу үшін әкімшіге хаб-ңыз.\n\nСондай-ақ, VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") қызметіне қосылғансыз. VPN қызметін жеткізуші де желілік белсенділікті бақылай алады."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Қолмен бекітпесін ашқанша құрылғы бекітілген күйде қалады"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Хабарландыруларды тезірек алу"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Бекітпесін ашу алдында оларды көру"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Жоқ, рақмет"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Реттеу"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> үнін өшірген"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 252f356..61d4289 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"ឧបករណ៍នេះត្រូវបានគ្រប់គ្រងដោយ៖\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nប្រវត្តិរូបរបស់អ្នកត្រូវបានគ្រប់គ្រង៖\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nអ្នកគ្រប់គ្រងរបស់អ្នកអាចតាមដានសកម្មភាពបណ្ដាញ រួមមានអ៊ីមែល កម្មវិធី និងតំបន់បណ្ដាញមានសុវត្ថិភាព។ ចំពោះព័ត៌មានបន្ថែម ទាក់ទងអ្នកគ្រប់គ្រងរបស់អ្នក។\n\nអ្នកបានផ្ដល់សិទ្ធិ \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" ឲ្យកំណត់ការភ្ជាប់ VPN ។ កម្មវិធីនេះអាចតាមដានសកម្មភាពបណ្ដាញផងដែរ។"</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"ឧបករណ៍នេះត្រូវបា​នគ្រប់គ្រងដោយ៖\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nប្រវត្តិរូបរបស់អ្នកត្រូវបានគ្រប់គ្រង​ដោយ៖\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nអ្នកគ្រប់គ្រងរបស់អ្នកអាចតាមដានសកម្មភាពបណ្ដាញរបស់អ្នក  រួមមានអ៊ីមែល, កម្មវិធី និងតំបន់បណ្ដាញមានសុវត្ថិភាព​​​។ ចំពោះព័ត៌មានបន្ថែម ទាក់ទង​អ្នកគ្រប់គ្រងរបស់​អ្នក។\n\nអ្នកក៏បានភ្ជាប់ទៅ​ VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") ។ ក្រុមហ៊ុនផ្ដល់សេវាកម្ម VPN របស់អ្នកអាចតាមដានសកម្មភាពបណ្ដាញបានផងដែរ។"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ឧបករណ៍​នឹង​ចាក់​សោ​រហូត​ដល់​អ្នក​ដោះ​សោ​ដោយ​ដៃ"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"ទទួល​បាន​ការ​ជូន​ដំណឹង​កាន់តែ​លឿន"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"ឃើញ​ពួកវា​មុន​ពេល​ដោះ​សោ"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"ទេ អរគុណ!"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"រៀបចំ"</string>
     <string name="muted_by" msgid="6147073845094180001">"បាន​បិទ​សំឡេង​ដោយ <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 9d424ae..e73cbde 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -357,13 +357,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"기기 관리자:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n프로필 관리자:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n관리자는 이메일, 앱, 보안 웹사이트를 비롯한 내 네트워크 활동을 모니터링할 수 있습니다. 자세한 정보는 관리자에게 문의하세요.\n\n또한 \'<xliff:g id="APPLICATION">%3$s</xliff:g>\'에 VPN 연결을 설정할 수 있는 권한을 부여했습니다. 이 앱에서도 네트워크 활동을 모니터링할 수 있습니다."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"기기 관리자:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n프로필 관리자:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n관리자는 이메일, 앱, 보안 웹사이트를 비롯한 내 네트워크 활동을 모니터링할 수 있습니다. 자세한 정보는 관리자에게 문의하세요.\n\n또한 현재 VPN(\'<xliff:g id="APPLICATION">%3$s</xliff:g>\')에 연결되어 있습니다. VPN 서비스 제공업체에서도 네트워크 활동을 모니터링할 수 있습니다."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"수동으로 잠금 해제할 때까지 기기가 잠금 상태로 유지됩니다."</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"알림을 더욱 빠르게 받기"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"잠금 해제하기 전에 알림을 봅니다."</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"사용 안함"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"설정"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>에서 알림음 음소거"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 1827c13..a96c88a 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -381,13 +381,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Бул түзмөктү төмөнкү башк-т:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПрофилиңизди төмөнкү башк-т:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдмин-ңуздун тармак ар-ңизди, анын ичинде email-дер, колд-лор жана коопсуз вебс-ды, көз-дөө мүмк-гү бар. Дагы маалымат үчүн, админ-ңузга кайр-з.\n\n\"<xliff:g id="APPLICATION">%3$s</xliff:g>\" VPN туташуусун орнотуусуна да уруксат бердиңиз. Бул колдонмо тармак аракетин да көзөмөлдөй алат."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Түзмөктү тө-кү башк-т:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПрофилди тө-кү башк-т:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдмин-ңуздун тармак ар-ңизди, анын ичинде email-дер, колд-лор жана коопсуз вебс-ды, көзөмөлдөө мүмкүнчүлүгү бар. Дагы маалымат үчүн, админ-ңузга кайрылыңыз.\n\nСиз VPN-ге (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") да туташкансыз. VPN тейлөөчүңүз да тармак аракетин көзөмөлдөй алат."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Түзмөктүн кулпусу кол менен ачылмайынча кулпуланган бойдон алат"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Эскертмелерди тезирээк алуу"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Аларды кулпудан чыгараардан мурун көрүңүз"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Жок, рахмат"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Орнотуу"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> тарабынан үнсүздөлдү"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 6f41766..468f717 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"ອຸ​ປະ​ກອນ​ນີ້​ແມ່ນ​ຈັດ​ການ​ໂດຍ:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nໂປຣ​ໄຟລ໌​ຂອງ​ທ່ານ​ແມ່ນ​ຖືກ​ຈັດ​ການ​ໂດຍ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nຜູ່​ເບິ່ງ​ແຍງ​ຂອງ​ທ່ານ​ມີ​ຄວາມ​ສາ​ມາດ​ໃນ​ການ​ຕິດ​ຕາມ​ການ​ເຄື່ອນ​ໄຫວ​ໃນ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ​ໄດ້ ຮວມ​ເຖິງ: ​ອີ​ເມວ, ແອັບຯ ແລະ​ເວັບ​ໄຊ​​ທີ່​ເຂົ້າ​ລະ​ຫັດ. ສຳ​ລັບ​ຂໍ້​ມູນ​ເພີ່ມ​ເຕີມ, ໃຫ້​ຕິດ​ຕໍ່​ຜູ່​ເບິ່ງ​ແຍງ​ລະ​ບົບ​ຂອງ​ທ່ານ.\n\nນອກ​ຈາກ​ນັ້ນ, ທ່ານ​ໄດ້​ອະ​ນຸ​ຍາດ​ໃຫ້ \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" ​ສາ​ມາດ​ຕັ້ງ​ຄ່າ​ການ​ເຊື່ອມ​ຕໍ່ VPN ໄດ້. ແອັບຯ​ນີ້​​ສາ​ມາດ​ຕິດ​ຕາມ​ການ​ເຄື່ອນ​ໄຫວ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ​ໄດ້​ເຊັ່ນ​ກັນ."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"ອຸ​ປະ​ກອນ​ນີ້​ແມ່ນ​ຈັດ​ການ​ໂດຍ:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nໂປຣ​ໄຟລ໌​ຂອງ​ທ່ານ​ແມ່ນ​ຖືກ​ຈັດ​ການ​ໂດຍ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nຜູ່​ເບິ່ງ​ແຍງ​ຂອງ​ທ່ານ​ມີ​ຄວາມ​ສາ​ມາດ​ໃນ​ການ​ຕິດ​ຕາມ​ການ​ເຄື່ອນ​ໄຫວ​ໃນ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ​ໄດ້ ຮວມ​ເຖິງ: ​ອີ​ເມວ, ແອັບຯ ແລະ​ເວັບ​ໄຊ​​ທີ່​ເຂົ້າ​ລະ​ຫັດ. ສຳ​ລັບ​ຂໍ້​ມູນ​ເພີ່ມ​ເຕີມ, ໃຫ້​ຕິດ​ຕໍ່​ຜູ່​ເບິ່ງ​ແຍງ​ລະ​ບົບ​ຂອງ​ທ່ານ.\n\nນອກ​ຈາກ​ນັ້ນ, ທ່ານ​ໄ​ດ້​ເຊື່ອມ​ຕໍ່​ຫາ VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). ຜູ່​ໃຫ້​ບໍ​ລິ​ການ VPN ​ຂອງ​ທ່ານ​ສາ​ມາດ​ຕິດ​ຕາມ​ການ​ເຄື່ອນ​ໄຫວ​ເຄືອ​ຂ່າຍ​ໄດ້​ເຊັ່ນ​ກັນ."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Device will stay locked until you manually unlock"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"ຮັບເອົາການ​ແຈ້ງເຕືອນ​ໄວຂຶ້ນ"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"ເບິ່ງພວກ​ມັນກ່ອນ​ທ່ານຈະ​ປົດລັອກ"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"ບໍ່, ຂອບໃຈ"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"ຕັ້ງຄ່າ"</string>
     <string name="muted_by" msgid="6147073845094180001">"ຖືກ​ປິດ​ສຽງ​ໂດຍ <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mdpi/dimens.xml b/packages/SystemUI/res/values-mdpi/dimens.xml
new file mode 100644
index 0000000..aa85d69
--- /dev/null
+++ b/packages/SystemUI/res/values-mdpi/dimens.xml
@@ -0,0 +1,27 @@
+<?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>
+    <!-- Margin on the right side of the system icon group on Keyguard. -->
+    <fraction name="battery_button_height_fraction">12%</fraction>
+
+    <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this
+         fraction of a pixel.-->
+    <fraction name="battery_subpixel_smoothing_left">10%</fraction>
+    <fraction name="battery_subpixel_smoothing_right">10%</fraction>
+
+    <dimen name="battery_margin_bottom">1px</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 12ab9e8..293b028 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -266,7 +266,7 @@
     <string name="quick_settings_tethering_label" msgid="7153452060448575549">"ടെതറിംഗ്"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ഹോട്ട്‌സ്‌പോട്ട്"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"അറിയിപ്പുകൾ"</string>
-    <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ഫ്‌ലാഷ്‌ലൈറ്റ്"</string>
+    <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ഫ്ലാഷ്‌ലൈറ്റ്"</string>
     <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"സെല്ലുലാർ ഡാറ്റ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ഡാറ്റ ഉപയോഗം"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ശേഷിക്കുന്ന ഡാറ്റ"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 1d8e11e..f6c6f8a 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -350,10 +350,10 @@
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"हे डिव्हाइस याद्वारे व्यवस्थापित केले जाते:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइट यासह आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, आपण एका VPN शी कनेक्ट केले आहे (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
     <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"हे प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या डिव्हाइसचे आणि नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो.\n\nअधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा."</string>
     <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"हे डिव्हाइस याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nआपले प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या डिव्हाइसचे आणि नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो.\n\nअधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा."</string>
-    <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"हे प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतथापि, VPN कनेक्शन सेट करण्यासाठी आपण \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" ला परवानगी दिली आहे. हा अॅप नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
-    <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"हे प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतथापि, आपण एका VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") शी कनेक्ट केलेले आहे. आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
-    <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"हे डिव्हाइस याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nआपले प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतथापि, VPN कनेक्शन सेट करण्यासाठी आपण \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" ला परवानगी दिली आहे. हा अॅप नेटवर्क क्रियाकलापाचे परीक्षण देखील करू शकतो."</string>
-    <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"हे डिव्हाइस याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nआपले प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतथापि, आपण एका VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") शी कनेक्ट केलेले आहे. आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
+    <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"हे प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, VPN कनेक्शन सेट करण्यासाठी आपण \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" ला परवानगी दिली आहे. हा अॅप नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
+    <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"हे प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, आपण एका VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") शी कनेक्ट केलेले आहे. आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
+    <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"हे डिव्हाइस याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nआपले प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, VPN कनेक्शन सेट करण्यासाठी आपण \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" ला परवानगी दिली आहे. हा अॅप नेटवर्क क्रियाकलापाचे परीक्षण देखील करू शकतो."</string>
+    <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"हे डिव्हाइस याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nआपले प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, आपण एका VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") शी कनेक्ट केलेले आहे. आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"आपण व्यक्तिचलितपणे अनलॉक करेपर्यंत डिव्हाइस लॉक केलेले राहील"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"सूचना अधिक जलद मिळवा"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"आपण अनलॉक करण्‍यापूर्वी त्यांना पहा"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index df99613..0c0efb3 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Peranti ini diurus olh:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil anda diurus olh:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nPentadbir anda bkemampuan mmantau aktiviti rgkaian anda tmasuk e-mel, apl dan tapak web yg slmt. Untuk mdptkn maklumat lanjut, hubungi pentadbir anda.\n\nAnda jg mberi \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" kebenaran utk menyediakan smbungn VPN. Apl ini jg blh mmantau aktiviti rngkaian."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Peranti ini diurus olh:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil anda diurus olh:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nPentadbir anda blh mmantau pranti dn aktiviti rgkaian anda, tmasuk e-mel, apl dan tapak web yg slmt. Utk mdapatkan mklumat lanjut, hubungi pentadbir anda.\n\nAnda juga disambungkn ke VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). Pmbekal perkhidmatan VPN anda jg blh memantau rangkaian aktiviti."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Peranti akan kekal terkunci sehingga anda membuka kunci secara manual"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Dapatkan pemberitahuan lebih cepat"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Lihat sebelum anda membuka kunci"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Tidak, terima kasih"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Sediakan"</string>
     <string name="muted_by" msgid="6147073845094180001">"Diredam oleh <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 8c866a9..df555a6 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"यस उपकरण र तपाईँको प्रोफाइल \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n र \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n ले व्यवस्थित गरिएको छ। तपाईँको प्रशासकले सञ्जाल गतिविधि निगरानी गर्न सक्षम छन् जस्तै इमेल, अनुप्रयोग र सुरक्षित वेबसाइट। थप जान्न प्रशासकलाई सम्पर्क गर्नुहोला।\n\nसाथै, तपाईँले VPN जडान स्थापित गर्न \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" अनुमति दिनुभयो। यो अनुप्रयोगले संजालको निगरानी पनि गर्न सक्छ।"</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"यो उपकरणको व्यवस्थित \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n ले गरेको छ। तपाईँको प्रोफाइल \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n ले व्यवस्थित गरिएको छ। तपाईँको प्रशासकले सञ्जाल गतिविधि निगरानी गर्न सक्षम छन् जसमा इमेल, अनुप्रयोग र सुरक्षित वेबसाइट छ। थप जान्न प्रशासकलाई सम्पर्क गर्नुहोला।\n\nसाथै, तपाईँ VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") मा जडित हुनुहुन्छ। जुन सेवा प्रदायकले निगरानी गर्न सक्ने छन्।"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"तपाईँले नखोले सम्म उपकरण बन्द रहनेछ"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"छिटो सूचनाहरू प्राप्त गर्नुहोस्"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"तपाईँले अनलक गर्नअघि तिनीहरूलाई हेर्नुहोस्"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"धन्यवाद पर्दैन"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"सेटअप गर्नुहोस्"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> द्वारा मौन गरिएको"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 181f361..4180640 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -357,13 +357,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Este dispositivo é gerenciado por:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nSeu perfil é gerenciado por:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nO administrador pode monitorar sua atividade na rede, como e-mails, apps e sites seguros. Para mais informações, contate o administrador.\n\nVocê autorizou \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" a fazer conexões VPN e o provedor de serviços de VPN também pode monitorar atividades de rede."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Este dispositivo é gerenciado por:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nSeu perfil é gerenciado por:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nO administrador pode monitorar sua atividade na rede, como e-mails, apps e sites seguros. Para mais informações, contate o administrador.\n\nVocê está conectado a uma VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") e o provedor de serviços de VPN também pode monitorar atividades de rede."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até que você o desbloqueie manualmente"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Receba notificações mais rápido"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Veja-as antes de desbloquear"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Não, obrigado"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Configurar"</string>
     <string name="muted_by" msgid="6147073845094180001">"Som desativado por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9a41430..84cfff4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -357,13 +357,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Устройством управляет организация:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nВашим профилем управляет организация:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдминистратор может отслеживать вашу работу с эл. почтой, приложениями и защищенными веб-сайтами. Обратитесь к нему за дополнительной информацией.\n\nВы разрешили приложению \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" подключаться к VPN, и ему также доступны эти сведения."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Устройством управляет организация:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nВашим профилем управляет организация:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдминистратор может отслеживать вашу работу с почтой, приложениями и защищенными веб-сайтами. Обратитесь к нему за дополнительной информацией.\n\nУстройство подключено к сети VPN (<xliff:g id="APPLICATION">%3$s</xliff:g>). Поставщику услуг VPN видны ваши действия в Сети."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Устройство необходимо будет разблокировать вручную"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Быстрый доступ к уведомлениям"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Просматривайте уведомления на заблокированном экране."</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Закрыть"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Настроить"</string>
     <string name="muted_by" msgid="6147073845094180001">"Звук отключен приложением \"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>\""</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index bd667cf..c0b1b12 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -337,7 +337,7 @@
     <string name="profile_owned_footer" msgid="8021888108553696069">"Huenda wasifu ukafuatiliwa"</string>
     <string name="vpn_footer" msgid="2388611096129106812">"Huenda mtandao unafuatiliwa"</string>
     <string name="monitoring_title_device_owned" msgid="7121079311903859610">"Ufuatiliaji wa kifaa"</string>
-    <string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Ufuatiliaji wa wasifu"</string>
+    <string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Ufuatiliaji wasifu"</string>
     <string name="monitoring_title" msgid="169206259253048106">"Ufuatiliaji wa mtandao"</string>
     <string name="disable_vpn" msgid="4435534311510272506">"Zima VPN"</string>
     <string name="disconnect_vpn" msgid="1324915059568548655">"Ondoa VPN"</string>
@@ -346,20 +346,16 @@
     <string name="monitoring_description_legacy_vpn" msgid="4740349017929725435">"Umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%1$s</xliff:g>\").\n\nMtoa huduma wako wa VPN anaweza kufuatilia kifaa na shughuli za kifaa na mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti salama."</string>
     <string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi anaweza kufuatilia shughuli za mtandao wako ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeruhusu \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli za mtandao wako."</string>
     <string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi anaweza kufuatilia shughuli za mtandao wako ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli za mtandao."</string>
-    <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"Wasifu huu unasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia kifaa chako na shughuli za mtandao, ikiwa ni pamoja na barua pepe na tovuti salama.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
-    <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia kifaa chako na shughuli za mtandao, ikiwa ni pamoja na barua pepe na tovuti salama.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
-    <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"Wasifu huu unasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli za mtandao, ikiwa ni pamoja na barua pepe, programu na na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, uliruhusu \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli za mtandao."</string>
-    <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli za mtandao wako ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli za mtandao."</string>
-    <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli za mtandao, ikiwa ni pamoja na barua pepe, programu na na tovuti salama\n\nPia, uliruhusu \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli za mtandao."</string>
-    <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli za mtandao."</string>
+    <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"Wasifu huu unasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia kifaa chako na shughuli kwenye mtandao, ikiwa ni pamoja na barua pepe na tovuti salama.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
+    <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia kifaa chako na shughuli kwenye mtandao, ikiwa ni pamoja na barua pepe na tovuti salama.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
+    <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"Wasifu huu unasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli zako kwenye mtandao, ikiwa ni pamoja na barua pepe, programu na na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, uliruhusu \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli kwenye mtandao."</string>
+    <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli zako kwenye mtandao ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli kwenye mtandao."</string>
+    <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli zako kwenye mtandao, ikiwa ni pamoja na barua pepe, programu na na tovuti salama\n\nPia, uliruhusu \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli kwenye mtandao."</string>
+    <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli zako kwenye mtandao, ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli kwenye mtandao."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Kifaa kitaendelea kuwa katika hali ya kufungwa hadi utakapokifungua mwenyewe"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Pata arifa kwa haraka"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Zitazame kabla hujafungua"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"La, asante"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Sanidi"</string>
     <string name="muted_by" msgid="6147073845094180001">"Sauti imezimwa na <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 9901e44..d3b5580 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -46,6 +46,9 @@
     <!-- The side padding for the task stack as a percentage of the width. -->
     <item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.075</item>
 
+    <!-- The height of the search bar space. -->
+    <dimen name="recents_search_bar_space_height">72dp</dimen>
+
     <!-- The fraction of the screen height where the clock on the Keyguard has its center. The
          max value is used when no notifications are displaying, and the min value is when the
          highest possible number of notifications are showing. -->
@@ -81,4 +84,7 @@
     <dimen name="edge_tap_area_width">80dp</dimen>
 
     <dimen name="keyguard_indication_margin_bottom">90dp</dimen>
+
+    <!-- Margin on the right side of the system icon group on Keyguard. -->
+    <dimen name="system_icons_keyguard_padding_end">2dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 1c343a9..52700cc 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -83,7 +83,7 @@
     <string name="accessibility_recent" msgid="1606470783629913980">"சமீபத்திய திரைகள்"</string>
     <string name="accessibility_search_light" msgid="1103867596330271848">"தேடு"</string>
     <string name="accessibility_camera_button" msgid="8064671582820358152">"கேமரா"</string>
-    <string name="accessibility_phone_button" msgid="6738112589538563574">"மொபைல்"</string>
+    <string name="accessibility_phone_button" msgid="6738112589538563574">"ஃபோன்"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"திற"</string>
     <string name="unlock_label" msgid="8779712358041029439">"திற"</string>
     <string name="phone_label" msgid="2320074140205331708">"ஃபோனைத் திற"</string>
@@ -143,7 +143,7 @@
     <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ரோமிங்"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"வைஃபை"</string>
-    <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM இல்லை."</string>
+    <string name="accessibility_no_sim" msgid="8274017118472455155">"சிம் இல்லை."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"புளூடூத் இணைப்பு முறை."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"விமானப் பயன்முறை."</string>
     <string name="accessibility_battery_level" msgid="7451474187113371965">"பேட்டரி சக்தி <xliff:g id="NUMBER">%d</xliff:g> சதவிகிதம் உள்ளது."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 2aa8f05..0c0149c 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Bu cihazı yöneten kuruluş:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfilinizi yöneten kuruluş:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nYöneticiniz; e-postalar, uygulamalar ve güvenli web siteleri de dahil olmak üzere ağ etkinliğinizi izleyebilir. Daha fazla bilgi için yöneticinize başvurun.\n\nAyrıca \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" uygulamasına VPN kurma izni verdiniz. Bu uygulama da ağ etkinliğini izleyebilir."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Bu cihazı yöneten kuruluş:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfilinizi yöneten kuruluş:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nYöneticiniz; e-postalar, uygulamalar ve güvenli web siteleri de dahil olmak üzere ağ etkinliğinizi izleyebilir. Daha fazla bilgi için yöneticinize başvurun.\n\nAyrıca, bir VPN\'ye (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") bağlısınız. VPN hizmet sağlayıcınız da ağ etkinliğini izleyebilir."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Cihazınızın kilidini manuel olarak açmadıkça cihaz kilitli kalacak"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Bildirimleri daha hızlı alın"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Kilidi açmadan bildirimleri görün"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Hayır, teşekkürler"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Kur"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> tarafından kapatıldı"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tvdpi/dimens.xml b/packages/SystemUI/res/values-tvdpi/dimens.xml
new file mode 100644
index 0000000..5327cee
--- /dev/null
+++ b/packages/SystemUI/res/values-tvdpi/dimens.xml
@@ -0,0 +1,27 @@
+<?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>
+    <!-- Margin on the right side of the system icon group on Keyguard. -->
+    <fraction name="battery_button_height_fraction">12%</fraction>
+
+    <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this
+     fraction of a pixel.-->
+    <fraction name="battery_subpixel_smoothing_left">10%</fraction>
+    <fraction name="battery_subpixel_smoothing_right">10%</fraction>
+
+    <dimen name="battery_margin_bottom">1px</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 4ab3171..162a280 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -286,7 +286,7 @@
     <string name="description_target_search" msgid="3091587249776033139">"Пошук"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Проведіть пальцем угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Проведіть пальцем ліворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Без сповіщень. Навіть без сигналів будильника."</string>
+    <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_alarm_information_time" msgid="5235772206174372272">"Наступний сигнал: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 5bfac40..708607c 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"‏اس آلہ کا نظم کیا جاتا ہے بذریعہ:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nآپ کے پروفائل کا نظم کیا جاتا ہے بذریعہ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nآپ کا منتظم آپ کے نیٹ ورک کی سرگرمی بشمول، ای میلز، ایپس اور محفوظ ویب سائٹس کو مانیٹر کر سکتا ہے۔ مزید معلومات کیلئے، اپنے منتظم سے رابطہ کریں۔\n\nنیز، آپ نے \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" کو ایک VPN کنکشن ترتیب دینے کی اجازت دی ہے۔ یہ ایپ نیٹ ورک کی سرگرمی بھی مانیٹر کر سکتی ہے۔"</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"‏اس آلہ کا نظم کیا جاتا ہے بذریعہ:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nآپ کے پروفائل کا نظم کیا جاتا ہے بذریعہ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nآپ کا منتظم آپ کے نیٹ ورک کی سرگرمی، بشمول ای میلز، ایپس اور محفوظ ویب سائٹس کو مانیٹر کر سکتا ہے۔ مزید معلومات کیلئے، اپنے منتظم سے رابطہ کریں۔\n\nنیز، آپ ایک VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") سے منسلک ہیں۔ آپ کا VPN سروس فراہم کنندہ نیٹ ورک کی سرگرمی کو بھی مانیٹر کر سکتا ہے۔"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"آلہ اس وقت تک مقفل رہے گا جب تک آپ دستی طور پر اسے غیر مقفل نہ کریں"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"تیزی سے اطلاعات حاصل کریں"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"غیر مقفل کرنے سے پہلے انہیں دیکھیں"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"نہیں شکریہ"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"ترتیب دیں"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> کے ذریعے خاموش کردہ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 8868213..7776269 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -355,13 +355,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Bu qurilma boshqaruvchisi:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil boshqaruvchisi:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdmin-ngiz tarmoqdagi faollik – e-pochta, ilova va xavfsiz veb-saytlardagi har-ni kuzatishi m-n. Qo‘sh. ma’l. olish u-n admin-ga murojaat qiling.\n\nSiz “<xliff:g id="APPLICATION">%3$s</xliff:g>” ilovasiga VPN ulanishini sozlash u-n ruxsat bergansiz. U ham tarmoqdagi faollikni kuzatishi m-n."</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Bu qurilma boshqaruvchisi:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil boshqaruvchisi:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdmin-ngiz tarmoqdagi faollik – e-pochta, ilova va xavfsiz veb-saytlardagi har-ni kuzatishi m-n.\n\nQo‘sh. ma’l. olish u-n admin-ga murojaat qiling. Siz VPN tarmog‘iga (“<xliff:g id="APPLICATION">%3$s</xliff:g>”) ulangansiz. VPN xizmati ta’minotchingiz ham tarmoqdagi faollikni kuzatishi m-n."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Qurilma qo‘lda qulfdan chiqarilmaguncha qulflangan holatda qoladi"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Bildirishnomalarni tezroq oling"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"Ularni qulfdan chiqarishdan oldin ko‘ring"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Yo‘q, kerak emas"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Sozlash"</string>
     <string name="muted_by" msgid="6147073845094180001">"“<xliff:g id="THIRD_PARTY">%1$s</xliff:g>” tomonidan ovozsiz qilingan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-xhdpi/dimens.xml b/packages/SystemUI/res/values-xhdpi/dimens.xml
new file mode 100644
index 0000000..144b225
--- /dev/null
+++ b/packages/SystemUI/res/values-xhdpi/dimens.xml
@@ -0,0 +1,27 @@
+<?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>
+
+    <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this
+         fraction of a pixel.-->
+    <fraction name="battery_subpixel_smoothing_left">25%</fraction>
+    <fraction name="battery_subpixel_smoothing_right">12.5%</fraction>
+
+    <dimen name="battery_margin_bottom">0dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-xxhdpi/dimens.xml b/packages/SystemUI/res/values-xxhdpi/dimens.xml
new file mode 100644
index 0000000..26c8437
--- /dev/null
+++ b/packages/SystemUI/res/values-xxhdpi/dimens.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
+  -->
+
+<resources>
+
+    <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this
+         fraction of a pixel.-->
+    <fraction name="battery_subpixel_smoothing_left">33%</fraction>
+    <fraction name="battery_subpixel_smoothing_right">33%</fraction>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7d6dc64..06cebb3 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -357,13 +357,9 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"此设备由以下单位管理:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的资料由以下单位管理:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理员可以监控您的网络活动,包括收发电子邮件、使用应用和浏览安全网站。若要了解详情,请与您的管理员联系。\n\n此外,您已授权“<xliff:g id="APPLICATION">%3$s</xliff:g>”设置VPN连接。此应用也可以监控网络活动。"</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"此设备由以下单位管理:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的资料由以下单位管理:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理员可以监控您的网络活动,包括收发电子邮件、使用应用和浏览安全网站。若要了解详情,请与您的管理员联系。\n\n此外,您已连接到VPN(“<xliff:g id="APPLICATION">%3$s</xliff:g>”)。您的VPN服务提供商也可以监控您的网络活动。"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"在您手动解锁之前,设备会保持锁定状态"</string>
-    <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
-    <skip />
-    <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
-    <skip />
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"更快捷地查看通知"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"无需解锁即可查看通知"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"不用了"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"设置"</string>
     <string name="muted_by" msgid="6147073845094180001">"已被<xliff:g id="THIRD_PARTY">%1$s</xliff:g>设为静音"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 2df414c..9b0bde1 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -338,7 +338,7 @@
     <string name="media_projection_action_text" msgid="8470872969457985954">"立即開始"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"沒有通知"</string>
     <string name="device_owned_footer" msgid="3802752663326030053">"裝置可能會受到監控"</string>
-    <string name="profile_owned_footer" msgid="8021888108553696069">"個人檔案可能會受到監控"</string>
+    <string name="profile_owned_footer" msgid="8021888108553696069">"個人檔案可能受到監控"</string>
     <string name="vpn_footer" msgid="2388611096129106812">"網絡可能會受到監控"</string>
     <string name="monitoring_title_device_owned" msgid="7121079311903859610">"裝置監控"</string>
     <string name="monitoring_title_profile_owned" msgid="6790109874733501487">"個人檔案監控"</string>
@@ -357,7 +357,7 @@
     <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"這部裝置的管理機構:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的個人檔案的管理機構:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網絡活動,包括電郵、應用程式及安全網站。如需瞭解詳情,請聯絡您的管理員。\n\n同時,由於您已授權「<xliff:g id="APPLICATION">%3$s</xliff:g>」設定 VPN 連線,因此這個應用程式也能監控您的網絡活動。"</string>
     <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"這部裝置的管理機構:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的個人檔案的管理機構:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網絡活動,包括電郵、應用程式及安全網站。如需瞭解詳情,請聯絡您的管理員。\n\n同時,由於您的裝置已與 VPN (「<xliff:g id="APPLICATION">%3$s</xliff:g>」) 連線,因此您的 VPN 服務供應商也能監控您的網絡活動。"</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"裝置將保持上鎖,直到您手動解鎖"</string>
-    <string name="hidden_notifications_title" msgid="7139628534207443290">"更快取得通知"</string>
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"快速取得通知"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"解鎖前顯示"</string>
     <string name="hidden_notifications_cancel" msgid="3690709735122344913">"不用了,謝謝"</string>
     <string name="hidden_notifications_setup" msgid="41079514801976810">"設定"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index f3a62b8..6da811f 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -90,7 +90,10 @@
     <color name="notification_material_background_media_default_color">#ff424242</color>
 
     <!-- The color of the ripples on the untinted notifications -->
-    <color name="notification_ripple_untinted_color">#20000000</color>
+    <color name="notification_ripple_untinted_color">#28000000</color>
+
+    <!-- The color of the ripples on the low priority notifications -->
+    <color name="notification_ripple_color_low_priority">#30000000</color>
 
     <!-- The color of the ripples on the tinted notifications -->
     <color name="notification_ripple_tinted_color">#30ffffff</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 0e18979..5399a39 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -137,7 +137,7 @@
     <!-- The min animation duration for animating the task in when transitioning from home. -->
     <integer name="recents_animate_task_enter_from_home_duration">275</integer>
     <!-- The animation stagger to apply to each task animation when transitioning from home. -->
-    <integer name="recents_animate_task_enter_from_home_delay">10</integer>
+    <integer name="recents_animate_task_enter_from_home_delay">150</integer>
     <!-- The short duration when animating in/out the lock to app button. -->
     <integer name="recents_animate_lock_to_app_button_short_duration">150</integer>
     <!-- The long duration when animating in/out the lock to app button. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d3cebd45..8cd4ce6 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -73,6 +73,9 @@
     <!-- Height of notification icons in the status bar -->
     <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
 
+    <!-- The font size for the clock -->
+    <dimen name="status_bar_clock_size">14sp</dimen>
+
     <!-- Height of a small notification in the status bar -->
     <dimen name="notification_min_height">64dp</dimen>
 
@@ -86,10 +89,10 @@
     <dimen name="notification_summary_height">44dp</dimen>
 
     <!-- size at which Notification icons will be drawn in the status bar -->
-    <dimen name="status_bar_icon_drawing_size">18dip</dimen>
+    <dimen name="status_bar_icon_drawing_size">17dip</dimen>
 
     <!-- opacity at which Notification icons will be drawn in the status bar -->
-    <item type="dimen" name="status_bar_icon_drawing_alpha">75%</item>
+    <item type="dimen" name="status_bar_icon_drawing_alpha">90%</item>
 
     <!-- gap on either side of status bar notification icons -->
     <dimen name="status_bar_icon_padding">0dp</dimen>
@@ -286,13 +289,13 @@
     <dimen name="speed_bump_height">16dp</dimen>
 
     <!-- Lockscreen unlocking falsing threshold. -->
-    <dimen name="unlock_falsing_threshold">100dp</dimen>
+    <dimen name="unlock_falsing_threshold">80dp</dimen>
 
     <!-- Lockscreen falsing threshold for quick settings. -->
-    <dimen name="qs_falsing_threshold">60dp</dimen>
+    <dimen name="qs_falsing_threshold">80dp</dimen>
 
     <!-- Falsing threshold used when dismissing notifications from the lockscreen. -->
-    <dimen name="swipe_helper_falsing_threshold">100dp</dimen>
+    <dimen name="swipe_helper_falsing_threshold">70dp</dimen>
 
     <dimen name="notifications_top_padding">8dp</dimen>
     
@@ -312,7 +315,7 @@
     <dimen name="heads_up_window_height">250dp</dimen>
 
     <!-- The minimum amount the user needs to swipe to go to the camera / phone. -->
-    <dimen name="keyguard_min_swipe_amount">85dp</dimen>
+    <dimen name="keyguard_min_swipe_amount">90dp</dimen>
 
     <!-- The minimum background radius when swiping to a side for the camera / phone affordances. -->
     <dimen name="keyguard_affordance_min_background_radius">30dp</dimen>
@@ -405,8 +408,8 @@
     <!-- The font size of the date in QS -->
     <dimen name="qs_date_collapsed_size">14sp</dimen>
 
-    <!-- Battery level padding end when in expanded QS (but not on Keyguard) -->
-    <dimen name="battery_level_padding_end">4dp</dimen>
+    <!-- Battery level text padding end when in expanded QS and on Keyguard -->
+    <dimen name="battery_level_padding_end">2dp</dimen>
 
     <!-- The top padding of the clear all button -->
     <dimen name="clear_all_padding_top">12dp</dimen>
@@ -419,11 +422,14 @@
     <dimen name="keyguard_carrier_text_margin">16dp</dimen>
 
     <!-- Margin on the left side of the battery % in the header. -->
-    <dimen name="header_battery_margin_expanded">8dp</dimen>
+    <dimen name="header_battery_margin_expanded">6dp</dimen>
 
     <!-- Margin on the left side of the battery % when on Keyguard. -->
     <dimen name="header_battery_margin_keyguard">6dp</dimen>
 
+    <!-- Margin on the right side of the system icon group on Keyguard. -->
+    <dimen name="system_icons_keyguard_padding_end">4dp</dimen>
+
     <!-- Additional translation (downwards) for appearing notifications when going to the full shade
          from Keyguard. -->
     <dimen name="go_to_full_shade_appearing_translation">200dp</dimen>
@@ -461,4 +467,13 @@
     <!-- TrustDrawable: Thickness of the circle -->
     <dimen name="trust_circle_thickness">2dp</dimen>
 
+    <!-- Margin on the right side of the system icon group on Keyguard. -->
+    <fraction name="battery_button_height_fraction">10.5%</fraction>
+
+    <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this
+         fraction of a pixel.-->
+    <fraction name="battery_subpixel_smoothing_left">0%</fraction>
+    <fraction name="battery_subpixel_smoothing_right">0%</fraction>
+
+    <dimen name="battery_margin_bottom">0dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b488c56..23d9748 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -522,9 +522,13 @@
     <!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_clear_all">Clear all notifications.</string>
 
-    <!-- Title shown in notification popup for inspecting the responsible
-         application [CHAR LIMIT=30] -->
-    <string name="status_bar_notification_inspect_item_title">Settings</string>
+    <!-- Content description of button in notification inspector for system settings relating to
+         notifications from this application [CHAR LIMIT=NONE] -->
+    <string name="status_bar_notification_inspect_item_title">Notification settings</string>
+
+    <!-- Content description of button in notification inspetor for application-provided settings
+         for its own notifications [CHAR LIMIT=NONE] -->
+    <string name="status_bar_notification_app_settings_title"><xliff:g id="app_name" example="Calendar">%s</xliff:g> settings</string>
 
     <!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is on. [CHAR LIMIT=NONE] -->
     <string name="accessibility_rotation_lock_off">Screen will rotate automatically.</string>
@@ -752,6 +756,9 @@
     <!-- Accessibility label for the button that opens the user switcher. -->
     <string name="accessibility_multi_user_switch_switcher">Switch user</string>
 
+    <!-- Accessibility label for the button that opens the user switcher and announces the current user. -->
+    <string name="accessibility_multi_user_switch_switcher_with_current">Switch user, current user <xliff:g id="current_user_name" example="John Doe">%s</xliff:g></string>
+
     <!-- Accessibility label for the button that opens the quick contact of the user. -->
     <string name="accessibility_multi_user_switch_quick_contact">Show profile</string>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index efd4fb4..cb66e7a 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -69,8 +69,7 @@
     </style>
 
     <style name="TextAppearance.StatusBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon">
-        <!-- Note: must be dp to fit in status bar -->
-        <item name="android:textSize">16dp</item>
+        <item name="android:textSize">@dimen/status_bar_clock_size</item>
         <item name="android:fontFamily">sans-serif-medium</item>
         <item name="android:textColor">@color/status_bar_clock_color</item>
     </style>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 5e2f784..7bdbd0a 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -46,12 +46,14 @@
 
     private static final int FULL = 96;
 
-    private static final float SUBPIXEL = 0.4f;  // inset rects for softer edges
     private static final float BOLT_LEVEL_THRESHOLD = 0.3f;  // opaque bolt below this fraction
 
     private final int[] mColors;
 
     boolean mShowPercent = true;
+    private float mButtonHeightFraction;
+    private float mSubpixelSmoothingLeft;
+    private float mSubpixelSmoothingRight;
     private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint;
     private float mTextHeight, mWarningTextHeight;
 
@@ -205,6 +207,12 @@
         mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);
         mCriticalLevel = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_criticalBatteryWarningLevel);
+        mButtonHeightFraction = context.getResources().getFraction(
+                R.fraction.battery_button_height_fraction, 1, 1);
+        mSubpixelSmoothingLeft = context.getResources().getFraction(
+                R.fraction.battery_subpixel_smoothing_left, 1, 1);
+        mSubpixelSmoothingRight = context.getResources().getFraction(
+                R.fraction.battery_subpixel_smoothing_right, 1, 1);
 
         mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mFramePaint.setColor(frameColor);
@@ -304,28 +312,28 @@
         final int height = mHeight - pt - pb;
         final int width = mWidth - pl - pr;
 
-        final int buttonHeight = (int) (height * 0.12f);
+        final int buttonHeight = (int) (height * mButtonHeightFraction);
 
         mFrame.set(0, 0, width, height);
         mFrame.offset(pl, pt);
 
         // button-frame: area above the battery body
         mButtonFrame.set(
-                mFrame.left + width * 0.25f,
+                mFrame.left + Math.round(width * 0.25f),
                 mFrame.top,
-                mFrame.right - width * 0.25f,
+                mFrame.right - Math.round(width * 0.25f),
                 mFrame.top + buttonHeight);
 
-        mButtonFrame.top += SUBPIXEL;
-        mButtonFrame.left += SUBPIXEL;
-        mButtonFrame.right -= SUBPIXEL;
+        mButtonFrame.top += mSubpixelSmoothingLeft;
+        mButtonFrame.left += mSubpixelSmoothingLeft;
+        mButtonFrame.right -= mSubpixelSmoothingRight;
 
         // frame: battery body area
         mFrame.top += buttonHeight;
-        mFrame.left += SUBPIXEL;
-        mFrame.top += SUBPIXEL;
-        mFrame.right -= SUBPIXEL;
-        mFrame.bottom -= SUBPIXEL;
+        mFrame.left += mSubpixelSmoothingLeft;
+        mFrame.top += mSubpixelSmoothingLeft;
+        mFrame.right -= mSubpixelSmoothingRight;
+        mFrame.bottom -= mSubpixelSmoothingRight;
 
         // set the battery charging color
         mBatteryPaint.setColor(tracker.plugged ? mChargeColor : getColorForLevel(level));
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index f4d0669..8d35eb0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -27,6 +27,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.UserInfo;
 import android.media.AudioManager;
 import android.media.SoundPool;
 import android.os.Bundle;
@@ -302,6 +303,13 @@
         @Override
         public void onUserSwitchComplete(int userId) {
             mSwitchingUser = false;
+            if (userId != UserHandle.USER_OWNER) {
+                UserInfo info = UserManager.get(mContext).getUserInfo(userId);
+                if (info != null && info.isGuest()) {
+                    // If we just switched to a guest, try to dismiss keyguard.
+                    dismiss();
+                }
+            }
         }
 
         @Override
@@ -581,6 +589,8 @@
             final boolean lockImmediately =
                 mLockPatternUtils.getPowerButtonInstantlyLocks() || !mLockPatternUtils.isSecure();
 
+            notifyScreenOffLocked();
+
             if (mExitSecureCallback != null) {
                 if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
                 try {
@@ -593,7 +603,6 @@
                     hideLocked();
                 }
             } else if (mShowing) {
-                notifyScreenOffLocked();
                 resetStateLocked();
             } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
                    || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
@@ -1133,7 +1142,6 @@
         }
 
         handleHide();
-        sendUserPresentBroadcast();
     }
 
     private void sendUserPresentBroadcast() {
@@ -1304,6 +1312,7 @@
             mHideAnimationRun = false;
             updateActivityLockScreenState();
             adjustStatusBarLocked();
+            sendUserPresentBroadcast();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 98adf81..8743207 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -91,7 +91,7 @@
         if (cb == null) return;
 
         final Resources r = mContext.getResources();
-        state.iconId = cb.noSim ? R.drawable.stat_sys_no_sim
+        state.iconId = cb.noSim ? R.drawable.ic_qs_no_sim
                 : !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
                 : cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
                 : R.drawable.ic_qs_signal_no_signal;
@@ -99,7 +99,7 @@
         state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) && !cb.wifiConnected
                 ? cb.dataTypeIconId
                 : 0;
-        state.filter = state.iconId != R.drawable.stat_sys_no_sim;
+        state.filter = state.iconId != R.drawable.ic_qs_no_sim;
         state.activityIn = cb.enabled && cb.activityIn;
         state.activityOut = cb.enabled && cb.activityOut;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 46d8a9b..d1dc5d2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -60,7 +60,11 @@
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
         final boolean locationEnabled =  mController.isLocationEnabled();
-        state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
+
+        // Work around for bug 15916487: don't show location tile on top of lock screen. After the
+        // bug is fixed, this should be reverted to only hiding it on secure lock screens:
+        // state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
+        state.visible = !mKeyguard.isShowing();
         state.value = locationEnabled;
         if (locationEnabled) {
             state.iconId = R.drawable.ic_qs_location_on;
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index 3e2ef94..b7434fd 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -34,14 +34,12 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 
 import com.android.systemui.R;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 
 import java.util.ArrayList;
@@ -205,8 +203,8 @@
         Drawable icon = getFullResIcon(td.resolveInfo, pm);
         if (td.userId != UserHandle.myUserId()) {
             // Need to badge the icon
-            final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-            icon = um.getBadgedDrawableForUser(icon, new UserHandle(td.userId));
+            icon = mContext.getPackageManager().getUserBadgedDrawableForDensity(icon,
+                    new UserHandle(td.userId), null, 0);
         }
         if (DEBUG) Log.v(TAG, "Loaded bitmap for task "
                 + td + ": " + thumbnail);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 6cae7d4..ec7799a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -296,7 +296,7 @@
                         mSearchAppWidgetInfo);
                 Bundle opts = new Bundle();
                 opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
-                        AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+                        AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
                 mSearchAppWidgetHostView.updateAppWidgetOptions(opts);
                 // Set the padding to 0 for this search widget
                 mSearchAppWidgetHostView.setPadding(0, 0, 0, 0);
@@ -355,6 +355,8 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        // For the non-primary user, ensure that the SystemSericesProxy is initialized
+        RecentsTaskLoader.initialize(this);
 
         // Initialize the loader and the configuration
         mConfig = RecentsConfiguration.reinitialize(this,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index e27c0ac..07a42bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -49,7 +49,6 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.Pair;
@@ -79,7 +78,6 @@
     AppWidgetManager mAwm;
     PackageManager mPm;
     IPackageManager mIpm;
-    UserManager mUm;
     SearchManager mSm;
     WindowManager mWm;
     Display mDisplay;
@@ -103,7 +101,6 @@
         mIam = ActivityManagerNative.getDefault();
         mAwm = AppWidgetManager.getInstance(context);
         mPm = context.getPackageManager();
-        mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mIpm = AppGlobals.getPackageManager();
         mSm = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
         mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
@@ -343,7 +340,7 @@
      * necessary.
      */
     public Drawable getActivityIcon(ActivityInfo info, int userId) {
-        if (mPm == null || mUm == null) return null;
+        if (mPm == null) return null;
 
         // If we are mocking, then return a mock label
         if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
@@ -359,7 +356,7 @@
      */
     public Drawable getBadgedIcon(Drawable icon, int userId) {
         if (userId != UserHandle.myUserId()) {
-            icon = mUm.getBadgedDrawableForUser(icon, new UserHandle(userId));
+            icon = mPm.getUserBadgedDrawableForDensity(icon, new UserHandle(userId), null, 0);
         }
         return icon;
     }
@@ -392,7 +389,7 @@
 
         // Find the first Recents widget from the same package as the global assist activity
         List<AppWidgetProviderInfo> widgets = mAwm.getInstalledProviders(
-                AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+                AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
         for (AppWidgetProviderInfo info : widgets) {
             if (info.provider.getPackageName().equals(mAssistComponent.getPackageName())) {
                 return info;
@@ -418,7 +415,7 @@
         int searchWidgetId = host.allocateAppWidgetId();
         Bundle opts = new Bundle();
         opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
-                AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+                AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
         if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, searchWidgetInfo.provider, opts)) {
             return null;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 500bf45..c869ba4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -88,6 +88,9 @@
             = new PathInterpolator(0.6f, 0, 0.5f, 1);
     private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR
             = new PathInterpolator(0, 0, 0.5f, 1);
+    private final int mTintedRippleColor;
+    private final int mLowPriorityRippleColor;
+    private final int mNormalRippleColor;
 
     private boolean mDimmed;
     private boolean mDark;
@@ -118,7 +121,6 @@
 
     private NotificationBackgroundView mBackgroundNormal;
     private NotificationBackgroundView mBackgroundDimmed;
-    private NotificationScrimView mScrimView;
     private ObjectAnimator mBackgroundAnimator;
     private RectF mAppearAnimationRect = new RectF();
     private PorterDuffColorFilter mAppearAnimationFilter;
@@ -153,6 +155,12 @@
         mNormalColor = getResources().getColor(R.color.notification_material_background_color);
         mLowPriorityColor = getResources().getColor(
                 R.color.notification_material_background_low_priority_color);
+        mTintedRippleColor = context.getResources().getColor(
+                R.color.notification_ripple_tinted_color);
+        mLowPriorityRippleColor = context.getResources().getColor(
+                R.color.notification_ripple_color_low_priority);
+        mNormalRippleColor = context.getResources().getColor(
+                R.color.notification_ripple_untinted_color);
     }
 
     @Override
@@ -164,8 +172,6 @@
         mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
         updateBackground();
         updateBackgroundTint();
-        mScrimView = (NotificationScrimView) findViewById(R.id.scrim_view);
-        setScrimAmount(0);
     }
 
     private final Runnable mTapTimeoutRunnable = new Runnable() {
@@ -191,6 +197,16 @@
         }
     }
 
+    @Override
+    protected void drawableStateChanged() {
+        super.drawableStateChanged();
+        if (mDimmed) {
+            mBackgroundDimmed.setState(getDrawableState());
+        } else {
+            mBackgroundNormal.setState(getDrawableState());
+        }
+    }
+
     private boolean handleTouchEventDimmed(MotionEvent event) {
         int action = event.getActionMasked();
         switch (action) {
@@ -372,12 +388,15 @@
 
     private void updateBackgroundTint() {
         int color = getBackgroundColor();
+        int rippleColor = getRippleColor();
         if (color == mNormalColor) {
             // We don't need to tint a normal notification
             color = 0;
         }
         mBackgroundDimmed.setTint(color);
         mBackgroundNormal.setTint(color);
+        mBackgroundDimmed.setRippleColor(rippleColor);
+        mBackgroundNormal.setRippleColor(rippleColor);
     }
 
     private void fadeBackground() {
@@ -443,7 +462,6 @@
         setPivotY(actualHeight / 2);
         mBackgroundNormal.setActualHeight(actualHeight);
         mBackgroundDimmed.setActualHeight(actualHeight);
-        mScrimView.setActualHeight(actualHeight);
     }
 
     @Override
@@ -451,7 +469,6 @@
         super.setClipTopAmount(clipTopAmount);
         mBackgroundNormal.setClipTopAmount(clipTopAmount);
         mBackgroundDimmed.setClipTopAmount(clipTopAmount);
-        mScrimView.setClipTopAmount(clipTopAmount);
     }
 
     @Override
@@ -474,11 +491,6 @@
         }
     }
 
-    @Override
-    public void setScrimAmount(float scrimAmount) {
-        mScrimView.setAlpha(scrimAmount);
-    }
-
     private void startAppearAnimation(boolean isAppearing, float translationDirection, long delay,
             long duration, final Runnable onFinishedRunnable) {
         if (mAppearAnimator != null) {
@@ -618,6 +630,18 @@
         }
     }
 
+    private int getRippleColor() {
+        if (mBgTint != 0) {
+            return mTintedRippleColor;
+        } else if (mShowingLegacyBackground) {
+            return mTintedRippleColor;
+        } else if (mIsBelowSpeedBump) {
+            return mLowPriorityRippleColor;
+        } else {
+            return mNormalRippleColor;
+        }
+    }
+
     /**
      * When we draw the appear animation, we render the view in a bitmap and render this bitmap
      * as a shader of a rect. This call creates the Bitmap and switches the drawing mode,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index ce29407..1c4556f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -34,13 +34,11 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Build;
@@ -96,6 +94,7 @@
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 
 import static com.android.keyguard.KeyguardHostView.OnDismissAction;
@@ -177,7 +176,7 @@
     // public mode, private notifications, etc
     private boolean mLockscreenPublicMode = false;
     private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
-    private NotificationColorUtil mNotificationColorUtil = NotificationColorUtil.getInstance();
+    private NotificationColorUtil mNotificationColorUtil;
 
     private UserManager mUserManager;
 
@@ -435,6 +434,8 @@
         mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
 
+        mNotificationColorUtil = NotificationColorUtil.getInstance(mContext);
+
         mNotificationData = new NotificationData(this);
 
         mDreamManager = IDreamManager.Stub.asInterface(
@@ -557,6 +558,8 @@
             // disable lockscreen notifications until user acts on the banner.
             Settings.Secure.putInt(mContext.getContentResolver(),
                     Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0);
 
             final String packageName = mContext.getPackageName();
             PendingIntent cancelIntent = PendingIntent.getBroadcast(mContext, 0,
@@ -717,11 +720,23 @@
                entry.expandedBig.findViewById(com.android.internal.R.id.media_actions) != null;
     }
 
+    // The gear button in the guts that links to the app's own notification settings
+    private void startAppOwnNotificationSettingsActivity(Intent intent,
+            final int notificationId, final String notificationTag, final int appUid) {
+        intent.putExtra("notification_id", notificationId);
+        intent.putExtra("notification_tag", notificationTag);
+        startNotificationGutsIntent(intent, appUid);
+    }
+
+    // The (i) button in the guts that links to the system notification settings for that app
     private void startAppNotificationSettingsActivity(String packageName, final int appUid) {
         final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
         intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
         intent.putExtra(Settings.EXTRA_APP_UID, appUid);
+        startNotificationGutsIntent(intent, appUid);
+    }
 
+    private void startNotificationGutsIntent(final Intent intent, final int appUid) {
         final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
         dismissKeyguardThenExecute(new OnDismissAction() {
             @Override
@@ -1128,7 +1143,7 @@
                 entry.notification.getUser().getIdentifier());
 
         int maxHeight = mRowMaxHeight;
-        StatusBarNotification sbn = entry.notification;
+        final StatusBarNotification sbn = entry.notification;
         RemoteViews contentView = sbn.getNotification().contentView;
         RemoteViews bigContentView = sbn.getNotification().bigContentView;
 
@@ -1197,6 +1212,8 @@
         ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(entry.notification.getPostTime());
         ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
         final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
+        final View appSettingsButton
+                = guts.findViewById(R.id.notification_inspect_app_provided_settings);
         if (appUid >= 0) {
             final int appUidF = appUid;
             settingsButton.setOnClickListener(new View.OnClickListener() {
@@ -1204,8 +1221,33 @@
                     startAppNotificationSettingsActivity(pkg, appUidF);
                 }
             });
+
+            final Intent appSettingsQueryIntent
+                    = new Intent(Intent.ACTION_MAIN)
+                        .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
+                        .setPackage(pkg);
+            List<ResolveInfo> infos = pmUser.queryIntentActivities(appSettingsQueryIntent, 0);
+            if (infos.size() > 0) {
+                appSettingsButton.setVisibility(View.VISIBLE);
+                appSettingsButton.setContentDescription(
+                        mContext.getResources().getString(
+                                R.string.status_bar_notification_app_settings_title,
+                                appname
+                        ));
+                final Intent appSettingsLaunchIntent = new Intent(appSettingsQueryIntent)
+                        .setClassName(pkg, infos.get(0).activityInfo.name);
+                appSettingsButton.setOnClickListener(new View.OnClickListener() {
+                    public void onClick(View v) {
+                        startAppOwnNotificationSettingsActivity(appSettingsLaunchIntent,
+                                sbn.getId(),
+                                sbn.getTag(),
+                                appUidF);
+                    }
+                });
+            }
         } else {
             settingsButton.setVisibility(View.GONE);
+            appSettingsButton.setVisibility(View.GONE);
         }
 
         workAroundBadLayerDrawableOpacity(row);
@@ -1281,7 +1323,9 @@
             // Add a basic notification template
             publicViewLocal = LayoutInflater.from(mContext).inflate(
                     com.android.internal.R.layout.notification_template_material_base,
-                    expandedPublic, true);
+                    expandedPublic, false);
+            publicViewLocal.setIsRootNamespace(true);
+            expandedPublic.setContractedChild(publicViewLocal);
 
             final TextView title = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.title);
             try {
@@ -1305,7 +1349,7 @@
 
             Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic);
             icon.setImageDrawable(iconDrawable);
-            if (mNotificationColorUtil.isGrayscale(iconDrawable)) {
+            if (mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) {
                 icon.setBackgroundResource(
                         com.android.internal.R.drawable.notification_icon_legacy_bg);
                 int padding = mContext.getResources().getDimensionPixelSize(
@@ -1314,8 +1358,8 @@
             }
 
             if (profileBadge != null) {
-                Drawable profileDrawable
-                        = mUserManager.getBadgeForUser(entry.notification.getUser(), 0);
+                Drawable profileDrawable = mContext.getPackageManager().getUserBadgeForDensity(
+                        entry.notification.getUser(), 0);
                 if (profileDrawable != null) {
                     profileBadge.setImageDrawable(profileDrawable);
                     profileBadge.setVisibility(View.VISIBLE);
@@ -1581,10 +1625,11 @@
                 }
             }
             boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
-            if (onKeyguard && (visibleNotifications >= maxKeyguardNotifications
-                    || !showOnKeyguard)) {
+            if ((isLockscreenPublicMode() && !showOnKeyguard) ||
+                    (onKeyguard && (visibleNotifications >= maxKeyguardNotifications
+                            || !showOnKeyguard))) {
                 entry.row.setVisibility(View.GONE);
-                if (showOnKeyguard) {
+                if (onKeyguard && showOnKeyguard) {
                     mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
                 }
             } else {
@@ -1902,6 +1947,13 @@
     }
 
     protected boolean shouldInterrupt(StatusBarNotification sbn) {
+        if (mNotificationData.shouldFilterOut(sbn)) {
+            if (DEBUG) {
+                Log.d(TAG, "Skipping HUN check for " + sbn.getKey() + " since it's filtered out.");
+            }
+            return false;
+        }
+
         Notification notification = sbn.getNotification();
         // some predicates to make the boolean logic legible
         boolean isNoisy = (notification.defaults & Notification.DEFAULT_SOUND) != 0
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index dfcc408..c13593a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -17,10 +17,15 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 
+import android.widget.ImageView;
 import com.android.systemui.R;
 
 public class ExpandableNotificationRow extends ActivatableNotificationView {
@@ -62,6 +67,51 @@
     private boolean mWasReset;
     private NotificationGuts mGuts;
 
+    public void setIconAnimationRunning(boolean running) {
+        setIconAnimationRunning(running, mPublicLayout);
+        setIconAnimationRunning(running, mPrivateLayout);
+    }
+
+    private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
+        if (layout != null) {
+            View contractedChild = layout.getContractedChild();
+            View expandedChild = layout.getExpandedChild();
+            setIconAnimationRunningForChild(running, contractedChild);
+            setIconAnimationRunningForChild(running, expandedChild);
+        }
+    }
+
+    private void setIconAnimationRunningForChild(boolean running, View child) {
+        if (child != null) {
+            ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
+            setIconRunning(icon, running);
+            ImageView rightIcon = (ImageView) child.findViewById(
+                    com.android.internal.R.id.right_icon);
+            setIconRunning(rightIcon, running);
+        }
+    }
+
+    private void setIconRunning(ImageView imageView, boolean running) {
+        if (imageView != null) {
+            Drawable drawable = imageView.getDrawable();
+            if (drawable instanceof AnimationDrawable) {
+                AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
+                if (running) {
+                    animationDrawable.start();
+                } else {
+                    animationDrawable.stop();
+                }
+            } else if (drawable instanceof AnimatedVectorDrawable) {
+                AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
+                if (running) {
+                    animationDrawable.start();
+                } else {
+                    animationDrawable.stop();
+                }
+            }
+        }
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
@@ -97,6 +147,7 @@
         mMaxExpandHeight = 0;
         mWasReset = true;
         onHeightReset();
+        requestLayout();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 2838747..c8f756e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -255,8 +255,6 @@
 
     public abstract void performAddAnimation(long delay, long duration);
 
-    public abstract void setScrimAmount(float scrimAmount);
-
     public void setBelowSpeedBump(boolean below) {
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 5878ae1..a4161f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -251,15 +251,19 @@
     }
 
     public void setCircleRadius(float circleRadius) {
-        setCircleRadius(circleRadius, false);
+        setCircleRadius(circleRadius, false, false);
+    }
+
+    public void setCircleRadius(float circleRadius, boolean slowAnimation) {
+        setCircleRadius(circleRadius, slowAnimation, false);
     }
 
     public void setCircleRadiusWithoutAnimation(float circleRadius) {
         cancelAnimator(mCircleAnimator);
-        setCircleRadius(circleRadius, true);
+        setCircleRadius(circleRadius, false ,true);
     }
 
-    private void setCircleRadius(float circleRadius, boolean noAnimation) {
+    private void setCircleRadius(float circleRadius, boolean slowAnimation, boolean noAnimation) {
 
         // Check if we need a new animation
         boolean radiusHidden = (mCircleAnimator != null && mCircleWillBeHidden)
@@ -292,10 +296,13 @@
                     ? mDisappearInterpolator
                     : mAppearInterpolator;
             animator.setInterpolator(interpolator);
-            float durationFactor = Math.abs(mCircleRadius - circleRadius)
-                    / (float) mMinBackgroundRadius;
-            long duration = (long) (CIRCLE_APPEAR_DURATION * durationFactor);
-            duration = Math.min(duration, CIRCLE_DISAPPEAR_MAX_DURATION);
+            long duration = 250;
+            if (!slowAnimation) {
+                float durationFactor = Math.abs(mCircleRadius - circleRadius)
+                        / (float) mMinBackgroundRadius;
+                duration = (long) (CIRCLE_APPEAR_DURATION * durationFactor);
+                duration = Math.min(duration, CIRCLE_DISAPPEAR_MAX_DURATION);
+            }
             animator.setDuration(duration);
             animator.start();
             if (mPreviewView != null && mPreviewView.getVisibility() == View.VISIBLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index ad274b0..5db680a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -35,15 +35,9 @@
     private Drawable mBackground;
     private int mClipTopAmount;
     private int mActualHeight;
-    private final int mTintedRippleColor;
-    private final int mNormalRippleColor;
 
     public NotificationBackgroundView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mTintedRippleColor = context.getResources().getColor(
-                R.color.notification_ripple_tinted_color);
-        mNormalRippleColor = context.getResources().getColor(
-                R.color.notification_ripple_untinted_color);
     }
 
     @Override
@@ -103,17 +97,10 @@
     }
 
     public void setTint(int tintColor) {
-        int rippleColor;
         if (tintColor != 0) {
             mBackground.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP);
-            rippleColor = mTintedRippleColor;
         } else {
             mBackground.clearColorFilter();
-            rippleColor = mNormalRippleColor;
-        }
-        if (mBackground instanceof RippleDrawable) {
-            RippleDrawable ripple = (RippleDrawable) mBackground;
-            ripple.setColor(ColorStateList.valueOf(rippleColor));
         }
         invalidate();
     }
@@ -138,4 +125,15 @@
         // Prevents this view from creating a layer when alpha is animating.
         return false;
     }
+
+    public void setState(int[] drawableState) {
+        mBackground.setState(drawableState);
+    }
+
+    public void setRippleColor(int color) {
+        if (mBackground instanceof RippleDrawable) {
+            RippleDrawable ripple = (RippleDrawable) mBackground;
+            ripple.setColor(ColorStateList.valueOf(color));
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 8b4c2c4..e31eb7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -88,6 +88,14 @@
         mContractedVisible = true;
     }
 
+    public View getContractedChild() {
+        return mContractedChild;
+    }
+
+    public View getExpandedChild() {
+        return mExpandedChild;
+    }
+
     public void setContractedChild(View child) {
         if (mContractedChild != null) {
             mContractedChild.animate().cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 454041c..ca1fbe0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar;
 
 import android.app.Notification;
+import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
@@ -99,15 +100,26 @@
 
         @Override
         public int compare(Entry a, Entry b) {
-            String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
-
             // Upsort current media notification.
+            String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
             boolean aMedia = a.key.equals(mediaNotification);
             boolean bMedia = b.key.equals(mediaNotification);
             if (aMedia != bMedia) {
                 return aMedia ? -1 : 1;
             }
 
+            final StatusBarNotification na = a.notification;
+            final StatusBarNotification nb = b.notification;
+
+            // Upsort PRIORITY_MAX system notifications
+            boolean aSystemMax = na.getNotification().priority >= Notification.PRIORITY_MAX &&
+                    isSystemNotification(na);
+            boolean bSystemMax = nb.getNotification().priority >= Notification.PRIORITY_MAX &&
+                    isSystemNotification(nb);
+            if (aSystemMax != bSystemMax) {
+                return aSystemMax ? -1 : 1;
+            }
+
             // RankingMap as received from NoMan.
             if (mRankingMap != null) {
                 mRankingMap.getRanking(a.key, mRankingA);
@@ -115,8 +127,6 @@
                 return mRankingA.getRank() - mRankingB.getRank();
             }
 
-            final StatusBarNotification na = a.notification;
-            final StatusBarNotification nb = b.notification;
             int d = nb.getScore() - na.getScore();
             if (a.interruption != b.interruption) {
                 return a.interruption ? -1 : 1;
@@ -173,6 +183,14 @@
         return false;
     }
 
+    public int getVisibilityOverride(String key) {
+        if (mRankingMap != null) {
+            mRankingMap.getRanking(key, mTmpRanking);
+            return mTmpRanking.getVisibilityOverride();
+        }
+        return NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+    }
+
     private void updateRankingAndSort(RankingMap ranking) {
         if (ranking != null) {
             mRankingMap = ranking;
@@ -221,7 +239,7 @@
         return mGroupsWithSummaries.contains(groupKey);
     }
 
-    private boolean shouldFilterOut(StatusBarNotification sbn) {
+    boolean shouldFilterOut(StatusBarNotification sbn) {
         if (!(mEnvironment.isDeviceProvisioned() ||
                 showNotificationEvenIfUnprovisioned(sbn))) {
             return true;
@@ -296,11 +314,16 @@
         pw.println("      tickerText=\"" + n.getNotification().tickerText + "\"");
     }
 
+    private static boolean isSystemNotification(StatusBarNotification sbn) {
+        String sbnPackage = sbn.getPackageName();
+        return "android".equals(sbnPackage) || "com.android.systemui".equals(sbnPackage);
+    }
+
     /**
      * Provides access to keyguard state and user settings dependent data.
      */
     public interface Environment {
-        public boolean shouldHideSensitiveContents(int userId);
+        public boolean shouldHideSensitiveContents(int userid);
         public boolean isDeviceProvisioned();
         public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
         public String getCurrentMediaNotificationKey();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
index c75bd28..c4c9dac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
@@ -36,7 +36,7 @@
     private TextView mMoreText;
     private int mTintColor;
     private int mIconSize;
-    private NotificationColorUtil mNotificationColorUtil = new NotificationColorUtil();
+    private NotificationColorUtil mNotificationColorUtil;
 
     public NotificationOverflowIconsView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -45,6 +45,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        mNotificationColorUtil = NotificationColorUtil.getInstance(getContext());
         mTintColor = getResources().getColor(R.color.keyguard_overflow_content_color);
         mIconSize = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_icon_size);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java
deleted file mode 100644
index 440b2c1..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java
+++ /dev/null
@@ -1,79 +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.statusbar;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.View;
-
-import com.android.keyguard.R;
-
-/**
- * A view that can be used for both the dimmed and normal background of an notification.
- */
-public class NotificationScrimView extends View {
-
-    private Drawable mBackground;
-    private int mClipTopAmount;
-    private int mActualHeight;
-
-    public NotificationScrimView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mBackground = getResources().getDrawable(R.drawable.notification_scrim);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        draw(canvas, mBackground);
-    }
-
-    private void draw(Canvas canvas, Drawable drawable) {
-        if (drawable != null) {
-            drawable.setBounds(0, mClipTopAmount, getWidth(), mActualHeight);
-            drawable.draw(canvas);
-        }
-    }
-
-    @Override
-    protected boolean verifyDrawable(Drawable who) {
-        return super.verifyDrawable(who) || who == mBackground;
-    }
-
-    public void setActualHeight(int actualHeight) {
-        mActualHeight = actualHeight;
-        invalidate();
-    }
-
-    public int getActualHeight() {
-        return mActualHeight;
-    }
-
-    public void setClipTopAmount(int clipTopAmount) {
-        mClipTopAmount = clipTopAmount;
-        invalidate();
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-
-        // Prevents this view from creating a layer when alpha is animating.
-        return false;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 9da209a..5883c26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -49,7 +49,7 @@
 
     ViewGroup mWifiGroup, mMobileGroup;
     ImageView mWifi, mMobile, mMobileType, mAirplane;
-    View mSpacer;
+    View mWifiAirplaneSpacer;
 
     public SignalClusterView(Context context) {
         this(context, null);
@@ -77,8 +77,8 @@
         mMobileGroup    = (ViewGroup) findViewById(R.id.mobile_combo);
         mMobile         = (ImageView) findViewById(R.id.mobile_signal);
         mMobileType     = (ImageView) findViewById(R.id.mobile_type);
-        mSpacer         =             findViewById(R.id.spacer);
         mAirplane       = (ImageView) findViewById(R.id.airplane);
+        mWifiAirplaneSpacer =         findViewById(R.id.wifi_airplane_spacer);
 
         apply();
     }
@@ -90,7 +90,6 @@
         mMobileGroup    = null;
         mMobile         = null;
         mMobileType     = null;
-        mSpacer         = null;
         mAirplane       = null;
 
         super.onDetachedFromWindow();
@@ -198,10 +197,10 @@
             mAirplane.setVisibility(View.GONE);
         }
 
-        if (mMobileVisible && mWifiVisible && mIsAirplaneMode) {
-            mSpacer.setVisibility(View.INVISIBLE);
+        if (mIsAirplaneMode && mWifiVisible) {
+            mWifiAirplaneSpacer.setVisibility(View.VISIBLE);
         } else {
-            mSpacer.setVisibility(View.GONE);
+            mWifiAirplaneSpacer.setVisibility(View.GONE);
         }
 
         if (DEBUG) Log.d(TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
index 816612b..1fc8744 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
@@ -126,9 +126,4 @@
         // TODO: Use duration
         performVisibilityAnimation(true, delay);
     }
-
-    @Override
-    public void setScrimAmount(float scrimAmount) {
-        // We don't need to scrim the speedbumps
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
index 62a492e..c620046 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
@@ -127,11 +127,6 @@
     }
 
     @Override
-    public void setScrimAmount(float scrimAmount) {
-        // We don't need to scrim the dismissView
-    }
-
-    @Override
     public boolean hasOverlappingRendering() {
         return false;
     }
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 eca8e6a..a9c701a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -20,8 +20,6 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.content.Context;
-import android.os.PowerManager;
-import android.os.SystemClock;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
@@ -85,9 +83,9 @@
         mContext = context;
         mCallback = callback;
         initIcons();
-        updateIcon(mLeftIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false);
-        updateIcon(mCenterIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false);
-        updateIcon(mRightIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false);
+        updateIcon(mLeftIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false, false);
+        updateIcon(mCenterIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false, false);
+        updateIcon(mRightIcon, 0.0f, SWIPE_RESTING_ALPHA_AMOUNT, false, false);
         initDimens();
     }
 
@@ -295,8 +293,7 @@
         float vel = getCurrentVelocity();
 
         // We snap back if the current translation is not far enough
-        boolean snapBack = Math.abs(mTranslation) < Math.abs(mTranslationOnDown)
-                + mMinTranslationAmount;
+        boolean snapBack = isBelowFalsingThreshold();
 
         // or if the velocity is in the opposite direction.
         boolean velIsInWrongDirection = vel * mTranslation < 0;
@@ -305,6 +302,11 @@
         fling(vel, snapBack || forceSnapBack);
     }
 
+    private boolean isBelowFalsingThreshold() {
+        return Math.abs(mTranslation) < Math.abs(mTranslationOnDown)
+                + mMinTranslationAmount;
+    }
+
     private void fling(float vel, final boolean snapBack) {
         float target = mTranslation < 0 ? -mCallback.getPageWidth() : mCallback.getPageWidth();
         target = snapBack ? 0 : target;
@@ -355,13 +357,14 @@
 
             boolean animateIcons = isReset && animateReset;
             float radius = getRadiusFromTranslation(absTranslation);
+            boolean slowAnimation = isReset && isBelowFalsingThreshold();
             if (!isReset) {
-                updateIcon(targetView, radius, alpha, false);
+                updateIcon(targetView, radius, alpha, false, false);
             } else {
-                updateIcon(targetView, 0.0f, fadeOutAlpha, animateIcons);
+                updateIcon(targetView, 0.0f, fadeOutAlpha, animateIcons, slowAnimation);
             }
-            updateIcon(otherView, 0.0f, fadeOutAlpha, animateIcons);
-            updateIcon(mCenterIcon, 0.0f, fadeOutAlpha, animateIcons);
+            updateIcon(otherView, 0.0f, fadeOutAlpha, animateIcons, slowAnimation);
+            updateIcon(mCenterIcon, 0.0f, fadeOutAlpha, animateIcons, slowAnimation);
 
             mTranslation = translation;
         }
@@ -392,16 +395,16 @@
     }
 
     public void animateHideLeftRightIcon() {
-        updateIcon(mRightIcon, 0f, 0f, true);
-        updateIcon(mLeftIcon, 0f, 0f, true);
+        updateIcon(mRightIcon, 0f, 0f, true, false);
+        updateIcon(mLeftIcon, 0f, 0f, true, false);
     }
 
     private void updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha,
-            boolean animate) {
+            boolean animate, boolean slowRadiusAnimation) {
         if (view.getVisibility() != View.VISIBLE) {
             return;
         }
-        view.setCircleRadius(circleRadius);
+        view.setCircleRadius(circleRadius, slowRadiusAnimation);
         updateIconAlpha(view, alpha, animate);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index d7144da..dc49118 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -30,6 +30,7 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 /**
  * Container for image of the multi user switcher (tappable).
@@ -90,9 +91,21 @@
 
         if (isClickable()) {
             final UserManager um = UserManager.get(getContext());
-            String text = mContext.getString(um.isUserSwitcherEnabled()
-                    ? R.string.accessibility_multi_user_switch_switcher
-                    : R.string.accessibility_multi_user_switch_quick_contact);
+            String text;
+            if (um.isUserSwitcherEnabled()) {
+                UserSwitcherController controller = mQsPanel.getHost()
+                        .getUserSwitcherController();
+                String currentUser = controller.getCurrentUserName(mContext);
+                if (TextUtils.isEmpty(currentUser)) {
+                    text = mContext.getString(R.string.accessibility_multi_user_switch_switcher);
+                } else {
+                    text = mContext.getString(
+                            R.string.accessibility_multi_user_switch_switcher_with_current,
+                            currentUser);
+                }
+            } else {
+                text = mContext.getString(R.string.accessibility_multi_user_switch_quick_contact);
+            }
             if (!TextUtils.isEmpty(text)) {
                 event.getText().add(text);
             }
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 5a94395..cf5aebc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -35,6 +35,7 @@
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
+import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.statusbar.ExpandableView;
@@ -65,7 +66,7 @@
     private KeyguardStatusBarView mKeyguardStatusBar;
     private View mQsContainer;
     private QSPanel mQsPanel;
-    private View mKeyguardStatusView;
+    private KeyguardStatusView mKeyguardStatusView;
     private ObservableScrollView mScrollView;
     private TextView mClockView;
     private View mReserveNotificationSpace;
@@ -174,7 +175,7 @@
         mHeader = (StatusBarHeaderView) findViewById(R.id.header);
         mHeader.setOnClickListener(this);
         mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
-        mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
+        mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
         mQsContainer = findViewById(R.id.quick_settings_container);
         mQsPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
         mClockView = (TextView) findViewById(R.id.clock_view);
@@ -547,7 +548,7 @@
     }
 
     private boolean flingExpandsQs(float vel) {
-        if (!mQsTouchAboveFalsingThreshold && mStatusBarState == StatusBarState.KEYGUARD) {
+        if (isBelowFalsingThreshold()) {
             return false;
         }
         if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
@@ -557,6 +558,10 @@
         }
     }
 
+    private boolean isBelowFalsingThreshold() {
+        return !mQsTouchAboveFalsingThreshold && mStatusBar.isFalsingThresholdNeeded();
+    }
+
     private float getQsExpansionFraction() {
         return Math.min(1f, (mQsExpansionHeight - mQsMinExpansionHeight)
                 / (getTempQsMaxExpansion() - mQsMinExpansionHeight));
@@ -1042,7 +1047,6 @@
         int startDistance = mQsMinExpansionHeight + mNotificationScrimWaitDistance;
         float progress = (height - startDistance) / (mQsMaxExpansionHeight - startDistance);
         progress = Math.max(0.0f, Math.min(progress, 1.0f));
-        mNotificationStackScroller.setScrimAlpha(progress);
     }
 
     private float getHeaderExpansionFraction() {
@@ -1121,9 +1125,16 @@
             }
             return;
         }
+        boolean belowFalsingThreshold = isBelowFalsingThreshold();
+        if (belowFalsingThreshold) {
+            vel = 0;
+        }
         mScrollView.setBlockFlinging(true);
         ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
         mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
+        if (belowFalsingThreshold) {
+            animator.setDuration(350);
+        }
         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
@@ -1267,7 +1278,7 @@
     private void updateNotificationTranslucency() {
         float alpha = (getNotificationsTopY() + mNotificationStackScroller.getItemHeight())
                 / (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize()
-                        + mNotificationStackScroller.getCollapseSecondCardPadding());
+                        - mNotificationStackScroller.getCollapseSecondCardPadding());
         alpha = Math.max(0, Math.min(alpha, 1));
         alpha = (float) Math.pow(alpha, 0.75);
         if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) {
@@ -1691,9 +1702,9 @@
     }
 
     public void setEmptyDragAmount(float amount) {
-        float factor = 1f;
+        float factor = 0.8f;
         if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
-            factor = 0.6f;
+            factor = 0.4f;
         } else if (!mStatusBar.hasActiveNotifications()) {
             factor = 0.4f;
         }
@@ -1749,4 +1760,8 @@
             mHeader.updateEverything();
         }
     };
+
+    public void onScreenTurnedOn() {
+        mKeyguardStatusView.refreshTime();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
index 53361dc..b842a6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
@@ -87,7 +87,9 @@
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
-        if (!mTouchEnabled) {
+        boolean isEndGuesture = (ev.getAction() == MotionEvent.ACTION_UP
+                || ev.getAction() == MotionEvent.ACTION_CANCEL);
+        if (!mTouchEnabled && !isEndGuesture) {
             return false;
         }
         return super.dispatchTouchEvent(ev);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 6127811..7261ea1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -479,7 +479,7 @@
      * @return whether a fling should expands the panel; contracts otherwise
      */
     protected boolean flingExpands(float vel, float vectorVel) {
-        if (!mTouchAboveFalsingThreshold && mStatusBar.isFalsingThresholdNeeded()) {
+        if (isBelowFalsingThreshold()) {
             return true;
         }
         if (Math.abs(vectorVel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
@@ -489,6 +489,10 @@
         }
     }
 
+    private boolean isBelowFalsingThreshold() {
+        return !mTouchAboveFalsingThreshold && mStatusBar.isFalsingThresholdNeeded();
+    }
+
     protected void fling(float vel, boolean expand) {
         cancelPeek();
         float target = expand ? getMaxPanelHeight() : 0.0f;
@@ -509,7 +513,14 @@
         mOverExpandedBeforeFling = getOverExpansionAmount() > 0f;
         ValueAnimator animator = createHeightAnimator(target);
         if (expand) {
+            boolean belowFalsingThreshold = isBelowFalsingThreshold();
+            if (belowFalsingThreshold) {
+                vel = 0;
+            }
             mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight());
+            if (belowFalsingThreshold) {
+                animator.setDuration(350);
+            }
         } else {
             mFlingAnimationUtils.applyDismissing(animator, mExpandedHeight, target, vel,
                     getHeight());
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 3b24bfd..271371a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -71,6 +71,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
@@ -112,6 +113,7 @@
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.DemoMode;
 import com.android.systemui.EventLogTags;
+import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.doze.DozeService;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -1228,11 +1230,12 @@
                 + " icon=" + icon);
         StatusBarIconView view = new StatusBarIconView(mContext, slot, null);
         view.set(icon);
-        mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
+        mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(
+                LayoutParams.WRAP_CONTENT, mIconSize));
         view = new StatusBarIconView(mContext, slot, null);
         view.set(icon);
-        mStatusIconsKeyguard.addView(view, viewIndex,
-                new LinearLayout.LayoutParams(mIconSize, mIconSize));
+        mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(
+                LayoutParams.WRAP_CONTENT, mIconSize));
     }
 
     public void updateIcon(String slot, int index, int viewIndex,
@@ -1412,11 +1415,12 @@
             // Display public version of the notification if we need to redact.
             final boolean hideSensitive =
                     !userAllowsPrivateNotificationsInPublic(ent.notification.getUserId());
-            boolean sensitive = vis == Notification.VISIBILITY_PRIVATE;
-            boolean showingPublic = sensitive && hideSensitive && isLockscreenPublicMode();
-            ent.row.setSensitive(sensitive && hideSensitive);
+            boolean sensitiveNote = vis == Notification.VISIBILITY_PRIVATE;
+            boolean sensitivePackage = packageHasVisibilityOverride(ent.notification.getKey());
+            boolean sensitive = (sensitiveNote && hideSensitive) || sensitivePackage;
+            boolean showingPublic = sensitive && isLockscreenPublicMode();
+            ent.row.setSensitive(sensitive);
             if (ent.autoRedacted && ent.legacy) {
-
                 // TODO: Also fade this? Or, maybe easier (and better), provide a dark redacted form
                 // for legacy auto redacted notifications.
                 if (showingPublic) {
@@ -1477,6 +1481,11 @@
         mShadeUpdates.check();
     }
 
+    private boolean packageHasVisibilityOverride(String key) {
+        return mNotificationData.getVisibilityOverride(key)
+                != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+    }
+
     private void updateClearAll() {
         boolean showDismissView =
                 mState != StatusBarState.KEYGUARD &&
@@ -1550,8 +1559,9 @@
             }
         }
 
-        for (View remove : toRemove) {
-            mNotificationIcons.removeView(remove);
+        final int toRemoveCount = toRemove.size();
+        for (int i = 0; i < toRemoveCount; i++) {
+            mNotificationIcons.removeView(toRemove.get(i));
         }
 
         for (int i=0; i<toShow.size(); i++) {
@@ -1560,6 +1570,18 @@
                 mNotificationIcons.addView(v, i, params);
             }
         }
+
+        // Resort notification icons
+        final int childCount = mNotificationIcons.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View actual = mNotificationIcons.getChildAt(i);
+            StatusBarIconView expected = toShow.get(i);
+            if (actual == expected) {
+                continue;
+            }
+            mNotificationIcons.removeView(expected);
+            mNotificationIcons.addView(expected, i);
+        }
     }
 
     @Override
@@ -3057,6 +3079,7 @@
         updateDisplaySize(); // populates mDisplayMetrics
 
         updateResources();
+        updateClockSize();
         repositionNavigationBar();
         updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
         updateShowSearchHoldoff();
@@ -3128,6 +3151,13 @@
         }
     }
 
+    private void updateClockSize() {
+        if (mStatusBarView == null) return;
+        TextView clock = (TextView) mStatusBarView.findViewById(R.id.clock);
+        if (clock != null) {
+            FontSizeUtils.updateFontSize(clock, R.dimen.status_bar_clock_size);
+        }
+    }
     protected void loadDimens() {
         final Resources res = mContext.getResources();
 
@@ -3757,7 +3787,9 @@
             row = (ExpandableNotificationRow) expandView;
             row.setUserExpanded(true);
         }
-        if (isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(mCurrentUserId)) {
+        boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId)
+                || !mShowLockscreenNotifications;
+        if (isLockscreenPublicMode() && fullShadeNeedsBouncer) {
             mLeaveOpenOnKeyguardHide = true;
             showBouncer();
             mDraggedDownRow = row;
@@ -3817,6 +3849,7 @@
 
     public void onScreenTurnedOn() {
         mStackScroller.setAnimationsEnabled(true);
+        mNotificationPanel.onScreenTurnedOn();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index e1fd779..1811d8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -42,6 +42,7 @@
     private DragDownHelper mDragDownHelper;
     private NotificationStackScrollLayout mStackScrollLayout;
     private NotificationPanelView mNotificationPanel;
+    private View mBrightnessMirror;
 
     PhoneStatusBar mService;
 
@@ -72,6 +73,7 @@
                 R.id.notification_stack_scroller);
         mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
         mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService);
+        mBrightnessMirror = findViewById(R.id.brightness_mirror);
 
         // We really need to be able to animate while window animations are going on
         // so that activities may be started asynchronously from panel animations
@@ -106,6 +108,19 @@
     }
 
     @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
+            // Disallow new pointers while the brightness mirror is visible. This is so that you
+            // can't touch anything other than the brightness slider while the mirror is showing
+            // and the rest of the panel is transparent.
+            if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
+                return false;
+            }
+        }
+        return super.dispatchTouchEvent(ev);
+    }
+
+    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         boolean intercept = false;
         if (mNotificationPanel.isFullyExpanded()
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 10f457a..d9a3e14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -46,7 +46,8 @@
     private static final String TAG = "StatusBar.KeyButtonView";
     private static final boolean DEBUG = false;
 
-    public static final float DEFAULT_QUIESCENT_ALPHA = 0.70f;
+    // TODO: Get rid of this
+    public static final float DEFAULT_QUIESCENT_ALPHA = 1f;
 
     private long mDownTime;
     private int mCode;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index d5b2548..61ed095 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -42,8 +42,7 @@
     // The name of the placeholder corresponding to the location request status icon.
     // This string corresponds to config_statusBarIcons in core/res/res/values/config.xml.
     public static final String LOCATION_STATUS_ICON_PLACEHOLDER = "location";
-    public static final int LOCATION_STATUS_ICON_ID
-        = R.drawable.stat_sys_device_access_location_found;
+    public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
 
     private static final int[] mHighPowerRequestAppOpArray
         = new int[] {AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 9b59814..4a6f1a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -63,7 +63,7 @@
     static final boolean DEBUG = false;
     static final boolean CHATTY = false; // additional diagnostics, but not logspew
 
-    private static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_signal_flightmode;
+    private static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
     private static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
 
     // telephony
@@ -833,7 +833,7 @@
                     visible = false;
                 }
             } else {
-                iconId = R.drawable.stat_sys_no_sim;
+                iconId = 0;
                 mNoSim = true;
                 visible = false; // no SIM? no data
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index adb71e7..52fa621 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -188,7 +188,7 @@
                     }
                 }
 
-                if (canCreateUser) {
+                if (!mSimpleUserSwitcher && canCreateUser) {
                     records.add(new UserRecord(null /* info */, null /* picture */,
                             false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
                             createIsRestricted));
@@ -334,6 +334,14 @@
         }
     }
 
+    public String getCurrentUserName(Context context) {
+        if (mUsers.isEmpty()) return null;
+        UserRecord item = mUsers.get(0);
+        if (item == null || item.info == null) return null;
+        if (item.isGuest) return context.getString(R.string.guest_nickname);
+        return item.info.name;
+    }
+
     public static abstract class BaseUserAdapter extends BaseAdapter {
 
         final UserSwitcherController mController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index ddb5cb8..8e677f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -32,7 +32,6 @@
     private float mOverScrollTopAmount;
     private float mOverScrollBottomAmount;
     private int mSpeedBumpIndex = -1;
-    private float mScrimAmount;
     private boolean mDark;
     private boolean mHideSensitive;
 
@@ -105,14 +104,6 @@
         }
     }
 
-    public void setScrimAmount(float scrimAmount) {
-        mScrimAmount = scrimAmount;
-    }
-
-    public float getScrimAmount() {
-        return mScrimAmount;
-    }
-
     public float getOverScrollAmount(boolean top) {
         return top ? mOverScrollTopAmount : mOverScrollBottomAmount;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 148b00c..6f477ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1467,6 +1467,7 @@
             // drawn when removed
             getOverlay().add(child);
         }
+        updateAnimationState(false, child);
 
         // Make sure the clipRect we might have set is removed
         child.setClipBounds(null);
@@ -1545,10 +1546,28 @@
         mStackScrollAlgorithm.notifyChildrenChanged(this);
         ((ExpandableView) child).setOnHeightChangedListener(this);
         generateAddAnimation(child, false /* fromMoreCard */);
+        updateAnimationState(mAnimationsEnabled && mIsExpanded, child);
     }
 
     public void setAnimationsEnabled(boolean animationsEnabled) {
         mAnimationsEnabled = animationsEnabled;
+        updateNotificationAnimationStates();
+    }
+
+    private void updateNotificationAnimationStates() {
+        boolean running = mIsExpanded && mAnimationsEnabled;
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            updateAnimationState(running, child);
+        }
+    }
+
+    private void updateAnimationState(boolean running, View child) {
+        if (child instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            row.setIconAnimationRunning(running);
+        }
     }
 
     public boolean isAddOrRemoveAnimationPending() {
@@ -1918,8 +1937,12 @@
     }
 
     private void setIsExpanded(boolean isExpanded) {
+        boolean changed = isExpanded != mIsExpanded;
         mIsExpanded = isExpanded;
         mStackScrollAlgorithm.setIsExpanded(isExpanded);
+        if (changed) {
+            updateNotificationAnimationStates();
+        }
     }
 
     @Override
@@ -2071,13 +2094,6 @@
         return true;
     }
 
-    public void setScrimAlpha(float progress) {
-        if (progress != mAmbientState.getScrimAmount()) {
-            mAmbientState.setScrimAmount(progress);
-            requestChildrenUpdate();
-        }
-    }
-
     /**
      * See {@link AmbientState#setDark}.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index fe855d9..7c4c0e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -172,7 +172,6 @@
         handleDraggedViews(ambientState, resultState, algorithmState);
         updateDimmedActivatedHideSensitive(ambientState, resultState, algorithmState);
         updateClipping(resultState, algorithmState);
-        updateScrimAmount(resultState, algorithmState, ambientState.getScrimAmount());
         updateSpeedBumpState(resultState, algorithmState, ambientState.getSpeedBumpIndex());
     }
 
@@ -189,16 +188,6 @@
         }
     }
 
-    private void updateScrimAmount(StackScrollState resultState,
-            StackScrollAlgorithmState algorithmState, float scrimAmount) {
-        int childCount = algorithmState.visibleChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            View child = algorithmState.visibleChildren.get(i);
-            StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
-            childViewState.scrimAmount = scrimAmount;
-        }
-    }
-
     private void updateClipping(StackScrollState resultState,
             StackScrollAlgorithmState algorithmState) {
         float previousNotificationEnd = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index f7a2824..0967ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -165,9 +165,6 @@
                 // apply speed bump state
                 child.setBelowSpeedBump(state.belowSpeedBump);
 
-                // apply scrimming
-                child.setScrimAmount(state.scrimAmount);
-
                 // apply clipping
                 float oldClipTopAmount = child.getClipTopAmount();
                 if (oldClipTopAmount != state.clipTopAmount) {
@@ -252,12 +249,6 @@
         boolean belowSpeedBump;
 
         /**
-         * A value between 0 and 1 indicating how much the view should be scrimmed.
-         * 1 means that the notifications will be darkened as much as possible.
-         */
-        float scrimAmount;
-
-        /**
          * The amount which the view should be clipped from the top. This is calculated to
          * perceive consistent shadows.
          */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 58d5813..ece82a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -251,9 +251,6 @@
         child.setHideSensitive(viewState.hideSensitive, mAnimationFilter.animateHideSensitive &&
                 !wasAdded && !noAnimation, delay, duration);
 
-        // apply scrimming
-        child.setScrimAmount(viewState.scrimAmount);
-
         if (wasAdded) {
             child.performAddAnimation(delay, mCurrentLength);
         }
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 41695c1..7b41391 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -413,7 +413,7 @@
             @Override
             public void onPress() {
                 Intent intent = new Intent(Settings.ACTION_SETTINGS);
-                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                 mContext.startActivity(intent);
             }
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 93591a9..f39727a 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -264,7 +264,7 @@
     private Transition mSharedElementReturnTransition = USE_DEFAULT_TRANSITION;
     private Transition mSharedElementExitTransition = null;
     private Transition mSharedElementReenterTransition = USE_DEFAULT_TRANSITION;
-    private Boolean mAllowExitTransitionOverlap;
+    private Boolean mAllowReturnTransitionOverlap;
     private Boolean mAllowEnterTransitionOverlap;
     private long mBackgroundFadeDurationMillis = -1;
     private Boolean mSharedElementsUseOverlay;
@@ -2890,7 +2890,6 @@
             invalidate();
 
             int opacity = PixelFormat.OPAQUE;
-
             // Note: if there is no background, we will assume opaque. The
             // common case seems to be that an application sets there to be
             // no background so it can draw everything itself. For that,
@@ -3549,9 +3548,9 @@
                     mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
                             R.styleable.Window_windowAllowEnterTransitionOverlap, true);
                 }
-                if (mAllowExitTransitionOverlap == null) {
-                    mAllowExitTransitionOverlap = getWindowStyle().getBoolean(
-                            R.styleable.Window_windowAllowExitTransitionOverlap, true);
+                if (mAllowReturnTransitionOverlap == null) {
+                    mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(
+                            R.styleable.Window_windowAllowReturnTransitionOverlap, true);
                 }
                 if (mBackgroundFadeDurationMillis < 0) {
                     mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
@@ -4017,13 +4016,13 @@
     }
 
     @Override
-    public void setAllowExitTransitionOverlap(boolean allowExitTransitionOverlap) {
-        mAllowExitTransitionOverlap = allowExitTransitionOverlap;
+    public void setAllowReturnTransitionOverlap(boolean allowExitTransitionOverlap) {
+        mAllowReturnTransitionOverlap = allowExitTransitionOverlap;
     }
 
     @Override
-    public boolean getAllowExitTransitionOverlap() {
-        return (mAllowExitTransitionOverlap == null) ? true : mAllowExitTransitionOverlap;
+    public boolean getAllowReturnTransitionOverlap() {
+        return (mAllowReturnTransitionOverlap == null) ? true : mAllowReturnTransitionOverlap;
     }
 
     @Override
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index e382a9f..e8dc800 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -66,6 +66,7 @@
 import android.os.UEventObserver;
 import android.os.UserHandle;
 import android.os.Vibrator;
+import android.provider.MediaStore;
 import android.provider.Settings;
 import android.service.dreams.DreamManagerInternal;
 import android.service.dreams.DreamService;
@@ -127,6 +128,9 @@
 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
 
 /**
  * WindowManagerPolicy implementation for the Android phone UI.  This
@@ -315,6 +319,7 @@
     boolean mLanguageSwitchKeyPressed;
 
     int mLidState = LID_ABSENT;
+    int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
     boolean mHaveBuiltInKeyboard;
 
     boolean mSystemReady;
@@ -1525,6 +1530,10 @@
         mLidState = mWindowManagerFuncs.getLidState();
     }
 
+    private void readCameraLensCoverState() {
+        mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
+    }
+
     private boolean isHidden(int accessibilityMode) {
         switch (accessibilityMode) {
             case 1:
@@ -4055,6 +4064,27 @@
         }
     }
 
+    @Override
+    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
+        int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
+        if (mCameraLensCoverState == lensCoverState) {
+            return;
+        }
+        if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
+                lensCoverState == CAMERA_LENS_UNCOVERED) {
+            Intent intent;
+            final boolean keyguardActive = mKeyguardDelegate == null ? false :
+                    mKeyguardDelegate.isShowing();
+            if (keyguardActive) {
+                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
+            } else {
+                intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+            }
+            mContext.startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+        }
+        mCameraLensCoverState = lensCoverState;
+    }
+
     void setHdmiPlugged(boolean plugged) {
         if (mHdmiPlugged != plugged) {
             mHdmiPlugged = plugged;
@@ -5132,6 +5162,7 @@
         mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null);
         mKeyguardDelegate.onSystemReady();
 
+        readCameraLensCoverState();
         updateUiMode();
         synchronized (mLock) {
             updateOrientationListenerLp();
@@ -5783,6 +5814,7 @@
                 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
         pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
                 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
+                pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
                 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
         if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
                 || mForceClearedSystemUiFlags != 0) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 4e2f52c..a43a2a6 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -42,6 +42,7 @@
 import android.database.ContentObserver;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.Region;
 import android.hardware.display.DisplayManager;
 import android.hardware.input.InputManager;
 import android.net.Uri;
@@ -162,6 +163,8 @@
     private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList =
             new ArrayList<>();
 
+    private final Region mTempRegion = new Region();
+
     private final Rect mTempRect = new Rect();
 
     private final Point mTempPoint = new Point();
@@ -2161,6 +2164,7 @@
                 throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
+            Region partialInteractiveRegion = mTempRegion;
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
                 // share the accessibility state of the parent. The call below
@@ -2182,13 +2186,17 @@
                         return false;
                     }
                 }
+                if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
+                        resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion = null;
+                }
             }
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
-                connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId,
-                        viewIdResName, interactionId, callback, mFetchFlags, interrogatingPid,
+                connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
+                        partialInteractiveRegion, interactionId, callback, mFetchFlags, interrogatingPid,
                         interrogatingTid, spec);
                 return true;
             } catch (RemoteException re) {
@@ -2208,6 +2216,7 @@
                 throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
+            Region partialInteractiveRegion = mTempRegion;
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
                 // share the accessibility state of the parent. The call below
@@ -2229,14 +2238,18 @@
                         return false;
                     }
                 }
+                if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
+                        resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion = null;
+                }
             }
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
                 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
-                        interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
-                        spec);
+                        partialInteractiveRegion, interactionId, callback, mFetchFlags, interrogatingPid,
+                        interrogatingTid, spec);
                 return true;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -2255,6 +2268,7 @@
                 long interrogatingTid) throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
+            Region partialInteractiveRegion = mTempRegion;
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
                 // share the accessibility state of the parent. The call below
@@ -2276,14 +2290,18 @@
                         return false;
                     }
                 }
+                if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
+                        resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion = null;
+                }
             }
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
-                        interactionId, callback, mFetchFlags | flags, interrogatingPid,
-                        interrogatingTid, spec);
+                        partialInteractiveRegion, interactionId, callback, mFetchFlags | flags,
+                        interrogatingPid, interrogatingTid, spec);
                 return true;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -2302,6 +2320,7 @@
                 throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
+            Region partialInteractiveRegion = mTempRegion;
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
                 // share the accessibility state of the parent. The call below
@@ -2324,13 +2343,17 @@
                         return false;
                     }
                 }
+                if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
+                        resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion = null;
+                }
             }
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
-                connection.findFocus(accessibilityNodeId, focusType, interactionId, callback,
-                        mFetchFlags, interrogatingPid, interrogatingTid, spec);
+                connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, interactionId,
+                        callback, mFetchFlags, interrogatingPid, interrogatingTid, spec);
                 return true;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -2349,6 +2372,7 @@
                 throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
+            Region partialInteractiveRegion = mTempRegion;
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
                 // share the accessibility state of the parent. The call below
@@ -2370,13 +2394,17 @@
                         return false;
                     }
                 }
+                if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
+                        resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion = null;
+                }
             }
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
-                connection.focusSearch(accessibilityNodeId, direction, interactionId, callback,
-                        mFetchFlags, interrogatingPid, interrogatingTid, spec);
+                connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, interactionId,
+                        callback, mFetchFlags, interrogatingPid, interrogatingTid, spec);
                 return true;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -3288,6 +3316,42 @@
             }
         }
 
+        public boolean computePartialInteractiveRegionForWindowLocked(int windowId,
+                Region outRegion) {
+            if (mWindows == null) {
+                return false;
+            }
+
+            // Windows are ordered in z order so start from the botton and find
+            // the window of interest. After that all windows that cover it should
+            // be subtracted from the resulting region. Note that for accessibility
+            // we are returning only interactive windows.
+            Region windowInteractiveRegion = null;
+            boolean windowInteractiveRegionChanged = false;
+
+            final int windowCount = mWindows.size();
+            for (int i = windowCount - 1; i >= 0; i--) {
+                AccessibilityWindowInfo currentWindow = mWindows.get(i);
+                if (windowInteractiveRegion == null) {
+                    if (currentWindow.getId() == windowId) {
+                        Rect currentWindowBounds = mTempRect;
+                        currentWindow.getBoundsInScreen(currentWindowBounds);
+                        outRegion.set(currentWindowBounds);
+                        windowInteractiveRegion = outRegion;
+                        continue;
+                    }
+                } else {
+                    Rect currentWindowBounds = mTempRect;
+                    currentWindow.getBoundsInScreen(currentWindowBounds);
+                    if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) {
+                        windowInteractiveRegionChanged = true;
+                    }
+                }
+            }
+
+            return windowInteractiveRegionChanged;
+        }
+
         public void updateEventSourceLocked(AccessibilityEvent event) {
             if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
                 event.setSource(null);
@@ -3420,11 +3484,16 @@
         }
 
         private void notifyWindowsChanged() {
-            // Let the client know the windows changed.
-            AccessibilityEvent event = AccessibilityEvent.obtain(
-                    AccessibilityEvent.TYPE_WINDOWS_CHANGED);
-            event.setEventTime(SystemClock.uptimeMillis());
-            sendAccessibilityEvent(event, mCurrentUserId);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                // Let the client know the windows changed.
+                AccessibilityEvent event = AccessibilityEvent.obtain(
+                        AccessibilityEvent.TYPE_WINDOWS_CHANGED);
+                event.setEventTime(SystemClock.uptimeMillis());
+                sendAccessibilityEvent(event, mCurrentUserId);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
         }
 
         public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) {
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index af5c13d..ac0ca0a 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -708,7 +708,6 @@
                      // Send an event to the end of the drag gesture.
                      sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
                  }
-                 mCurrentState = STATE_TOUCH_EXPLORING;
             } break;
             case MotionEvent.ACTION_UP: {
                 mAms.onTouchInteractionEnd();
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 7f7e5c3..d05de69 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -440,12 +440,10 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Permission Denial: can't dump from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-        }
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
+                                                "Permission Denial: can't dump from from pid="
+                                                + Binder.getCallingPid()
+                                                + ", uid=" + Binder.getCallingUid());
 
         synchronized (mLock) {
             int N = mProviders.size();
@@ -1863,7 +1861,7 @@
 
     private void deleteProviderLocked(Provider provider) {
         int N = provider.widgets.size();
-        for (int i = 0; i < N; i++) {
+        for (int i = N - 1; i >= 0; i--) {
             Widget widget = provider.widgets.remove(i);
             // Call back with empty RemoteViews
             updateAppWidgetInstanceLocked(widget, null, false);
@@ -4038,4 +4036,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 3e7a7e4..083aa9b 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -8395,10 +8395,15 @@
 
         Slog.i(TAG, "Auto restore => " + doAutoRestore);
 
-        synchronized (this) {
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.BACKUP_AUTO_RESTORE, doAutoRestore ? 1 : 0);
-            mAutoRestore = doAutoRestore;
+        final long oldId = Binder.clearCallingIdentity();
+        try {
+            synchronized (this) {
+                Settings.Secure.putInt(mContext.getContentResolver(),
+                        Settings.Secure.BACKUP_AUTO_RESTORE, doAutoRestore ? 1 : 0);
+                mAutoRestore = doAutoRestore;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(oldId);
         }
     }
 
@@ -8467,10 +8472,15 @@
         synchronized (mTransports) {
             String prevTransport = null;
             if (mTransports.get(transport) != null) {
-                prevTransport = mCurrentTransport;
-                mCurrentTransport = transport;
-                Settings.Secure.putString(mContext.getContentResolver(),
-                        Settings.Secure.BACKUP_TRANSPORT, transport);
+                final long oldId = Binder.clearCallingIdentity();
+                try {
+                    prevTransport = mCurrentTransport;
+                    mCurrentTransport = transport;
+                    Settings.Secure.putString(mContext.getContentResolver(),
+                            Settings.Secure.BACKUP_TRANSPORT, transport);
+                } finally {
+                    Binder.restoreCallingIdentity(oldId);
+                }
                 Slog.v(TAG, "selectBackupTransport() set " + mCurrentTransport
                         + " returning " + prevTransport);
             } else {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0919f77..3bab1bf 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -967,6 +967,17 @@
     }
 
     @Override
+    public Network getNetworkForType(int networkType) {
+        enforceAccessPermission();
+        final int uid = Binder.getCallingUid();
+        if (isNetworkBlocked(networkType, uid)) {
+            return null;
+        }
+        NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
+        return (nai == null) ? null : nai.network;
+    }
+
+    @Override
     public Network[] getAllNetworks() {
         enforceAccessPermission();
         final ArrayList<Network> result = new ArrayList();
@@ -1724,7 +1735,7 @@
         pw.println();
 
         synchronized (this) {
-            pw.println("NetworkTranstionWakeLock is currently " +
+            pw.println("NetworkTransitionWakeLock is currently " +
                     (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
             pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy);
         }
@@ -4805,7 +4816,8 @@
             result.setType(networkType);
             return result;
         } else {
-            NetworkInfo result = new NetworkInfo(networkType);
+            NetworkInfo result = new NetworkInfo(
+                    networkType, 0, ConnectivityManager.getNetworkTypeName(networkType), "");
             result.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
             return result;
         }
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index df54c7f..b452a38 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -29,10 +29,12 @@
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.telephony.TelephonyManager;
 import android.util.Slog;
 
@@ -190,29 +192,30 @@
     // Service API calls implementation, proxied to the real MmsService in "com.android.mms.service"
     private final class BinderService extends IMms.Stub {
         @Override
-        public void sendMessage(long subId, String callingPkg, byte[] pdu, String locationUrl,
-                ContentValues configOverrides, PendingIntent sentIntent) throws RemoteException {
+        public void sendMessage(long subId, String callingPkg, Uri contentUri,
+                String locationUrl, Bundle configOverrides, PendingIntent sentIntent)
+                        throws RemoteException {
             mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
                     callingPkg) != AppOpsManager.MODE_ALLOWED) {
                 return;
             }
-            getServiceGuarded().sendMessage(subId, callingPkg, pdu, locationUrl, configOverrides,
-                    sentIntent);
+            getServiceGuarded().sendMessage(subId, callingPkg, contentUri, locationUrl,
+                    configOverrides, sentIntent);
         }
 
         @Override
         public void downloadMessage(long subId, String callingPkg, String locationUrl,
-                ContentValues configOverrides, PendingIntent downloadedIntent)
-                throws RemoteException {
+                Uri contentUri, Bundle configOverrides,
+                PendingIntent downloadedIntent) throws RemoteException {
             mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
                     "Download MMS message");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_RECEIVE_MMS, Binder.getCallingUid(),
                     callingPkg) != AppOpsManager.MODE_ALLOWED) {
                 return;
             }
-            getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, configOverrides,
-                    downloadedIntent);
+            getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, contentUri,
+                    configOverrides, downloadedIntent);
         }
 
         @Override
@@ -228,21 +231,8 @@
         }
 
         @Override
-        public boolean getCarrierConfigBoolean(long subId, String name, boolean defaultValue)
-                throws RemoteException {
-            return getServiceGuarded().getCarrierConfigBoolean(subId, name, defaultValue);
-        }
-
-        @Override
-        public int getCarrierConfigInt(long subId, String name, int defaultValue)
-                throws RemoteException {
-            return getServiceGuarded().getCarrierConfigInt(subId, name, defaultValue);
-        }
-
-        @Override
-        public String getCarrierConfigString(long subId, String name, String defaultValue)
-                throws RemoteException {
-            return getServiceGuarded().getCarrierConfigString(subId, name, defaultValue);
+        public Bundle getCarrierConfigValues(long subId) throws RemoteException {
+            return getServiceGuarded().getCarrierConfigValues(subId);
         }
 
         @Override
@@ -260,8 +250,9 @@
         }
 
         @Override
-        public Uri importMultimediaMessage(String callingPkg, byte[] pdu, String messageId,
-                long timestampSecs, boolean seen, boolean read) throws RemoteException {
+        public Uri importMultimediaMessage(String callingPkg, Uri contentUri,
+                String messageId, long timestampSecs, boolean seen, boolean read)
+                        throws RemoteException {
             mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Import MMS message");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
                     callingPkg) != AppOpsManager.MODE_ALLOWED) {
@@ -270,7 +261,7 @@
                 return FAKE_MMS_SENT_URI;
             }
             return getServiceGuarded().importMultimediaMessage(
-                    callingPkg, pdu, messageId, timestampSecs, seen, read);
+                    callingPkg, contentUri, messageId, timestampSecs, seen, read);
         }
 
         @Override
@@ -328,7 +319,8 @@
         }
 
         @Override
-        public Uri addMultimediaMessageDraft(String callingPkg, byte[] pdu) throws RemoteException {
+        public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
+                throws RemoteException {
             mContext.enforceCallingPermission(Manifest.permission.WRITE_SMS, "Add MMS draft");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
                     callingPkg) != AppOpsManager.MODE_ALLOWED) {
@@ -336,12 +328,12 @@
                 // while writing the TelephonyProvider
                 return FAKE_MMS_DRAFT_URI;
             }
-            return getServiceGuarded().addMultimediaMessageDraft(callingPkg, pdu);
+            return getServiceGuarded().addMultimediaMessageDraft(callingPkg, contentUri);
         }
 
         @Override
         public void sendStoredMessage(long subId, String callingPkg, Uri messageUri,
-                ContentValues configOverrides, PendingIntent sentIntent) throws RemoteException {
+                Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
             mContext.enforceCallingPermission(Manifest.permission.SEND_SMS,
                     "Send stored MMS message");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index f9b65b8..1318f66 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -44,6 +44,7 @@
 import android.net.InterfaceConfiguration;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
+import android.net.Network;
 import android.net.NetworkStats;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
@@ -1200,10 +1201,12 @@
     }
 
     @Override
-    public void setDnsForwarders(String[] dns) {
+    public void setDnsForwarders(Network network, String[] dns) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        final Command cmd = new Command("tether", "dns", "set");
+        int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
+        final Command cmd = new Command("tether", "dns", "set", netId);
+
         for (String s : dns) {
             cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
         }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 94d979e..c469b42 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1700,9 +1700,10 @@
             subtitle = titleAndSubtitle.substring(index + 1);
         }
         UserHandle user = new UserHandle(userId);
-        n.color = mContext.getResources().getColor(
+        Context contextForUser = getContextForUser(user);
+        n.color = contextForUser.getResources().getColor(
                 com.android.internal.R.color.system_notification_accent_color);
-        n.setLatestEventInfo(mContext, title, subtitle,
+        n.setLatestEventInfo(contextForUser, title, subtitle,
                 PendingIntent.getActivityAsUser(mContext, 0, intent,
                         PendingIntent.FLAG_CANCEL_CURRENT, null, user));
         installNotification(getCredentialPermissionNotificationId(
@@ -2968,11 +2969,12 @@
                 Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
                         0 /* when */);
                 UserHandle user = new UserHandle(userId);
+                Context contextForUser = getContextForUser(user);
                 final String notificationTitleFormat =
-                        mContext.getText(R.string.notification_title).toString();
-                n.color = mContext.getResources().getColor(
+                        contextForUser.getText(R.string.notification_title).toString();
+                n.color = contextForUser.getResources().getColor(
                         com.android.internal.R.color.system_notification_accent_color);
-                n.setLatestEventInfo(mContext,
+                n.setLatestEventInfo(contextForUser,
                         String.format(notificationTitleFormat, account.name),
                         message, PendingIntent.getActivityAsUser(
                         mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
@@ -3478,4 +3480,13 @@
         }
         return authTokensForAccount;
     }
+
+    private Context getContextForUser(UserHandle user) {
+        try {
+            return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user);
+        } catch (NameNotFoundException e) {
+            // Default to mContext, not finding the package system is running as is unlikely.
+            return mContext;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 389369f..023f627 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2903,9 +2903,11 @@
             boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
             boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
             String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
+        long startTime = SystemClock.elapsedRealtime();
         ProcessRecord app;
         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;
@@ -2927,14 +2929,17 @@
                 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
@@ -2970,6 +2975,7 @@
         }
 
         if (app == null) {
+            checkTime(startTime, "startProcess: creating new process record");
             app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
             app.crashHandler = crashHandler;
             if (app == null) {
@@ -2981,9 +2987,11 @@
             if (isolated) {
                 mIsolatedProcesses.put(app.uid, app);
             }
+            checkTime(startTime, "startProcess: done creating new process record");
         } else {
             // 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: added package to existing proc");
         }
 
         // If the system is not ready yet, then hold off on starting this
@@ -2995,11 +3003,14 @@
                 mProcessesOnHold.add(app);
             }
             if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
+            checkTime(startTime, "startProcess: returning with proc on hold");
             return app;
         }
 
+        checkTime(startTime, "startProcess: stepping in to startProcess");
         startProcessLocked(
                 app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
+        checkTime(startTime, "startProcess: done starting proc!");
         return (app.pid != 0) ? app : null;
     }
 
@@ -3015,11 +3026,14 @@
 
     private final void startProcessLocked(ProcessRecord app, String hostingType,
             String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
+        long startTime = SystemClock.elapsedRealtime();
         if (app.pid > 0 && app.pid != MY_PID) {
+            checkTime(startTime, "startProcess: removing from pids map");
             synchronized (mPidsSelfLocked) {
                 mPidsSelfLocked.remove(app.pid);
                 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             }
+            checkTime(startTime, "startProcess: done removing from pids map");
             app.setPid(0);
         }
 
@@ -3027,7 +3041,9 @@
                 "startProcessLocked removing on hold: " + app);
         mProcessesOnHold.remove(app);
 
+        checkTime(startTime, "startProcess: starting to update cpu stats");
         updateCpuStats();
+        checkTime(startTime, "startProcess: done updating cpu stats");
 
         try {
             int uid = app.uid;
@@ -3037,10 +3053,12 @@
             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) {
@@ -3066,6 +3084,7 @@
                 gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
                 gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
             }
+            checkTime(startTime, "startProcess: building args");
             if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
                 if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                         && mTopComponent != null
@@ -3109,14 +3128,17 @@
             // the PID of the new process, or else throw a RuntimeException.
             boolean isActivityProcess = (entryPoint == null);
             if (entryPoint == null) entryPoint = "android.app.ActivityThread";
+            checkTime(startTime, "startProcess: asking zygote to start proc");
             Process.ProcessStartResult startResult = Process.start(entryPoint,
                     app.processName, uid, uid, gids, debugFlags, mountExternal,
                     app.info.targetSdkVersion, app.info.seinfo, requiredAbi, entryPointArgs);
+            checkTime(startTime, "startProcess: returned from zygote!");
 
             if (app.isolated) {
                 mBatteryStatsService.addIsolatedUid(app.uid, app.info.uid);
             }
             mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
+            checkTime(startTime, "startProcess: done updating battery stats");
 
             EventLog.writeEvent(EventLogTags.AM_PROC_START,
                     UserHandle.getUserId(uid), startResult.pid, uid,
@@ -3127,6 +3149,7 @@
                 Watchdog.getInstance().processStarted(app.processName, startResult.pid);
             }
 
+            checkTime(startTime, "startProcess: building log message");
             StringBuilder buf = mStringBuilder;
             buf.setLength(0);
             buf.append("Start proc ");
@@ -3164,6 +3187,7 @@
             app.usingWrapper = startResult.usingWrapper;
             app.removed = false;
             app.killedByAm = false;
+            checkTime(startTime, "startProcess: starting to update pids map");
             synchronized (mPidsSelfLocked) {
                 this.mPidsSelfLocked.put(startResult.pid, app);
                 if (isActivityProcess) {
@@ -3173,6 +3197,7 @@
                             ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
                 }
             }
+            checkTime(startTime, "startProcess: done updating pids map");
         } catch (RuntimeException e) {
             // XXX do better error recovery.
             app.setPid(0);
@@ -3190,7 +3215,6 @@
         if (resumed) {
             if (mUsageStatsService != null) {
                 mUsageStatsService.reportEvent(component.realActivity, component.userId,
-                        System.currentTimeMillis(),
                         UsageEvents.Event.MOVE_TO_FOREGROUND);
             }
             synchronized (stats) {
@@ -3199,7 +3223,6 @@
         } else {
             if (mUsageStatsService != null) {
                 mUsageStatsService.reportEvent(component.realActivity, component.userId,
-                        System.currentTimeMillis(),
                         UsageEvents.Event.MOVE_TO_BACKGROUND);
             }
             synchronized (stats) {
@@ -8383,6 +8406,10 @@
         synchronized(this) {
             TaskRecord tr = recentTaskForIdLocked(taskId);
             if (tr != null) {
+                if (tr == mStackSupervisor.mLockTaskModeTask) {
+                    mStackSupervisor.showLockTaskToast();
+                    return;
+                }
                 if (DEBUG_STACK) Slog.d(TAG, "moveTaskToBack: moving task=" + tr);
                 ActivityStack stack = tr.stack;
                 if (stack.mResumedActivity != null && stack.mResumedActivity.task == tr) {
@@ -8415,11 +8442,19 @@
         enforceNotIsolatedCaller("moveActivityTaskToBack");
         synchronized(this) {
             final long origId = Binder.clearCallingIdentity();
-            int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
-            if (taskId >= 0) {
-                return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId, null);
+            try {
+                int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
+                if (taskId >= 0) {
+                    if ((mStackSupervisor.mLockTaskModeTask != null)
+                            && (mStackSupervisor.mLockTaskModeTask.taskId == taskId)) {
+                        mStackSupervisor.showLockTaskToast();
+                        return false;
+                    }
+                    return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId, null);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(origId);
             }
-            Binder.restoreCallingIdentity(origId);
         }
         return false;
     }
@@ -8660,7 +8695,8 @@
 
     @Override
     public void startLockTaskModeOnCurrent() throws RemoteException {
-        checkCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS);
+        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "startLockTaskModeOnCurrent");
         ActivityRecord r = null;
         synchronized (this) {
             r = mStackSupervisor.topRunningActivityLocked();
@@ -8702,7 +8738,8 @@
 
     @Override
     public void stopLockTaskModeOnCurrent() throws RemoteException {
-        checkCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS);
+        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "stopLockTaskModeOnCurrent");
         long ident = Binder.clearCallingIdentity();
         try {
             stopLockTaskMode();
@@ -10307,8 +10344,8 @@
                 final boolean translucentChanged = r.changeWindowTranslucency(false);
                 if (translucentChanged) {
                     r.task.stack.convertToTranslucent(r);
-                    mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
                 }
+                mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
                 mWindowManager.setAppFullscreen(token, false);
                 return translucentChanged;
             }
@@ -15897,6 +15934,7 @@
                 newConfig.seq = mConfigurationSeq;
                 mConfiguration = newConfig;
                 Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig);
+                mUsageStatsService.reportConfigurationChange(newConfig, mCurrentUserId);
                 //mUsageStatsService.noteStartConfig(newConfig);
 
                 final Configuration configCopy = new Configuration(mConfiguration);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3efd049..81c379a 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -241,6 +241,9 @@
     /** Run all ActivityStacks through this */
     final ActivityStackSupervisor mStackSupervisor;
 
+    /** Used to keep resumeTopActivityLocked() from being entered recursively */
+    private boolean inResumeTopActivity;
+
     static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
     static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
     static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
@@ -456,7 +459,7 @@
         final ActivityRecord r = ActivityRecord.forToken(token);
         if (r != null) {
             final TaskRecord task = r.task;
-            if (task.mActivities.contains(r) && mTaskHistory.contains(task)) {
+            if (task != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
                 if (task.stack != this) Slog.w(TAG,
                     "Illegal state! task does not point to stack it is in.");
                 return r;
@@ -1439,6 +1442,23 @@
     }
 
     final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
+        if (inResumeTopActivity) {
+            // Don't even start recursing.
+            return false;
+        }
+
+        boolean result = false;
+        try {
+            // Protect against recursion.
+            inResumeTopActivity = true;
+            result = resumeTopActivityInnerLocked(prev, options);
+        } finally {
+            inResumeTopActivity = false;
+        }
+        return result;
+    }
+
+    final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
         if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
 
         ActivityRecord parent = mActivityContainer.mParentActivity;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 6545134..780efa1 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1262,7 +1262,7 @@
         if (err == ActivityManager.START_SUCCESS) {
             final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
             Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
-                    + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)
+                    + "} from uid " + callingUid
                     + " on display " + (container == null ? (mFocusedStack == null ?
                             Display.DEFAULT_DISPLAY : mFocusedStack.mDisplayId) :
                             (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
@@ -1729,16 +1729,19 @@
                         | (baseIntent.getFlags()&flagsOfInterest);
                 intent.setFlags(launchFlags);
                 inTask.setIntent(r);
+                addingToTask = true;
 
-            // If the task is not empty, then we are going to add the new activity on top
-            // of the task, so it can not be launching as a new task.
+            // If the task is not empty and the caller is asking to start it as the root
+            // of a new task, then we don't actually want to start this on the task.  We
+            // will bring the task to the front, and possibly give it a new intent.
             } else if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
-                ActivityOptions.abort(options);
-                throw new IllegalStateException("Caller has inTask " + inTask
-                        + " but target is a new task");
+                addingToTask = false;
+
+            } else {
+                addingToTask = true;
             }
+
             reuseTask = inTask;
-            addingToTask = true;
         } else {
             inTask = null;
         }
@@ -1979,7 +1982,7 @@
                 sourceRecord.task : null;
 
         // Should this be considered a new task?
-        if (r.resultTo == null && !addingToTask
+        if (r.resultTo == null && inTask == null && !addingToTask
                 && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
             if (isLockTaskModeViolation(reuseTask)) {
                 Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
@@ -2072,6 +2075,7 @@
             }
             targetStack = inTask.stack;
             targetStack.moveTaskToFrontLocked(inTask, r, options);
+            targetStack.moveToFront();
             mWindowManager.moveTaskToTop(inTask.taskId);
 
             // Check whether we should actually launch the new activity in to the task,
@@ -2092,6 +2096,13 @@
                 }
             }
 
+            if (!addingToTask) {
+                // We don't actually want to have this activity added to the task, so just
+                // stop here but still tell the caller that we consumed the intent.
+                ActivityOptions.abort(options);
+                return ActivityManager.START_TASK_TO_FRONT;
+            }
+
             r.setTask(inTask, null);
             if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
                     + " in explicit task " + r.task);
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index cedf573..ff319d3 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -16,6 +16,7 @@
 
 package com.android.server.connectivity;
 
+import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -213,6 +214,7 @@
     private final NetworkAgentInfo mNetworkAgentInfo;
     private final TelephonyManager mTelephonyManager;
     private final WifiManager mWifiManager;
+    private final AlarmManager mAlarmManager;
 
     private String mServer;
     private boolean mIsCaptivePortalCheckEnabled = false;
@@ -236,6 +238,7 @@
         mNetworkAgentInfo = networkAgentInfo;
         mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
 
         addState(mDefaultState);
         addState(mOfflineState, mDefaultState);
@@ -500,10 +503,38 @@
     }
 
     private class LingeringState extends State {
+        private static final String ACTION_LINGER_EXPIRED = "android.net.netmon.lingerExpired";
+        private static final String EXTRA_NETID = "lingerExpiredNetId";
+        private static final String EXTRA_TOKEN = "lingerExpiredToken";
+
+        private class LingerExpiredBroadcastReceiver extends BroadcastReceiver {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent.getAction().equals(ACTION_LINGER_EXPIRED) &&
+                        Integer.parseInt(intent.getStringExtra(EXTRA_NETID)) ==
+                        mNetworkAgentInfo.network.netId) {
+                    sendMessage(CMD_LINGER_EXPIRED,
+                            Integer.parseInt(intent.getStringExtra(EXTRA_TOKEN)));
+                }
+            }
+        }
+
+        private BroadcastReceiver mBroadcastReceiver;
+        private PendingIntent mIntent;
+
         @Override
         public void enter() {
-            Message message = obtainMessage(CMD_LINGER_EXPIRED, ++mLingerToken, 0);
-            sendMessageDelayed(message, mLingerDelayMs);
+            mBroadcastReceiver = new LingerExpiredBroadcastReceiver();
+            mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_LINGER_EXPIRED));
+
+            Intent intent = new Intent(ACTION_LINGER_EXPIRED, null);
+            intent.putExtra(EXTRA_NETID, String.valueOf(mNetworkAgentInfo.network.netId));
+            intent.putExtra(EXTRA_TOKEN, String.valueOf(++mLingerToken));
+            mIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+            long wakeupTime = SystemClock.elapsedRealtime() + mLingerDelayMs;
+            mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeupTime,
+                    // Give a specific window so we aren't subject to unknown inexactitude.
+                    mLingerDelayMs / 6, mIntent);
         }
 
         @Override
@@ -524,6 +555,12 @@
                     return NOT_HANDLED;
             }
         }
+
+        @Override
+        public void exit() {
+            mAlarmManager.cancel(mIntent);
+            mContext.unregisterReceiver(mBroadcastReceiver);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 1fd114c..7c303ff 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -31,6 +31,7 @@
 import android.net.InterfaceConfiguration;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
+import android.net.Network;
 import android.net.NetworkInfo;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
@@ -56,6 +57,7 @@
 import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -742,7 +744,7 @@
         static final int CMD_IP_FORWARDING_ENABLE_ERROR  =  7;
         // notification from the master SM that it had trouble disabling IP Forwarding
         static final int CMD_IP_FORWARDING_DISABLE_ERROR =  8;
-        // notification from the master SM that it had trouble staring tethering
+        // notification from the master SM that it had trouble starting tethering
         static final int CMD_START_TETHERING_ERROR       =  9;
         // notification from the master SM that it had trouble stopping tethering
         static final int CMD_STOP_TETHERING_ERROR        = 10;
@@ -1235,12 +1237,6 @@
                         return false;
                     }
                 }
-                try {
-                    mNMService.setDnsForwarders(mDefaultDnsServers);
-                } catch (Exception e) {
-                    transitionTo(mSetDnsForwardersErrorState);
-                    return false;
-                }
                 return true;
             }
             protected boolean turnOffMasterTetherSettings() {
@@ -1348,8 +1344,17 @@
                             }
                         }
                         try {
-                            mNMService.setDnsForwarders(dnsServers);
+                            Network network = getConnectivityManager().getNetworkForType(upType);
+                            if (network == null) {
+                                Log.e(TAG, "No Network for upstream type " + upType + "!");
+                            }
+                            if (VDBG) {
+                                Log.d(TAG, "Setting DNS forwarders: Network=" + network +
+                                       ", dnsServers=" + Arrays.toString(dnsServers));
+                            }
+                            mNMService.setDnsForwarders(network, dnsServers);
                         } catch (Exception e) {
+                            Log.e(TAG, "Setting DNS forwarders failed!");
                             transitionTo(mSetDnsForwardersErrorState);
                         }
                     }
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 9e169d9..f6beb9a 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -46,6 +46,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ProviderInfo;
 import android.content.pm.RegisteredServicesCache;
 import android.content.pm.RegisteredServicesCacheListener;
@@ -3098,26 +3099,28 @@
                 return;
             }
 
+            UserHandle user = new UserHandle(userId);
             final PendingIntent pendingIntent = PendingIntent
                     .getActivityAsUser(mContext, 0, clickIntent,
-                            PendingIntent.FLAG_CANCEL_CURRENT, null, new UserHandle(userId));
+                            PendingIntent.FLAG_CANCEL_CURRENT, null, user);
 
             CharSequence tooManyDeletesDescFormat = mContext.getResources().getText(
                     R.string.contentServiceTooManyDeletesNotificationDesc);
 
+            Context contextForUser = getContextForUser(user);
             Notification notification =
                 new Notification(R.drawable.stat_notify_sync_error,
                         mContext.getString(R.string.contentServiceSync),
                         System.currentTimeMillis());
-            notification.color = mContext.getResources().getColor(
+            notification.color = contextForUser.getResources().getColor(
                     com.android.internal.R.color.system_notification_accent_color);
-            notification.setLatestEventInfo(mContext,
-                    mContext.getString(R.string.contentServiceSyncNotificationTitle),
+            notification.setLatestEventInfo(contextForUser,
+                    contextForUser.getString(R.string.contentServiceSyncNotificationTitle),
                     String.format(tooManyDeletesDescFormat.toString(), authorityName),
                     pendingIntent);
             notification.flags |= Notification.FLAG_ONGOING_EVENT;
             mNotificationMgr.notifyAsUser(null, account.hashCode() ^ authority.hashCode(),
-                    notification, new UserHandle(userId));
+                    notification, user);
         }
 
         /**
@@ -3305,4 +3308,13 @@
             return mTable.size();
         }
     }
+
+    private Context getContextForUser(UserHandle user) {
+        try {
+            return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user);
+        } catch (NameNotFoundException e) {
+            // Default to mContext, not finding the package system is running as is unlikely.
+            return mContext;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index aa1310d..6ce235b 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -159,6 +159,8 @@
     static final int TRUE = 1;
     static final int FALSE = 0;
 
+    // Internal abort error code. It's the same as success.
+    static final int ABORT_NO_ERROR = -1;
     // Constants related to operands of HDMI CEC commands.
     // Refer to CEC Table 29 in HDMI Spec v1.4b.
     // [Abort Reason]
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index bb22b4d..c5a6dbd 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -31,8 +31,6 @@
 
 import libcore.util.EmptyArray;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -102,11 +100,6 @@
     // Stores the local CEC devices in the system. Device type is used for key.
     private final SparseArray<HdmiCecLocalDevice> mLocalDevices = new SparseArray<>();
 
-    @IoThreadOnly
-    private final HdmiLogger mIoThreadLogger = new HdmiLogger(TAG);
-    @ServiceThreadOnly
-    private final HdmiLogger mServiceThreadLogger = new HdmiLogger(TAG);
-
     // Private constructor.  Use HdmiCecController.create().
     private HdmiCecController(HdmiControlService service) {
         mService = service;
@@ -210,9 +203,8 @@
         }
 
         final int assignedAddress = logicalAddress;
-        mIoThreadLogger.debug(
-                String.format("New logical address for device [%d]: [preferred:%d, assigned:%d]",
-                        deviceType, preferredAddress, assignedAddress));
+        HdmiLogger.debug("New logical address for device [%d]: [preferred:%d, assigned:%d]",
+                        deviceType, preferredAddress, assignedAddress);
         if (callback != null) {
             runOnServiceThread(new Runnable() {
                 @Override
@@ -449,7 +441,7 @@
                         allocated.add(address);
                     }
                 }
-                mIoThreadLogger.debug("[P]:Allocated Address=" + allocated);
+                HdmiLogger.debug("[P]:Allocated Address=" + allocated);
                 if (callback != null) {
                     runOnServiceThread(new Runnable() {
                         @Override
@@ -551,7 +543,7 @@
         runOnIoThread(new Runnable() {
             @Override
             public void run() {
-                mIoThreadLogger.debug("[S]:" + cecMessage);
+                HdmiLogger.debug("[S]:" + cecMessage);
                 byte[] body = buildBody(cecMessage.getOpcode(), cecMessage.getParams());
                 int i = 0;
                 int errorCode = Constants.SEND_RESULT_SUCCESS;
@@ -586,7 +578,7 @@
     private void handleIncomingCecCommand(int srcAddress, int dstAddress, byte[] body) {
         assertRunOnServiceThread();
         HdmiCecMessage command = HdmiCecMessageBuilder.of(srcAddress, dstAddress, body);
-        mServiceThreadLogger.debug("[R]:" + command);
+        HdmiLogger.debug("[R]:" + command);
         onReceiveCommand(command);
     }
 
@@ -596,8 +588,7 @@
     @ServiceThreadOnly
     private void handleHotplug(int port, boolean connected) {
         assertRunOnServiceThread();
-        mServiceThreadLogger.debug(
-                "Hotplug event:[port:" + port + " , connected:" + connected + "]");
+        HdmiLogger.debug("Hotplug event:[port:%d, connected:%b]", port, connected);
         mService.onHotplug(port, connected);
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
index 85f5be2..b2300a6 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
@@ -43,9 +43,6 @@
  */
 abstract class HdmiCecFeatureAction {
     private static final String TAG = "HdmiCecFeatureAction";
-    // As all actions run in the same thread (service thread), it's fine to have single logger.
-    // TODO: create global logger for each threads and use them.
-    protected static final HdmiLogger DLOGGER = new HdmiLogger(TAG);
 
     // Timer handler message used for timeout event
     protected static final int MSG_TIMEOUT = 100;
@@ -264,10 +261,7 @@
     }
 
     protected final void sendUserControlPressedAndReleased(int targetAddress, int uiCommand) {
-        sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(
-                getSourceAddress(), targetAddress, uiCommand));
-        sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(
-                getSourceAddress(), targetAddress));
+        mSource.sendUserControlPressedAndReleased(targetAddress, uiCommand);
     }
 
     protected final void addOnFinishedCallback(HdmiCecFeatureAction action, Runnable runnable) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index bc6a299..c00c5d0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -274,6 +274,12 @@
                 return handleRecordTvScreen(message);
             case Constants.MESSAGE_TIMER_CLEARED_STATUS:
                 return handleTimerClearedStatus(message);
+            case Constants.MESSAGE_REPORT_POWER_STATUS:
+                return handleReportPowerStatus(message);
+            case Constants.MESSAGE_TIMER_STATUS:
+                return handleTimerStatus(message);
+            case Constants.MESSAGE_RECORD_STATUS:
+                return handleRecordStatus(message);
             default:
                 return false;
         }
@@ -541,6 +547,18 @@
         return false;
     }
 
+    protected boolean handleReportPowerStatus(HdmiCecMessage message) {
+        return false;
+    }
+
+    protected boolean handleTimerStatus(HdmiCecMessage message) {
+        return false;
+    }
+
+    protected boolean handleRecordStatus(HdmiCecMessage message) {
+        return false;
+    }
+
     @ServiceThreadOnly
     final void handleAddressAllocated(int logicalAddress, int reason) {
         assertRunOnServiceThread();
@@ -810,6 +828,13 @@
         Slog.w(TAG, "sendKeyEvent not implemented");
     }
 
+    void sendUserControlPressedAndReleased(int targetAddress, int cecKeycode) {
+        mService.sendCecCommand(HdmiCecMessageBuilder.buildUserControlPressed(
+                mAddress, targetAddress, cecKeycode));
+        mService.sendCecCommand(HdmiCecMessageBuilder.buildUserControlReleased(
+                mAddress, targetAddress));
+    }
+
     /**
      * Dump internal status of HdmiCecLocalDevice object.
      */
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 7ae2198..58ccbdb 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -120,8 +120,6 @@
     // other CEC devices since they might not have logical address.
     private final ArraySet<Integer> mCecSwitches = new ArraySet<Integer>();
 
-    private final HdmiLogger mSafeLogger = new HdmiLogger(TAG);
-
     HdmiCecLocalDeviceTv(HdmiControlService service) {
         super(service, HdmiDeviceInfo.DEVICE_TV);
         mPrevPortId = Constants.INVALID_PORT_ID;
@@ -476,6 +474,25 @@
         return true;
     }
 
+    @Override
+    protected boolean handleReportPowerStatus(HdmiCecMessage command) {
+        int newStatus = command.getParams()[0] & 0xFF;
+        updateDevicePowerStatus(command.getSource(), newStatus);
+        return true;
+    }
+
+    @Override
+    protected boolean handleTimerStatus(HdmiCecMessage message) {
+        // Do nothing.
+        return true;
+    }
+
+    @Override
+    protected boolean handleRecordStatus(HdmiCecMessage message) {
+        // Do nothing.
+        return true;
+    }
+
     boolean updateCecSwitchInfo(int address, int type, int path) {
         if (address == Constants.ADDR_UNREGISTERED
                 && type == HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH) {
@@ -700,8 +717,7 @@
 
     // # Seq 25
     void setSystemAudioMode(boolean on, boolean updateSetting) {
-        mSafeLogger.debug(String.format("System Audio Mode change[old:%b new:%b]",
-                mSystemAudioActivated, on));
+        HdmiLogger.debug("System Audio Mode change[old:%b new:%b]", mSystemAudioActivated, on);
 
         if (updateSetting) {
             mService.writeBooleanSetting(Global.HDMI_SYSTEM_AUDIO_ENABLED, on);
@@ -832,6 +848,8 @@
                     AudioManager.STREAM_MUSIC);
             mService.setAudioStatus(mute,
                     VolumeControlAction.scaleToCustomVolume(volume, maxVolume));
+            displayOsd(HdmiControlManager.OSD_MESSAGE_AVR_VOLUME_CHANGED,
+                    mute ? HdmiControlManager.AVR_VOLUME_MUTED : volume);
         }
     }
 
@@ -855,12 +873,13 @@
             }
         }
 
-        // Remove existing volume action.
-        removeAction(VolumeControlAction.class);
-
-        HdmiDeviceInfo avr = getAvrDeviceInfo();
-        addAndStartAction(VolumeControlAction.ofVolumeChange(this, avr.getLogicalAddress(),
-                cecVolume, delta > 0));
+        List<VolumeControlAction> actions = getActions(VolumeControlAction.class);
+        if (actions.isEmpty()) {
+            addAndStartAction(new VolumeControlAction(this,
+                    getAvrDeviceInfo().getLogicalAddress(), delta > 0));
+        } else {
+            actions.get(0).handleVolumeChange(delta > 0);
+        }
     }
 
     @ServiceThreadOnly
@@ -872,8 +891,9 @@
 
         // Remove existing volume action.
         removeAction(VolumeControlAction.class);
-        HdmiDeviceInfo avr = getAvrDeviceInfo();
-        addAndStartAction(VolumeControlAction.ofMute(this, avr.getLogicalAddress(), mute));
+        sendUserControlPressedAndReleased(getAvrDeviceInfo().getLogicalAddress(),
+                mute ? HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION :
+                        HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION);
     }
 
     @Override
@@ -935,8 +955,9 @@
     protected boolean handleSetSystemAudioMode(HdmiCecMessage message) {
         assertRunOnServiceThread();
         if (!isMessageForSystemAudio(message)) {
-            mSafeLogger.warning("Invalid <Set System Audio Mode> message:" + message);
-            return false;
+            HdmiLogger.warning("Invalid <Set System Audio Mode> message:" + message);
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+            return true;
         }
         SystemAudioActionFromAvr action = new SystemAudioActionFromAvr(this,
                 message.getSource(), HdmiUtils.parseCommandParamSystemAudioStatus(message), null);
@@ -949,8 +970,9 @@
     protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) {
         assertRunOnServiceThread();
         if (!isMessageForSystemAudio(message)) {
-            mSafeLogger.warning("Invalid <System Audio Mode Status> message:" + message);
-            return false;
+            HdmiLogger.warning("Invalid <System Audio Mode Status> message:" + message);
+            // Ignore this message.
+            return true;
         }
         setSystemAudioMode(HdmiUtils.parseCommandParamSystemAudioStatus(message), true);
         return true;
@@ -973,7 +995,10 @@
 
         int recorderAddress = message.getSource();
         byte[] recordSource = mService.invokeRecordRequestListener(recorderAddress);
-        startOneTouchRecord(recorderAddress, recordSource);
+        int reason = startOneTouchRecord(recorderAddress, recordSource);
+        if (reason != Constants.ABORT_NO_ERROR) {
+            mService.maySendFeatureAbortCommand(message, reason);
+        }
         return true;
     }
 
@@ -998,7 +1023,8 @@
     }
 
     private boolean isMessageForSystemAudio(HdmiCecMessage message) {
-        return message.getSource() == Constants.ADDR_AUDIO_SYSTEM
+        return mService.isControlEnabled()
+                && message.getSource() == Constants.ADDR_AUDIO_SYSTEM
                 && (message.getDestination() == Constants.ADDR_TV
                         || message.getDestination() == Constants.ADDR_BROADCAST)
                 && getAvrDeviceInfo() != null;
@@ -1445,31 +1471,38 @@
         mService.displayOsd(messageId);
     }
 
+    @ServiceThreadOnly
+    void displayOsd(int messageId, int extra) {
+        assertRunOnServiceThread();
+        mService.displayOsd(messageId, extra);
+    }
+
     // Seq #54 and #55
     @ServiceThreadOnly
-    void startOneTouchRecord(int recorderAddress, byte[] recordSource) {
+    int startOneTouchRecord(int recorderAddress, byte[] recordSource) {
         assertRunOnServiceThread();
         if (!mService.isControlEnabled()) {
             Slog.w(TAG, "Can not start one touch record. CEC control is disabled.");
             announceOneTouchRecordResult(ONE_TOUCH_RECORD_CEC_DISABLED);
-            return;
+            return Constants.ABORT_NOT_IN_CORRECT_MODE;
         }
 
         if (!checkRecorder(recorderAddress)) {
             Slog.w(TAG, "Invalid recorder address:" + recorderAddress);
             announceOneTouchRecordResult(ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
-            return;
+            return Constants.ABORT_NOT_IN_CORRECT_MODE;
         }
 
         if (!checkRecordSource(recordSource)) {
             Slog.w(TAG, "Invalid record source." + Arrays.toString(recordSource));
             announceOneTouchRecordResult(ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN);
-            return;
+            return Constants.ABORT_UNABLE_TO_DETERMINE;
         }
 
         addAndStartAction(new OneTouchRecordAction(this, recorderAddress, recordSource));
         Slog.i(TAG, "Start new [One Touch Record]-Target:" + recorderAddress + ", recordSource:"
                 + Arrays.toString(recordSource));
+        return Constants.ABORT_NO_ERROR;
     }
 
     @ServiceThreadOnly
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index 8b345cf..0b3d9fb 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -51,7 +51,6 @@
     }
 
     final SparseArray<ValidationInfo> mValidationInfo = new SparseArray<>();
-    private final HdmiLogger mSpamSafeLogger = new HdmiLogger(TAG);
 
     public HdmiCecMessageValidator(HdmiControlService service) {
         mService = service;
@@ -183,32 +182,32 @@
         int opcode = message.getOpcode();
         ValidationInfo info = mValidationInfo.get(opcode);
         if (info == null) {
-            mSpamSafeLogger.warning("No validation information for the message: " + message);
+            HdmiLogger.warning("No validation information for the message: " + message);
             return true;
         }
 
         // Check the source field.
         if (message.getSource() == Constants.ADDR_UNREGISTERED &&
                 (info.addressType & SRC_UNREGISTERED) == 0) {
-            mSpamSafeLogger.warning("Unexpected source: " + message);
+            HdmiLogger.warning("Unexpected source: " + message);
             return false;
         }
         // Check the destination field.
         if (message.getDestination() == Constants.ADDR_BROADCAST) {
             if ((info.addressType & DEST_BROADCAST) == 0) {
-                mSpamSafeLogger.warning("Unexpected broadcast message: " + message);
+                HdmiLogger.warning("Unexpected broadcast message: " + message);
                 return false;
             }
         } else {  // Direct addressing.
             if ((info.addressType & DEST_DIRECT) == 0) {
-                mSpamSafeLogger.warning("Unexpected direct message: " + message);
+                HdmiLogger.warning("Unexpected direct message: " + message);
                 return false;
             }
         }
 
         // Check the parameter type.
         if (!info.parameterValidator.isValid(message.getParams())) {
-            mSpamSafeLogger.warning("Unexpected parameters: " + message);
+            HdmiLogger.warning("Unexpected parameters: " + message);
             return false;
         }
         return true;
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 93c0f07..38c6fb3 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -166,8 +166,6 @@
     // Type of logical devices hosted in the system. Stored in the unmodifiable list.
     private final List<Integer> mLocalDevices;
 
-    private final HdmiLogger mSpamSafeLogger = new HdmiLogger(TAG);
-
     // List of records for hotplug event listener to handle the the caller killed in action.
     @GuardedBy("mLock")
     private final ArrayList<HotplugEventListenerRecord> mHotplugEventListenerRecords =
@@ -656,7 +654,7 @@
         if (mMessageValidator.isValid(command)) {
             mCecController.sendCommand(command, callback);
         } else {
-            mSpamSafeLogger.error("Invalid message type:" + command);
+            HdmiLogger.error("Invalid message type:" + command);
             if (callback != null) {
                 callback.onSendCompleted(Constants.SEND_RESULT_FAILURE);
             }
@@ -705,7 +703,7 @@
         }
 
         if (message.getDestination() != Constants.ADDR_BROADCAST) {
-            mSpamSafeLogger.warning("Unhandled cec command:" + message);
+            HdmiLogger.warning("Unhandled cec command:" + message);
         }
         return false;
     }
@@ -794,7 +792,6 @@
             // FLAG_HDMI_SYSTEM_AUDIO_VOLUME prevents audio manager from announcing
             // volume change notification back to hdmi control service.
             audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume,
-                    AudioManager.FLAG_SHOW_UI |
                     AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME);
         }
     }
@@ -856,8 +853,11 @@
                 device.onDeviceRemoved();
                 // There is no explicit event for device removal unlike capability register event
                 // used for device addition . Hence we remove the device on hotplug event.
-                invokeDeviceEventListeners(device.getInfo(), DEVICE_EVENT_REMOVE_DEVICE);
-                updateSafeMhlInput();
+                HdmiDeviceInfo deviceInfo = device.getInfo();
+                if (deviceInfo != null) {
+                    invokeDeviceEventListeners(deviceInfo, DEVICE_EVENT_REMOVE_DEVICE);
+                    updateSafeMhlInput();
+                }
             } else {
                 Slog.w(TAG, "No device to remove:[portId=" + portId);
             }
@@ -1082,7 +1082,7 @@
                         // the connected mobile device, start routing control to switch ports.
                         // callback is handled by MHL action.
                         device.turnOn(callback);
-                        tv.doManualPortSwitching(device.getInfo().getPortId(), null);
+                        tv.doManualPortSwitching(device.getPortId(), null);
                         return;
                     }
                     tv.deviceSelect(deviceId, callback);
@@ -2030,4 +2030,14 @@
         getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
                 HdmiControlService.PERMISSION);
     }
+
+    @ServiceThreadOnly
+    void displayOsd(int messageId, int extra) {
+        assertRunOnServiceThread();
+        Intent intent = new Intent(HdmiControlManager.ACTION_OSD_MESSAGE);
+        intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_ID, messageId);
+        intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_EXTRAM_PARAM1, extra);
+        getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
+                HdmiControlService.PERMISSION);
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
index c7add75..2562ffc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiLogger.java
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -26,44 +26,83 @@
 /**
  * A logger that prevents spammy log. For the same log message, it logs once every 20seconds.
  * This class is not thread-safe.
+ * <p>
+ * For convenience, use single character prefix for all messages.
+ * Here are common acronyms
+ * <ul>
+ *   <li>[T]: Timout
+ *   <li>[R]: Received message
+ *   <li>[S]: Sent message
+ *   <li>[P]: Device polling result
+ * </ul>
  */
 final class HdmiLogger {
+    private static final String TAG = "HDMI";
     // Logging duration for same error message.
     private static final long ERROR_LOG_DURATTION_MILLIS = 20 * 1000;  // 20s
 
     private static final boolean DEBUG = false;
 
+    private static final ThreadLocal<HdmiLogger> sLogger = new ThreadLocal<>();
+
     // Key (String): log message.
     // Value (Pair(Long, Integer)): a pair of last log time millis and the number of logMessage.
     // Cache for warning.
     private final HashMap<String, Pair<Long, Integer>> mWarningTimingCache = new HashMap<>();
     // Cache for error.
     private final HashMap<String, Pair<Long, Integer>> mErrorTimingCache = new HashMap<>();
-    private final String mTag;
 
-    HdmiLogger(String tag) {
-        mTag = "HDMI:" + tag;
+    private HdmiLogger() {
     }
 
-    void warning(String logMessage) {
+    static final void warning(String logMessage, Object... objs) {
+        getLogger().warningInternal(toLogString(logMessage, objs));
+    }
+
+    private void warningInternal(String logMessage) {
         String log = updateLog(mWarningTimingCache, logMessage);
         if (!log.isEmpty()) {
-            Slog.w(mTag, log);
+            Slog.w(TAG, log);
         }
     }
 
-    void error(String logMessage) {
+    static final void error(String logMessage, Object... objs) {
+        getLogger().errorInternal(toLogString(logMessage, objs));
+    }
+
+    private void errorInternal(String logMessage) {
         String log = updateLog(mErrorTimingCache, logMessage);
         if (!log.isEmpty()) {
-            Slog.e(mTag, log);
+            Slog.e(TAG, log);
         }
     }
 
-    void debug(String logMessage) {
+    static final void debug(String logMessage, Object... objs) {
+        getLogger().debugInternal(toLogString(logMessage, objs));
+    }
+
+    private void debugInternal(String logMessage) {
         if (!DEBUG) {
             return;
         }
-        Slog.d(mTag, logMessage);
+        Slog.d(TAG, logMessage);
+    }
+
+    private static final String toLogString(String logMessage, Object[] objs) {
+        if (objs.length > 0) {
+            return String.format(logMessage, objs);
+        } else {
+            return logMessage;
+        }
+    }
+
+    private static HdmiLogger getLogger() {
+        HdmiLogger logger = sLogger.get();
+        if (logger == null) {
+            logger = new HdmiLogger();
+            sLogger.set(logger);
+        }
+        return logger;
     }
 
     private static String updateLog(HashMap<String, Pair<Long, Integer>> cache, String logMessage) {
diff --git a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
index 03fbb95..1e29fd6 100644
--- a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
+++ b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
@@ -77,7 +77,7 @@
             // if no device exists for incoming message, hands it over to other actions.
             return false;
         }
-        int newStatus = cmd.getParams()[0];
+        int newStatus = cmd.getParams()[0] & 0xFF;
         updatePowerStatus(sourceAddress, newStatus, true);
         return true;
     }
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
index 17c2d6c..3fb450f 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -85,6 +85,7 @@
         if (mState != state || state != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE) {
             return;
         }
+        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 f25363d..d9e1f24 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
@@ -35,15 +35,15 @@
 
     @Override
     boolean start() {
+        mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
+        addTimer(mState, HdmiConfig.TIMEOUT_MS);
+
         HdmiCecMessage command = HdmiCecMessageBuilder.buildRequestArcInitiation(
                 getSourceAddress(), mAvrAddress);
         sendCommand(command, new HdmiControlService.SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error == Constants.SEND_RESULT_SUCCESS) {
-                    mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
-                    addTimer(mState, HdmiConfig.TIMEOUT_MS);
-                } else {
+                if (error != Constants.SEND_RESULT_SUCCESS) {
                     // If failed to send <Request ARC Initiation>, start "Disabled"
                     // ARC transmission action.
                     disableArcTransmission();
diff --git a/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
index 1491c72..f5a0115 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
@@ -35,15 +35,15 @@
 
     @Override
     boolean start() {
+        mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
+        addTimer(mState, HdmiConfig.TIMEOUT_MS);
+
         HdmiCecMessage command =
                 HdmiCecMessageBuilder.buildRequestArcTermination(getSourceAddress(), mAvrAddress);
         sendCommand(command, new HdmiControlService.SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error == Constants.SEND_RESULT_SUCCESS) {
-                    mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
-                    addTimer(mState, HdmiConfig.TIMEOUT_MS);
-                } else {
+                if (error != Constants.SEND_RESULT_SUCCESS) {
                     // If failed to send <Request ARC Termination>, start "Disabled" ARC
                     // transmission action.
                     disableArcTransmission();
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index 30519f3..bffa854 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -53,6 +53,18 @@
     @Override
     boolean start() {
         if (mEnabled) {
+            // Enable ARC status immediately after sending <Report Arc Initiated>.
+            // If AVR responds with <Feature Abort>, disable ARC status again.
+            // This is different from spec that says that turns ARC status to
+            // "Enabled" if <Report ARC Initiated> is acknowledged and no
+            // <Feature Abort> is received.
+            // But implemented this way to save the time having to wait for
+            // <Feature Abort>.
+            setArcStatus(true);
+            // If succeeds to send <Report ARC Initiated>, wait general timeout
+            // to check whether there is no <Feature Abort> for <Report ARC Initiated>.
+            mState = STATE_WAITING_TIMEOUT;
+            addTimer(mState, HdmiConfig.TIMEOUT_MS);
             sendReportArcInitiated();
         } else {
             setArcStatus(false);
@@ -67,23 +79,11 @@
         sendCommand(command, new HdmiControlService.SendMessageCallback() {
             @Override
             public void onSendCompleted(int error) {
-                if (error == Constants.SEND_RESULT_SUCCESS) {
-                    // Enable ARC status immediately after sending <Report Arc Initiated>.
-                    // If AVR responds with <Feature Abort>, disable ARC status again.
-                    // This is different from spec that says that turns ARC status to
-                    // "Enabled" if <Report ARC Initiated> is acknowledged and no
-                    // <Feature Abort> is received.
-                    // But implemented this way to save the time having to wait for
-                    // <Feature Abort>.
-                    setArcStatus(true);
-                    // If succeeds to send <Report ARC Initiated>, wait general timeout
-                    // to check whether there is no <Feature Abort> for <Report ARC Initiated>.
-                    mState = STATE_WAITING_TIMEOUT;
-                    addTimer(mState, HdmiConfig.TIMEOUT_MS);
-                } else {
+                if (error != Constants.SEND_RESULT_SUCCESS) {
                     // If fails to send <Report ARC Initiated>, disable ARC and
                     // send <Report ARC Terminated> directly.
                     setArcStatus(false);
+                    HdmiLogger.debug("Failed to send <Report Arc Initiated>.");
                     finish();
                 }
             }
@@ -112,6 +112,7 @@
         if (opcode == Constants.MESSAGE_FEATURE_ABORT) {
             int originalOpcode = cmd.getParams()[0] & 0xFF;
             if (originalOpcode == Constants.MESSAGE_REPORT_ARC_INITIATED) {
+                HdmiLogger.debug("Feature aborted for <Report Arc Initiated>");
                 setArcStatus(false);
                 finish();
                 return true;
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
index d15ffb0..0871194 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -98,7 +98,7 @@
             @Override
             public void onSendCompleted(int error) {
                 if (error != Constants.SEND_RESULT_SUCCESS) {
-                    DLOGGER.debug("Failed to send <System Audio Mode Request>:" + error);
+                    HdmiLogger.debug("Failed to send <System Audio Mode Request>:" + error);
                     setSystemAudioMode(false);
                     finishWithCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
                 }
@@ -111,7 +111,7 @@
     private void handleSendSystemAudioModeRequestTimeout() {
         if (!mTargetAudioStatus  // Don't retry for Off case.
                 || mSendRetryCount++ >= MAX_SEND_RETRY_COUNT) {
-            DLOGGER.debug("[T]:wait for <Set System Audio Mode>.");
+            HdmiLogger.debug("[T]:wait for <Set System Audio Mode>.");
             setSystemAudioMode(false);
             finishWithCallback(HdmiControlManager.RESULT_TIMEOUT);
             return;
@@ -130,7 +130,7 @@
                 if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT
                         && (cmd.getParams()[0] & 0xFF)
                                 == Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST) {
-                    DLOGGER.debug("Failed to start system audio mode request.");
+                    HdmiLogger.debug("Failed to start system audio mode request.");
                     setSystemAudioMode(false);
                     finishWithCallback(HdmiControlManager.RESULT_EXCEPTION);
                     return true;
@@ -145,7 +145,7 @@
                     startAudioStatusAction();
                     return true;
                 } else {
-                    DLOGGER.debug("Unexpected system audio mode request:" + receivedStatus);
+                    HdmiLogger.debug("Unexpected system audio mode request:" + receivedStatus);
                     // Unexpected response, consider the request is newly initiated by AVR.
                     // To return 'false' will initiate new SystemAudioActionFromAvr by the control
                     // service.
diff --git a/services/core/java/com/android/server/hdmi/VolumeControlAction.java b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
index ddc267a..4338fc7 100644
--- a/services/core/java/com/android/server/hdmi/VolumeControlAction.java
+++ b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
@@ -17,66 +17,35 @@
 package com.android.server.hdmi;
 
 import static com.android.server.hdmi.Constants.IRT_MS;
+import static com.android.server.hdmi.Constants.MESSAGE_FEATURE_ABORT;
+import static com.android.server.hdmi.Constants.MESSAGE_REPORT_AUDIO_STATUS;
+import static com.android.server.hdmi.Constants.MESSAGE_USER_CONTROL_PRESSED;
 
-import com.android.internal.util.Preconditions;
+import android.media.AudioManager;
 
 /**
  * Feature action that transmits volume change to Audio Receiver.
  * <p>
- * This action is created when a user pressed volume up/down. However, Since Android only provides a
- * listener for delta of some volume change, we will set a target volume, and check reported volume
- * from Audio Receiver(AVR). If TV receives no &lt;Report Audio Status&gt; from AVR, this action
- * will be finished in {@link #IRT_MS} * {@link #VOLUME_CHANGE_TIMEOUT_MAX_COUNT} (ms).
+ * This action is created when a user pressed volume up/down. However, Android only provides a
+ * listener for delta of some volume change instead of individual key event. Also it's hard to know
+ * Audio Receiver's number of volume steps for a single volume control key. Because of this, it
+ * sends key-down event until IRT timeout happens, and it will send key-up event if no additional
+ * volume change happens; otherwise, it will send again key-down as press and hold feature does.
  */
 final class VolumeControlAction extends HdmiCecFeatureAction {
     private static final String TAG = "VolumeControlAction";
 
-    private static final int VOLUME_MUTE = 101;
-    private static final int VOLUME_RESTORE = 102;
+    // State that wait for next volume press.
+    private static final int STATE_WAIT_FOR_NEXT_VOLUME_PRESS = 1;
     private static final int MAX_VOLUME = 100;
-    private static final int MIN_VOLUME = 0;
 
-    // State where to wait for <Report Audio Status>
-    private static final int STATE_WAIT_FOR_REPORT_VOLUME_STATUS = 1;
-
-    // Maximum count of time out used to finish volume action.
-    private static final int VOLUME_CHANGE_TIMEOUT_MAX_COUNT = 2;
+    private static final int UNKNOWN_AVR_VOLUME = -1;
 
     private final int mAvrAddress;
-    private final int mTargetVolume;
-    private final boolean mIsVolumeUp;
-    private int mTimeoutCount;
-
-    /**
-     * Create a {@link VolumeControlAction} for mute/restore change
-     *
-     * @param source source device sending volume change
-     * @param avrAddress address of audio receiver
-     * @param mute whether to mute sound or not. {@code true} for mute on; {@code false} for mute
-     *            off, i.e restore volume
-     * @return newly created {@link VolumeControlAction}
-     */
-    public static VolumeControlAction ofMute(HdmiCecLocalDevice source, int avrAddress,
-            boolean mute) {
-        return new VolumeControlAction(source, avrAddress, mute ? VOLUME_MUTE : VOLUME_RESTORE,
-                false);
-    }
-
-    /**
-     * Create a {@link VolumeControlAction} for volume up/down change
-     *
-     * @param source source device sending volume change
-     * @param avrAddress address of audio receiver
-     * @param targetVolume target volume to be set to AVR. It should be in range of [0-100]
-     * @param isVolumeUp whether to volume up or not. {@code true} for volume up; {@code false} for
-     *            volume down
-     * @return newly created {@link VolumeControlAction}
-     */
-    public static VolumeControlAction ofVolumeChange(HdmiCecLocalDevice source, int avrAddress,
-            int targetVolume, boolean isVolumeUp) {
-        Preconditions.checkArgumentInRange(targetVolume, MIN_VOLUME, MAX_VOLUME, "volume");
-        return new VolumeControlAction(source, avrAddress, targetVolume, isVolumeUp);
-    }
+    private boolean mIsVolumeUp;
+    private long mLastKeyUpdateTime;
+    private int mLastAvrVolume;
+    private boolean mSentKeyPressed;
 
     /**
      * Scale a custom volume value to cec volume scale.
@@ -94,123 +63,141 @@
      *
      * @param cecVolume volume value in cec volume scale. It should be in a range of [0-100]
      * @param scale scale of custom volume (max volume)
-     * @return a volume value scaled to custom volume range
+     * @return a volume scaled to custom volume range
      */
     public static int scaleToCustomVolume(int cecVolume, int scale) {
         return (cecVolume * scale) / MAX_VOLUME;
     }
 
-    private VolumeControlAction(HdmiCecLocalDevice source, int avrAddress, int targetVolume,
-            boolean isVolumeUp) {
+    VolumeControlAction(HdmiCecLocalDevice source, int avrAddress, boolean isVolumeUp) {
         super(source);
-
         mAvrAddress = avrAddress;
-        mTargetVolume = targetVolume;
         mIsVolumeUp = isVolumeUp;
+        mLastAvrVolume = UNKNOWN_AVR_VOLUME;
+        mSentKeyPressed = false;
+
+        updateLastKeyUpdateTime();
+    }
+
+    private void updateLastKeyUpdateTime() {
+        mLastKeyUpdateTime = System.currentTimeMillis();
     }
 
     @Override
     boolean start() {
-        if (isForMute()) {
-            sendMuteChange(mTargetVolume == VOLUME_MUTE);
-            finish();
-            return true;
-        }
-
-        startVolumeChange();
+        mState = STATE_WAIT_FOR_NEXT_VOLUME_PRESS;
+        sendVolumeKeyPressed();
+        resetTimer();
         return true;
     }
 
-
-    private boolean isForMute() {
-        return mTargetVolume == VOLUME_MUTE || mTargetVolume == VOLUME_RESTORE;
-    }
-
-    private void startVolumeChange() {
-        mTimeoutCount = 0;
-        sendVolumeChange(mIsVolumeUp);
-        mState = STATE_WAIT_FOR_REPORT_VOLUME_STATUS;
-        addTimer(mState, IRT_MS);
-    }
-
-    private void sendVolumeChange(boolean up) {
+    private void sendVolumeKeyPressed() {
         sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(), mAvrAddress,
-                up ? HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP
+                mIsVolumeUp ? HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP
                         : HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
+        mSentKeyPressed = true;
     }
 
-    private void sendMuteChange(boolean mute) {
-        sendUserControlPressedAndReleased(mAvrAddress,
-                mute ? HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION :
-                        HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION);
+    private void resetTimer() {
+        mActionTimer.clearTimerMessage();
+        addTimer(STATE_WAIT_FOR_NEXT_VOLUME_PRESS, IRT_MS);
+    }
+
+    void handleVolumeChange(boolean isVolumeUp) {
+        if (mIsVolumeUp != isVolumeUp) {
+            HdmiLogger.debug("Volume Key Status Changed[old:%b new:%b]", mIsVolumeUp, isVolumeUp);
+            sendVolumeKeyReleased();
+            mIsVolumeUp = isVolumeUp;
+        }
+        updateLastKeyUpdateTime();
+    }
+
+    private void sendVolumeKeyReleased() {
+        sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(
+                getSourceAddress(), mAvrAddress));
+        mSentKeyPressed = false;
     }
 
     @Override
     boolean processCommand(HdmiCecMessage cmd) {
-        if (mState != STATE_WAIT_FOR_REPORT_VOLUME_STATUS) {
+        if (mState != STATE_WAIT_FOR_NEXT_VOLUME_PRESS || cmd.getSource() != mAvrAddress) {
             return false;
         }
 
         switch (cmd.getOpcode()) {
-            case Constants.MESSAGE_REPORT_AUDIO_STATUS:
-                handleReportAudioStatus(cmd);
-                return true;
-            case Constants.MESSAGE_FEATURE_ABORT:
-                int originalOpcode = cmd.getParams()[0] & 0xFF;
-                if (originalOpcode == Constants.MESSAGE_USER_CONTROL_PRESSED
-                        || originalOpcode == Constants.MESSAGE_USER_CONTROL_RELEASED) {
-                    // TODO: handle feature abort.
-                    finish();
-                    return true;
-                }
-            default:  // fall through
+            case MESSAGE_REPORT_AUDIO_STATUS:
+                return handleReportAudioStatus(cmd);
+            case MESSAGE_FEATURE_ABORT:
+                return handleFeatureAbort(cmd);
+            default:
                 return false;
         }
     }
 
-    private void handleReportAudioStatus(HdmiCecMessage cmd) {
-        byte[] params = cmd.getParams();
+    private boolean handleReportAudioStatus(HdmiCecMessage cmd) {
+        byte params[] = cmd.getParams();
+        boolean mute = (params[0] & 0x80) == 0x80;
         int volume = params[0] & 0x7F;
-        // Update volume with new value.
-        // Note that it will affect system volume change.
-        tv().setAudioStatus(false, volume);
-        if (mIsVolumeUp) {
-            if (mTargetVolume <= volume) {
-                finishWithVolumeChangeRelease();
-                return;
-            }
-        } else {
-            if (mTargetVolume >= volume) {
-                finishWithVolumeChangeRelease();
-                return;
-            }
+        mLastAvrVolume = volume;
+        if (shouldUpdateAudioVolume(mute)) {
+            HdmiLogger.debug("Force volume change[mute:%b, volume=%d]", mute, volume);
+            tv().setAudioStatus(mute, volume);
         }
-
-        // Clear action status and send another volume change command.
-        clear();
-        startVolumeChange();
+        return true;
     }
 
-    private void finishWithVolumeChangeRelease() {
-        sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(
-                getSourceAddress(), mAvrAddress));
-        finish();
+    private boolean shouldUpdateAudioVolume(boolean mute) {
+        // Do nothing if in mute.
+        if (mute) {
+            return true;
+        }
+
+        // Update audio status if current volume position is edge of volume bar,
+        // i.e max or min volume.
+        AudioManager audioManager = tv().getService().getAudioManager();
+        int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+        if (mIsVolumeUp) {
+            int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+            return currentVolume == maxVolume;
+        } else {
+            return currentVolume == 0;
+        }
+    }
+
+    private boolean handleFeatureAbort(HdmiCecMessage cmd) {
+        int originalOpcode = cmd.getParams()[0] & 0xFF;
+        // Since it sends <User Control Released> only when it finishes this action,
+        // it takes care of <User Control Pressed> only here.
+        if (originalOpcode == MESSAGE_USER_CONTROL_PRESSED) {
+            finish();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected void clear() {
+        super.clear();
+        if (mSentKeyPressed) {
+            sendVolumeKeyReleased();
+        }
+        if (mLastAvrVolume != UNKNOWN_AVR_VOLUME) {
+            tv().setAudioStatus(false, mLastAvrVolume);
+            mLastAvrVolume = UNKNOWN_AVR_VOLUME;
+        }
     }
 
     @Override
     void handleTimerEvent(int state) {
-        if (mState != STATE_WAIT_FOR_REPORT_VOLUME_STATUS) {
+        if (state != STATE_WAIT_FOR_NEXT_VOLUME_PRESS) {
             return;
         }
 
-        // If no report volume action after IRT * VOLUME_CHANGE_TIMEOUT_MAX_COUNT just stop volume
-        // action.
-        if (++mTimeoutCount == VOLUME_CHANGE_TIMEOUT_MAX_COUNT) {
-            finishWithVolumeChangeRelease();
-            return;
+        if (System.currentTimeMillis() - mLastKeyUpdateTime >= IRT_MS) {
+            finish();
+        } else {
+            sendVolumeKeyPressed();
+            resetTimer();
         }
-
-        sendVolumeChange(mIsVolumeUp);
-        addTimer(mState, IRT_MS);
     }
 }
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 93dceff..9e81149 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -241,6 +241,9 @@
     /** Switch code: Headphone/Microphone Jack.  When set, something is inserted. */
     public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
 
+    /** Switch code: Camera lens cover. When set the lens is covered. */
+    public static final int SW_CAMERA_LENS_COVER = 0x09;
+
     public static final int SW_LID_BIT = 1 << SW_LID;
     public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
     public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
@@ -249,6 +252,7 @@
     public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
     public static final int SW_JACK_BITS =
             SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT;
+    public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
 
     /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
     final boolean mUseDevInputEventForAudioJack;
@@ -1380,6 +1384,11 @@
             mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
         }
 
+        if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
+            final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) == 0);
+            mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
+        }
+
         if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
             mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
                     switchMask);
@@ -1575,6 +1584,8 @@
 
         public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
 
+        public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
+
         public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
 
         public long notifyANR(InputApplicationHandle inputApplicationHandle,
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index c3bc306..30154d7 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -199,9 +199,6 @@
             List<JobStatus> jobsForUser = mJobs.getJobsByUser(userHandle);
             for (int i=0; i<jobsForUser.size(); i++) {
                 JobStatus toRemove = jobsForUser.get(i);
-                if (DEBUG) {
-                    Slog.d(TAG, "Cancelling: " + toRemove);
-                }
                 cancelJobLocked(toRemove);
             }
         }
@@ -219,9 +216,6 @@
             List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
             for (int i=0; i<jobsForUid.size(); i++) {
                 JobStatus toRemove = jobsForUid.get(i);
-                if (DEBUG) {
-                    Slog.d(TAG, "Cancelling: " + toRemove);
-                }
                 cancelJobLocked(toRemove);
             }
         }
@@ -547,14 +541,28 @@
         private void queueReadyJobsForExecutionH() {
             synchronized (mJobs) {
                 ArraySet<JobStatus> jobs = mJobs.getJobs();
+                if (DEBUG) {
+                    Slog.d(TAG, "queuing all ready jobs for execution:");
+                }
                 for (int i=0; i<jobs.size(); i++) {
                     JobStatus job = jobs.valueAt(i);
                     if (isReadyToBeExecutedLocked(job)) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "    queued " + job.toShortString());
+                        }
                         mPendingJobs.add(job);
                     } else if (isReadyToBeCancelledLocked(job)) {
                         stopJobOnServiceContextLocked(job);
                     }
                 }
+                if (DEBUG) {
+                    final int queuedJobs = mPendingJobs.size();
+                    if (queuedJobs == 0) {
+                        Slog.d(TAG, "No jobs pending.");
+                    } else {
+                        Slog.d(TAG, queuedJobs + " jobs queued.");
+                    }
+                }
             }
         }
 
@@ -657,6 +665,9 @@
         private void maybeRunPendingJobsH() {
             synchronized (mJobs) {
                 Iterator<JobStatus> it = mPendingJobs.iterator();
+                if (DEBUG) {
+                    Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
+                }
                 while (it.hasNext()) {
                     JobStatus nextPending = it.next();
                     JobServiceContext availableContext = null;
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 5297911..344c57b 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -157,6 +157,7 @@
             mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();
 
             mVerb = VERB_BINDING;
+            scheduleOpTimeOut();
             final Intent intent = new Intent().setComponent(job.getServiceComponent());
             boolean binding = mContext.bindServiceAsUser(intent, this,
                     Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
@@ -253,8 +254,6 @@
             return;
         }
         this.service = IJobService.Stub.asInterface(service);
-        // Remove all timeouts.
-        mCallbackHandler.removeMessages(MSG_TIMEOUT);
         final PowerManager pm =
                 (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mRunningJob.getTag());
@@ -299,6 +298,7 @@
         public void handleMessage(Message message) {
             switch (message.what) {
                 case MSG_SERVICE_BOUND:
+                    removeMessages(MSG_TIMEOUT);
                     handleServiceBoundH();
                     break;
                 case MSG_CALLBACK:
@@ -337,6 +337,9 @@
 
         /** Start the job on the service. */
         private void handleServiceBoundH() {
+            if (DEBUG) {
+                Slog.d(TAG, "MSG_SERVICE_BOUND for " + mRunningJob.toShortString());
+            }
             if (mVerb != VERB_BINDING) {
                 Slog.e(TAG, "Sending onStartJob for a job that isn't pending. "
                         + VERB_STRINGS[mVerb]);
@@ -456,42 +459,36 @@
 
         /** Process MSG_TIMEOUT here. */
         private void handleOpTimeoutH() {
-            if (JobSchedulerService.DEBUG) {
-                Slog.d(TAG, "MSG_TIMEOUT of " +
-                        mRunningJob.getServiceComponent().getShortClassName() + " : "
-                        + mParams.getJobId());
-            }
-
-            final int jobId = mParams.getJobId();
             switch (mVerb) {
+                case VERB_BINDING:
+                    Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() +
+                            ", dropping.");
+                    closeAndCleanupJobH(false /* needsReschedule */);
+                    break;
                 case VERB_STARTING:
                     // Client unresponsive - wedged or failed to respond in time. We don't really
                     // know what happened so let's log it and notify the JobScheduler
                     // FINISHED/NO-RETRY.
                     Slog.e(TAG, "No response from client for onStartJob '" +
-                            mRunningJob.getServiceComponent().getShortClassName() + "' jId: "
-                            + jobId);
+                            mRunningJob.toShortString());
                     closeAndCleanupJobH(false /* needsReschedule */);
                     break;
                 case VERB_STOPPING:
                     // At least we got somewhere, so fail but ask the JobScheduler to reschedule.
                     Slog.e(TAG, "No response from client for onStopJob, '" +
-                            mRunningJob.getServiceComponent().getShortClassName() + "' jId: "
-                            + jobId);
+                            mRunningJob.toShortString());
                     closeAndCleanupJobH(true /* needsReschedule */);
                     break;
                 case VERB_EXECUTING:
                     // Not an error - client ran out of time.
                     Slog.i(TAG, "Client timed out while executing (no jobFinished received)." +
-                            " sending onStop. "  +
-                            mRunningJob.getServiceComponent().getShortClassName() + "' jId: "
-                            + jobId);
+                            " sending onStop. "  + mRunningJob.toShortString());
                     sendStopMessageH();
                     break;
                 default:
-                    Slog.e(TAG, "Handling timeout for an unknown active job state: "
-                            + mRunningJob);
-                    return;
+                    Slog.e(TAG, "Handling timeout for an invalid job state: " +
+                            mRunningJob.toShortString() + ", dropping.");
+                    closeAndCleanupJobH(false /* needsReschedule */);
             }
         }
 
@@ -530,7 +527,9 @@
                 } catch (RemoteException e) {
                     // Whatever.
                 }
-                mWakeLock.release();
+                if (mWakeLock != null) {
+                    mWakeLock.release();
+                }
                 mContext.unbindService(JobServiceContext.this);
                 mWakeLock = null;
                 mRunningJob = null;
@@ -547,25 +546,25 @@
             removeMessages(MSG_SHUTDOWN_EXECUTION);
             mCompletedListener.onJobCompleted(completedJob, reschedule);
         }
+    }
 
-        /**
-         * Called when sending a message to the client, over whose execution we have no control. If
-         * we haven't received a response in a certain amount of time, we want to give up and carry
-         * on with life.
-         */
-        private void scheduleOpTimeOut() {
-            mCallbackHandler.removeMessages(MSG_TIMEOUT);
+    /**
+     * Called when sending a message to the client, over whose execution we have no control. If
+     * we haven't received a response in a certain amount of time, we want to give up and carry
+     * on with life.
+     */
+    private void scheduleOpTimeOut() {
+        mCallbackHandler.removeMessages(MSG_TIMEOUT);
 
-            final long timeoutMillis = (mVerb == VERB_EXECUTING) ?
-                    EXECUTING_TIMESLICE_MILLIS : OP_TIMEOUT_MILLIS;
-            if (DEBUG) {
-                Slog.d(TAG, "Scheduling time out for '" +
-                        mRunningJob.getServiceComponent().getShortClassName() + "' jId: " +
-                        mParams.getJobId() + ", in " + (timeoutMillis / 1000) + " s");
-            }
-            Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT);
-            mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
-            mTimeoutElapsed = SystemClock.elapsedRealtime() + timeoutMillis;
+        final long timeoutMillis = (mVerb == VERB_EXECUTING) ?
+                EXECUTING_TIMESLICE_MILLIS : OP_TIMEOUT_MILLIS;
+        if (DEBUG) {
+            Slog.d(TAG, "Scheduling time out for '" +
+                    mRunningJob.getServiceComponent().getShortClassName() + "' jId: " +
+                    mParams.getJobId() + ", in " + (timeoutMillis / 1000) + " s");
         }
+        Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT);
+        mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
+        mTimeoutElapsed = SystemClock.elapsedRealtime() + timeoutMillis;
     }
 }
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 0da2cfa..b936130d 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -231,7 +231,7 @@
      * @param direction The direction to adjust volume in.
      */
     public void adjustVolume(int direction, int flags, String packageName, int uid) {
-        if (isPlaybackActive(false)) {
+        if (isPlaybackActive(false) || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
             flags &= ~AudioManager.FLAG_PLAY_SOUND;
         }
         if (direction > 1) {
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 189131c..05ad1fe 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -545,8 +545,9 @@
                 setZenModeCondition(condition, "downtime");
             }
             // exit downtime
-            if (!inDowntime && mode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
-                    && mDowntime.isDowntimeCondition(mExitCondition)) {
+            if (!inDowntime && mDowntime.isDowntimeCondition(mExitCondition)
+                    && (mode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+                                || mode == Global.ZEN_MODE_NO_INTERRUPTIONS)) {
                 mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF, "downtimeExit");
             }
         }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d0f4054..bc538ed 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1126,6 +1126,19 @@
             return mRankingHelper.getPackagePriority(pkg, uid);
         }
 
+        @Override
+        public void setPackageVisibilityOverride(String pkg, int uid, int visibility) {
+            checkCallerIsSystem();
+            mRankingHelper.setPackageVisibilityOverride(pkg, uid, visibility);
+            savePolicyFile();
+        }
+
+        @Override
+        public int getPackageVisibilityOverride(String pkg, int uid) {
+            checkCallerIsSystem();
+            return mRankingHelper.getPackageVisibilityOverride(pkg, uid);
+        }
+
         /**
          * System-only API for getting a list of current (i.e. not cleared) notifications.
          *
@@ -1457,7 +1470,14 @@
         @Override
         public boolean matchesCallFilter(Bundle extras) {
             enforceSystemOrSystemUI("INotificationManager.matchesCallFilter");
-            return mZenModeHelper.matchesCallFilter(extras,
+            return matchesCallFilterAsUser(extras, Binder.getCallingUid());
+        }
+
+        @Override
+        public boolean matchesCallFilterAsUser(Bundle extras, int userId) {
+            enforceSystemOrSystemUI("INotificationManager.matchesCallFilter");
+            UserHandle userHandle = new UserHandle(userId);
+            return mZenModeHelper.matchesCallFilter(userHandle, extras,
                     mRankingHelper.findExtractor(ValidateNotificationPeople.class));
         }
     };
@@ -2045,12 +2065,15 @@
             }
             int indexBefore = findNotificationRecordIndexLocked(record);
             boolean interceptBefore = record.isIntercepted();
+            int visibilityBefore = record.getPackageVisibilityOverride();
             recon.applyChangesLocked(record);
             applyZenModeLocked(record);
             mRankingHelper.sort(mNotificationList);
             int indexAfter = findNotificationRecordIndexLocked(record);
             boolean interceptAfter = record.isIntercepted();
-            changed = indexBefore != indexAfter || interceptBefore != interceptAfter;
+            int visibilityAfter = record.getPackageVisibilityOverride();
+            changed = indexBefore != indexAfter || interceptBefore != interceptAfter
+                    || visibilityBefore != visibilityAfter;
             if (interceptBefore && !interceptAfter) {
                 buzzBeepBlinkLocked(record);
             }
@@ -2064,14 +2087,18 @@
         synchronized (mNotificationList) {
             final int N = mNotificationList.size();
             ArrayList<String> orderBefore = new ArrayList<String>(N);
+            int[] visibilities = new int[N];
             for (int i = 0; i < N; i++) {
                 final NotificationRecord r = mNotificationList.get(i);
                 orderBefore.add(r.getKey());
+                visibilities[i] = r.getPackageVisibilityOverride();
                 mRankingHelper.extractSignals(r);
             }
-            mRankingHelper.sort(mNotificationList);
             for (int i = 0; i < N; i++) {
-                if (!orderBefore.get(i).equals(mNotificationList.get(i).getKey())) {
+                mRankingHelper.sort(mNotificationList);
+                final NotificationRecord r = mNotificationList.get(i);
+                if (!orderBefore.get(i).equals(r.getKey())
+                        || visibilities[i] != r.getPackageVisibilityOverride()) {
                     scheduleSendRankingUpdate();
                     return;
                 }
@@ -2601,6 +2628,7 @@
         final int N = mNotificationList.size();
         ArrayList<String> keys = new ArrayList<String>(N);
         ArrayList<String> interceptedKeys = new ArrayList<String>(N);
+        Bundle visibilityOverrides = new Bundle();
         for (int i = 0; i < N; i++) {
             NotificationRecord record = mNotificationList.get(i);
             if (!isVisibleToListener(record.sbn, info)) {
@@ -2610,14 +2638,23 @@
             if (record.isIntercepted()) {
                 interceptedKeys.add(record.sbn.getKey());
             }
+            if (record.getPackageVisibilityOverride()
+                    != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
+                visibilityOverrides.putInt(record.sbn.getKey(),
+                        record.getPackageVisibilityOverride());
+            }
+            // Find first min-prio notification for speedbump placement.
             if (speedBumpIndex == -1 &&
+                    // Intrusiveness trumps priority, hence ignore intrusives.
+                    !record.isRecentlyIntrusive() &&
                     record.sbn.getNotification().priority == Notification.PRIORITY_MIN) {
                 speedBumpIndex = keys.size() - 1;
             }
         }
         String[] keysAr = keys.toArray(new String[keys.size()]);
         String[] interceptedKeysAr = interceptedKeys.toArray(new String[interceptedKeys.size()]);
-        return new NotificationRankingUpdate(keysAr, interceptedKeysAr, speedBumpIndex);
+        return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
+                speedBumpIndex);
     }
 
     private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index f2bd676..fd34aa5 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -21,6 +21,7 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.media.AudioAttributes;
+import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -65,6 +66,7 @@
 
     private int mAuthoritativeRank;
     private String mGlobalSortKey;
+    private int mPackageVisibility;
 
     @VisibleForTesting
     public NotificationRecord(StatusBarNotification sbn, int score)
@@ -79,6 +81,7 @@
         mContactAffinity = previous.mContactAffinity;
         mRecentlyIntrusive = previous.mRecentlyIntrusive;
         mPackagePriority = previous.mPackagePriority;
+        mPackageVisibility = previous.mPackageVisibility;
         mIntercept = previous.mIntercept;
         mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
         // Don't copy mGlobalSortKey, recompute it.
@@ -86,8 +89,10 @@
 
     public Notification getNotification() { return sbn.getNotification(); }
     public int getFlags() { return sbn.getNotification().flags; }
-    public int getUserId() { return sbn.getUserId(); }
+    public UserHandle getUser() { return sbn.getUser(); }
     public String getKey() { return sbn.getKey(); }
+    /** @deprecated Use {@link #getUser()} instead. */
+    public int getUserId() { return sbn.getUserId(); }
 
     void dump(PrintWriter pw, String prefix, Context baseContext) {
         final Notification notification = sbn.getNotification();
@@ -155,6 +160,7 @@
         pw.println(prefix + "  mContactAffinity=" + mContactAffinity);
         pw.println(prefix + "  mRecentlyIntrusive=" + mRecentlyIntrusive);
         pw.println(prefix + "  mPackagePriority=" + mPackagePriority);
+        pw.println(prefix + "  mPackageVisibility=" + mPackageVisibility);
         pw.println(prefix + "  mIntercept=" + mIntercept);
         pw.println(prefix + "  mGlobalSortKey=" + mGlobalSortKey);
         pw.println(prefix + "  mRankingTimeMs=" + mRankingTimeMs);
@@ -216,6 +222,14 @@
         return mPackagePriority;
     }
 
+    public void setPackageVisibilityOverride(int packageVisibility) {
+        mPackageVisibility = packageVisibility;
+    }
+
+    public int getPackageVisibilityOverride() {
+        return mPackageVisibility;
+    }
+
     public boolean setIntercepted(boolean intercept) {
         mIntercept = intercept;
         return mIntercept;
diff --git a/services/core/java/com/android/server/notification/PackageVisibilityExtractor.java b/services/core/java/com/android/server/notification/PackageVisibilityExtractor.java
new file mode 100644
index 0000000..f720f9f
--- /dev/null
+++ b/services/core/java/com/android/server/notification/PackageVisibilityExtractor.java
@@ -0,0 +1,53 @@
+/*
+* 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.server.notification;
+
+import android.content.Context;
+import android.util.Slog;
+
+public class PackageVisibilityExtractor implements NotificationSignalExtractor {
+    private static final String TAG = "PackageVisibilityExtractor";
+    private static final boolean DBG = false;
+
+    private RankingConfig mConfig;
+
+    public void initialize(Context ctx) {
+        if (DBG) Slog.d(TAG, "Initializing  " + getClass().getSimpleName() + ".");
+    }
+
+    public RankingReconsideration process(NotificationRecord record) {
+        if (record == null || record.getNotification() == null) {
+            if (DBG) Slog.d(TAG, "skipping empty notification");
+            return null;
+        }
+
+        if (mConfig == null) {
+            if (DBG) Slog.d(TAG, "missing config");
+            return null;
+        }
+
+        final int packageVisibility = mConfig.getPackageVisibilityOverride(
+                record.sbn.getPackageName(), record.sbn.getUid());
+        record.setPackageVisibilityOverride(packageVisibility);
+
+        return null;
+    }
+
+    @Override
+    public void setConfig(RankingConfig config) {
+        mConfig = config;
+    }
+}
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 7d0bd59..aea137b 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -19,4 +19,8 @@
     int getPackagePriority(String packageName, int uid);
 
     void setPackagePriority(String packageName, int uid, int priority);
+
+    int getPackageVisibilityOverride(String packageName, int uid);
+
+    void setPackageVisibilityOverride(String packageName, int uid, int visibility);
 }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 435177b..aeddecb 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -20,8 +20,10 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.UserHandle;
+import android.service.notification.NotificationListenerService;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseIntArray;
@@ -33,7 +35,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 public class RankingHelper implements RankingConfig {
@@ -49,6 +51,7 @@
     private static final String ATT_NAME = "name";
     private static final String ATT_UID = "uid";
     private static final String ATT_PRIORITY = "priority";
+    private static final String ATT_VISIBILITY = "visibility";
 
     private final NotificationSignalExtractor[] mSignalExtractors;
     private final NotificationComparator mPreliminaryComparator = new NotificationComparator();
@@ -56,6 +59,7 @@
 
     // Package name to uid, to priority. Would be better as Table<String, Int, Int>
     private final ArrayMap<String, SparseIntArray> mPackagePriorities;
+    private final ArrayMap<String, SparseIntArray> mPackageVisibilities;
     private final ArrayMap<String, NotificationRecord> mProxyByGroupTmp;
 
     private final Context mContext;
@@ -65,6 +69,7 @@
         mContext = context;
         mRankingHandler = rankingHandler;
         mPackagePriorities = new ArrayMap<String, SparseIntArray>();
+        mPackageVisibilities = new ArrayMap<String, SparseIntArray>();
 
         final int N = extractorNames.length;
         mSignalExtractors = new NotificationSignalExtractor[N];
@@ -132,15 +137,27 @@
                 if (TAG_PACKAGE.equals(tag)) {
                     int uid = safeInt(parser, ATT_UID, UserHandle.USER_ALL);
                     int priority = safeInt(parser, ATT_PRIORITY, Notification.PRIORITY_DEFAULT);
+                    int vis = safeInt(parser, ATT_VISIBILITY,
+                            NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
                     String name = parser.getAttributeValue(null, ATT_NAME);
 
-                    if (!TextUtils.isEmpty(name) && priority != Notification.PRIORITY_DEFAULT) {
-                        SparseIntArray priorityByUid = mPackagePriorities.get(name);
-                        if (priorityByUid == null) {
-                            priorityByUid = new SparseIntArray();
-                            mPackagePriorities.put(name, priorityByUid);
+                    if (!TextUtils.isEmpty(name)) {
+                        if (priority != Notification.PRIORITY_DEFAULT) {
+                            SparseIntArray priorityByUid = mPackagePriorities.get(name);
+                            if (priorityByUid == null) {
+                                priorityByUid = new SparseIntArray();
+                                mPackagePriorities.put(name, priorityByUid);
+                            }
+                            priorityByUid.put(uid, priority);
                         }
-                        priorityByUid.put(uid, priority);
+                        if (vis != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
+                            SparseIntArray visibilityByUid = mPackageVisibilities.get(name);
+                            if (visibilityByUid == null) {
+                                visibilityByUid = new SparseIntArray();
+                                mPackageVisibilities.put(name, visibilityByUid);
+                            }
+                            visibilityByUid.put(uid, vis);
+                        }
                     }
                 }
             }
@@ -152,18 +169,43 @@
         out.startTag(null, TAG_RANKING);
         out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION));
 
-        final int N = mPackagePriorities.size();
-        for (int i = 0; i < N; i ++) {
-            String name = mPackagePriorities.keyAt(i);
-            SparseIntArray priorityByUid = mPackagePriorities.get(name);
-            final int M = priorityByUid.size();
-            for (int j = 0; j < M; j++) {
-                int uid = priorityByUid.keyAt(j);
-                int priority = priorityByUid.get(uid);
+        final Set<String> packageNames = new ArraySet<>(mPackagePriorities.size()
+                + mPackageVisibilities.size());
+        packageNames.addAll(mPackagePriorities.keySet());
+        packageNames.addAll(mPackageVisibilities.keySet());
+        final Set<Integer> packageUids = new ArraySet<>();
+        for (String packageName : packageNames) {
+            packageUids.clear();
+            SparseIntArray priorityByUid = mPackagePriorities.get(packageName);
+            SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName);
+            if (priorityByUid != null) {
+                final int M = priorityByUid.size();
+                for (int j = 0; j < M; j++) {
+                    packageUids.add(priorityByUid.keyAt(j));
+                }
+            }
+            if (visibilityByUid != null) {
+                final int M = visibilityByUid.size();
+                for (int j = 0; j < M; j++) {
+                    packageUids.add(visibilityByUid.keyAt(j));
+                }
+            }
+            for (Integer uid : packageUids) {
                 out.startTag(null, TAG_PACKAGE);
-                out.attribute(null, ATT_NAME, name);
+                out.attribute(null, ATT_NAME, packageName);
+                if (priorityByUid != null) {
+                    final int priority = priorityByUid.get(uid);
+                    if (priority != Notification.PRIORITY_DEFAULT) {
+                        out.attribute(null, ATT_PRIORITY, Integer.toString(priority));
+                    }
+                }
+                if (visibilityByUid != null) {
+                    final int visibility = visibilityByUid.get(uid);
+                    if (visibility != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
+                        out.attribute(null, ATT_VISIBILITY, Integer.toString(visibility));
+                    }
+                }
                 out.attribute(null, ATT_UID, Integer.toString(uid));
-                out.attribute(null, ATT_PRIORITY, Integer.toString(priority));
                 out.endTag(null, TAG_PACKAGE);
             }
         }
@@ -293,6 +335,31 @@
         updateConfig();
     }
 
+    @Override
+    public int getPackageVisibilityOverride(String packageName, int uid) {
+        int visibility = NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+        SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName);
+        if (visibilityByUid != null) {
+            visibility = visibilityByUid.get(uid,
+                    NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
+        }
+        return visibility;
+    }
+
+    @Override
+    public void setPackageVisibilityOverride(String packageName, int uid, int visibility) {
+        if (visibility == getPackageVisibilityOverride(packageName, uid)) {
+            return;
+        }
+        SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName);
+        if (visibilityByUid == null) {
+            visibilityByUid = new SparseIntArray();
+            mPackageVisibilities.put(packageName, visibilityByUid);
+        }
+        visibilityByUid.put(uid, visibility);
+        updateConfig();
+    }
+
     public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
         if (filter == null) {
             final int N = mSignalExtractors.length;
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index aa47858..f266916 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -18,18 +18,23 @@
 
 import android.app.Notification;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Contacts;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
 import android.util.LruCache;
 import android.util.Slog;
 
 import java.util.ArrayList;
 import java.util.LinkedList;
+import java.util.Map;
 
 /**
  * This {@link NotificationSignalExtractor} attempts to validate
@@ -65,21 +70,88 @@
     static final float STARRED_CONTACT = 1f;
 
     protected boolean mEnabled;
-    private Context mContext;
+    private Context mBaseContext;
 
     // maps raw person handle to resolved person object
     private LruCache<String, LookupResult> mPeopleCache;
+    private Map<Integer, Context> mUserToContextMap;
 
-    private RankingReconsideration validatePeople(final NotificationRecord record) {
+    public void initialize(Context context) {
+        if (DEBUG) Slog.d(TAG, "Initializing  " + getClass().getSimpleName() + ".");
+        mUserToContextMap = new ArrayMap<>();
+        mBaseContext = context;
+        mPeopleCache = new LruCache<String, LookupResult>(PEOPLE_CACHE_SIZE);
+        mEnabled = ENABLE_PEOPLE_VALIDATOR && 1 == Settings.Global.getInt(
+                mBaseContext.getContentResolver(), SETTING_ENABLE_PEOPLE_VALIDATOR, 1);
+    }
+
+    public RankingReconsideration process(NotificationRecord record) {
+        if (!mEnabled) {
+            if (INFO) Slog.i(TAG, "disabled");
+            return null;
+        }
+        if (record == null || record.getNotification() == null) {
+            if (INFO) Slog.i(TAG, "skipping empty notification");
+            return null;
+        }
+        if (record.getUserId() == UserHandle.USER_ALL) {
+            if (INFO) Slog.i(TAG, "skipping global notification");
+            return null;
+        }
+        Context context = getContextAsUser(record.getUser());
+        if (context == null) {
+            if (INFO) Slog.i(TAG, "skipping notification that lacks a context");
+            return null;
+        }
+        return validatePeople(context, record);
+    }
+
+    @Override
+    public void setConfig(RankingConfig config) {
+        // ignore: config has no relevant information yet.
+    }
+
+    public float getContactAffinity(UserHandle userHandle, Bundle extras) {
+        if (extras == null) return NONE;
+        final String key = Long.toString(System.nanoTime());
+        final float[] affinityOut = new float[1];
+        Context context = getContextAsUser(userHandle);
+        if (context == null) {
+            return NONE;
+        }
+        final PeopleRankingReconsideration prr = validatePeople(context, key, extras, affinityOut);
+        float affinity = affinityOut[0];
+        if (prr != null) {
+            prr.work();
+            affinity = Math.max(prr.getContactAffinity(), affinity);
+        }
+        return affinity;
+    }
+
+    private Context getContextAsUser(UserHandle userHandle) {
+        Context context = mUserToContextMap.get(userHandle.getIdentifier());
+        if (context == null) {
+            try {
+                context = mBaseContext.createPackageContextAsUser("android", 0, userHandle);
+                mUserToContextMap.put(userHandle.getIdentifier(), context);
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.e(TAG, "failed to create package context for lookups", e);
+            }
+        }
+        return context;
+    }
+
+    private RankingReconsideration validatePeople(Context context,
+            final NotificationRecord record) {
         final String key = record.getKey();
         final Bundle extras = record.getNotification().extras;
         final float[] affinityOut = new float[1];
-        final RankingReconsideration rr = validatePeople(key, extras, affinityOut);
+        final RankingReconsideration rr = validatePeople(context, key, extras, affinityOut);
         record.setContactAffinity(affinityOut[0]);
         return rr;
     }
 
-    private PeopleRankingReconsideration validatePeople(String key, Bundle extras,
+    private PeopleRankingReconsideration validatePeople(Context context, String key, Bundle extras,
             float[] affinityOut) {
         float affinity = NONE;
         if (extras == null) {
@@ -98,7 +170,8 @@
             if (TextUtils.isEmpty(handle)) continue;
 
             synchronized (mPeopleCache) {
-                LookupResult lookupResult = mPeopleCache.get(handle);
+                final String cacheKey = getCacheKey(context.getUserId(), handle);
+                LookupResult lookupResult = mPeopleCache.get(cacheKey);
                 if (lookupResult == null || lookupResult.isExpired()) {
                     pendingLookups.add(handle);
                 } else {
@@ -119,7 +192,11 @@
         }
 
         if (DEBUG) Slog.d(TAG, "Pending: future work scheduled for: " + key);
-        return new PeopleRankingReconsideration(key, pendingLookups);
+        return new PeopleRankingReconsideration(context, key, pendingLookups);
+    }
+
+    private String getCacheKey(int userId, String handle) {
+        return Integer.toString(userId) + ":" + handle;
     }
 
     // VisibleForTesting
@@ -185,24 +262,24 @@
         return null;
     }
 
-    private LookupResult resolvePhoneContact(final String number) {
+    private LookupResult resolvePhoneContact(Context context, final String number) {
         Uri phoneUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
                 Uri.encode(number));
-        return searchContacts(phoneUri);
+        return searchContacts(context, phoneUri);
     }
 
-    private LookupResult resolveEmailContact(final String email) {
+    private LookupResult resolveEmailContact(Context context, final String email) {
         Uri numberUri = Uri.withAppendedPath(
                 ContactsContract.CommonDataKinds.Email.CONTENT_LOOKUP_URI,
                 Uri.encode(email));
-        return searchContacts(numberUri);
+        return searchContacts(context, numberUri);
     }
 
-    private LookupResult searchContacts(Uri lookupUri) {
+    private LookupResult searchContacts(Context context, Uri lookupUri) {
         LookupResult lookupResult = new LookupResult();
         Cursor c = null;
         try {
-            c = mContext.getContentResolver().query(lookupUri, LOOKUP_PROJECTION, null, null, null);
+            c = context.getContentResolver().query(lookupUri, LOOKUP_PROJECTION, null, null, null);
             if (c != null && c.getCount() > 0) {
                 c.moveToFirst();
                 lookupResult.readContact(c);
@@ -217,44 +294,6 @@
         return lookupResult;
     }
 
-    public void initialize(Context context) {
-        if (DEBUG) Slog.d(TAG, "Initializing  " + getClass().getSimpleName() + ".");
-        mContext = context;
-        mPeopleCache = new LruCache<String, LookupResult>(PEOPLE_CACHE_SIZE);
-        mEnabled = ENABLE_PEOPLE_VALIDATOR && 1 == Settings.Global.getInt(
-                mContext.getContentResolver(), SETTING_ENABLE_PEOPLE_VALIDATOR, 1);
-    }
-
-    public RankingReconsideration process(NotificationRecord record) {
-        if (!mEnabled) {
-            if (INFO) Slog.i(TAG, "disabled");
-            return null;
-        }
-        if (record == null || record.getNotification() == null) {
-            if (INFO) Slog.i(TAG, "skipping empty notification");
-            return null;
-        }
-        return validatePeople(record);
-    }
-
-    @Override
-    public void setConfig(RankingConfig config) {
-        // ignore: config has no relevant information yet.
-    }
-
-    public float getContactAffinity(Bundle extras) {
-        if (extras == null) return NONE;
-        final String key = Long.toString(System.nanoTime());
-        final float[] affinityOut = new float[1];
-        final PeopleRankingReconsideration prr = validatePeople(key, extras, affinityOut);
-        float affinity = affinityOut[0];
-        if (prr != null) {
-            prr.work();
-            affinity = Math.max(prr.getContactAffinity(), affinity);
-        }
-        return affinity;
-    }
-
     private static class LookupResult {
         private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000;  // 1hr
         public static final int INVALID_ID = -1;
@@ -317,11 +356,13 @@
 
     private class PeopleRankingReconsideration extends RankingReconsideration {
         private final LinkedList<String> mPendingLookups;
+        private final Context mContext;
 
         private float mContactAffinity = NONE;
 
-        private PeopleRankingReconsideration(String key, LinkedList<String> pendingLookups) {
+        private PeopleRankingReconsideration(Context context, String key, LinkedList<String> pendingLookups) {
             super(key);
+            mContext = context;
             mPendingLookups = pendingLookups;
         }
 
@@ -333,20 +374,21 @@
                 final Uri uri = Uri.parse(handle);
                 if ("tel".equals(uri.getScheme())) {
                     if (DEBUG) Slog.d(TAG, "checking telephone URI: " + handle);
-                    lookupResult = resolvePhoneContact(uri.getSchemeSpecificPart());
+                    lookupResult = resolvePhoneContact(mContext, uri.getSchemeSpecificPart());
                 } else if ("mailto".equals(uri.getScheme())) {
                     if (DEBUG) Slog.d(TAG, "checking mailto URI: " + handle);
-                    lookupResult = resolveEmailContact(uri.getSchemeSpecificPart());
+                    lookupResult = resolveEmailContact(mContext, uri.getSchemeSpecificPart());
                 } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
                     if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle);
-                    lookupResult = searchContacts(uri);
+                    lookupResult = searchContacts(mContext, uri);
                 } else {
                     lookupResult = new LookupResult();  // invalid person for the cache
                     Slog.w(TAG, "unsupported URI " + handle);
                 }
                 if (lookupResult != null) {
                     synchronized (mPeopleCache) {
-                        mPeopleCache.put(handle, lookupResult);
+                        final String cacheKey = getCacheKey(mContext.getUserId(), handle);
+                        mPeopleCache.put(cacheKey, lookupResult);
                     }
                     mContactAffinity = Math.max(mContactAffinity, lookupResult.getAffinity());
                 }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index fd35ede..168328f 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -373,13 +373,14 @@
         return record.isCategory(Notification.CATEGORY_MESSAGE) || isDefaultMessagingApp(record);
     }
 
-    public boolean matchesCallFilter(Bundle extras, ValidateNotificationPeople validator) {
+    public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
+            ValidateNotificationPeople validator) {
         final int zen = mZenMode;
         if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) return false; // nothing gets through
         if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
             if (!mConfig.allowCalls) return false; // no calls get through
             if (validator != null) {
-                final float contactAffinity = validator.getContactAffinity(extras);
+                final float contactAffinity = validator.getContactAffinity(userHandle, extras);
                 return audienceMatches(contactAffinity);
             }
         }
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 355f34f..a7eebf8 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -75,7 +75,7 @@
                         schedule(BackgroundDexOptService.this);
                         return;
                     }
-                    pm.performDexOpt(pkg, null /* instruction set */, false);
+                    pm.performDexOpt(pkg, null /* instruction set */, true);
                 }
                 // ran to completion, so we abandon our timeslice and do not reschedule
                 jobFinished(jobParams, false);
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index 37bedf3..4a8e318 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -538,14 +538,17 @@
                     pw.println("");
                 }
                 printedLabel = false;
-                for (long keySetId : pkg.keySetData.getSigningKeySets()) {
-                    if (!printedLabel) {
-                        pw.print("      Signing KeySets: ");
-                        printedLabel = true;
-                    } else {
-                        pw.print(", ");
+                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));
                     }
-                    pw.print(Long.toString(keySetId));
                 }
                 if (printedLabel) {
                     pw.println("");
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 85df6e2..d2a627e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -323,6 +323,7 @@
     final Context mContext;
     final boolean mFactoryTest;
     final boolean mOnlyCore;
+    final boolean mLazyDexOpt;
     final DisplayMetrics mMetrics;
     final int mDefParseFlags;
     final String[] mSeparateProcesses;
@@ -1272,6 +1273,7 @@
         mContext = context;
         mFactoryTest = factoryTest;
         mOnlyCore = onlyCore;
+        mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
         mMetrics = new DisplayMetrics();
         mSettings = new Settings(context);
         mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
@@ -4457,13 +4459,12 @@
         if (pkgs != null) {
             // Filter out packages that aren't recently used.
             //
-            // The exception is first boot of a non-eng device, which
+            // The exception is first boot of a non-eng device (aka !mLazyDexOpt), which
             // should do a full dexopt.
-            boolean eng = "eng".equals(SystemProperties.get("ro.build.type"));
-            if (eng || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
+            if (mLazyDexOpt || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
                 // TODO: add a property to control this?
                 long dexOptLRUThresholdInMinutes;
-                if (eng) {
+                if (mLazyDexOpt) {
                     dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
                 } else {
                     dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
@@ -4517,7 +4518,7 @@
 
     @Override
     public boolean performDexOptIfNeeded(String packageName, String instructionSet) {
-        return performDexOpt(packageName, instructionSet, true);
+        return performDexOpt(packageName, instructionSet, false);
     }
 
     private static String getPrimaryInstructionSet(ApplicationInfo info) {
@@ -4528,7 +4529,13 @@
         return VMRuntime.getInstructionSet(info.primaryCpuAbi);
     }
 
-    public boolean performDexOpt(String packageName, String instructionSet, boolean updateUsage) {
+    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
+        if (!dexopt && !updateUsage) {
+            // We aren't going to dexopt or update usage, so bail early.
+            return false;
+        }
         PackageParser.Package p;
         final String targetInstructionSet;
         synchronized (mPackages) {
@@ -4540,6 +4547,10 @@
                 p.mLastPackageUsageTimeInMills = System.currentTimeMillis();
             }
             mPackageUsage.write(false);
+            if (!dexopt) {
+                // We aren't going to dexopt, so bail early.
+                return false;
+            }
 
             targetInstructionSet = instructionSet != null ? instructionSet :
                     getPrimaryInstructionSet(p.applicationInfo);
@@ -10242,8 +10253,18 @@
                 if (bp != null) {
                     // If the defining package is signed with our cert, it's okay.  This
                     // also includes the "updating the same package" case, of course.
-                    if (compareSignatures(bp.packageSetting.signatures.mSignatures,
-                            pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
+                    // "updating same package" could also involve key-rotation.
+                    final boolean sigsOk;
+                    if (!bp.sourcePackage.equals(pkg.packageName)
+                            || !(bp.packageSetting instanceof PackageSetting)
+                            || !bp.packageSetting.keySetData.isUsingUpgradeKeySets()
+                            || ((PackageSetting) bp.packageSetting).sharedUser != null) {
+                        sigsOk = compareSignatures(bp.packageSetting.signatures.mSignatures,
+                                pkg.mSignatures) != PackageManager.SIGNATURE_MATCH;
+                    } else {
+                        sigsOk = checkUpgradeKeySetLP((PackageSetting) bp.packageSetting, pkg);
+                    }
+                    if (!sigsOk) {
                         // If the owning package is the system itself, we log but allow
                         // install to proceed; we fail the install on all other permission
                         // redefinitions.
@@ -12989,6 +13010,9 @@
         Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
         while (psit.hasNext()) {
             PackageSetting ps = psit.next();
+            if (ps.pkg == null) {
+                continue;
+            }
             final String packageName = ps.pkg.packageName;
             // Skip over if system app
             if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index c346f71..c1caeac 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -602,11 +602,8 @@
                             // original default value is true), or we are being
                             // asked to install for all users, or this is the
                             // user we are installing for.
-                            // In this context all users (USER_ALL) implies an adb install,
-                            // so we additionally check whether that is allowed for this user.
                             final boolean installed = installUser == null
-                                    || (installUser.getIdentifier() == UserHandle.USER_ALL
-                                            && (!isUnknownSourcesDisallowed(user.id)))
+                                    || installUser.getIdentifier() == UserHandle.USER_ALL
                                     || installUser.getIdentifier() == user.id;
                             p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
                                     installed,
@@ -673,10 +670,7 @@
                 List<UserInfo> users = getAllUsers();
                 if (users != null) {
                     for (UserInfo user : users) {
-                        // Installing for USER_ALL implies an adb install, so we
-                        // additionally check whether that is allowed for this user.
-                        if ((installUser.getIdentifier() == UserHandle.USER_ALL
-                                        && (!isUnknownSourcesDisallowed(user.id)))
+                        if (installUser.getIdentifier() == UserHandle.USER_ALL
                                 || installUser.getIdentifier() == user.id) {
                             boolean installed = p.getInstalled(user.id);
                             if (!installed) {
@@ -691,12 +685,6 @@
         return p;
     }
 
-    boolean isUnknownSourcesDisallowed(int userId) {
-        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        return um.getUserRestrictions(new UserHandle(userId)).getBoolean(
-                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
-    }
-
     void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
         p.pkg = pkg;
         // pkg.mSetEnabled = p.getEnabled(userId);
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 7e0215c..c8b5b3e 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -116,7 +116,7 @@
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
             mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
             mReceiver.register(mContext);
-            refreshAgentList();
+            refreshAgentList(UserHandle.USER_ALL);
         }
     }
 
@@ -157,11 +157,17 @@
         dispatchOnTrustChanged(aggregateIsTrusted(userId), userId, initiatedByUser);
     }
 
-    void refreshAgentList() {
+    void refreshAgentList(int userId) {
         if (DEBUG) Slog.d(TAG, "refreshAgentList()");
         PackageManager pm = mContext.getPackageManager();
 
-        List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
+        List<UserInfo> userInfos;
+        if (userId == UserHandle.USER_ALL) {
+            userInfos = mUserManager.getUsers(true /* excludeDying */);
+        } else {
+            userInfos = new ArrayList<>();
+            userInfos.add(mUserManager.getUserInfo(userId));
+        }
         LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
 
         ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
@@ -170,6 +176,7 @@
         for (UserInfo userInfo : userInfos) {
             if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
                     == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
+            if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
             DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
             int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
             final boolean disableTrustAgents =
@@ -233,7 +240,7 @@
         }
     }
 
-    void updateDevicePolicyFeatures(int userId) {
+    void updateDevicePolicyFeatures() {
         for (int i = 0; i < mActiveAgents.size(); i++) {
             AgentInfo info = mActiveAgents.valueAt(i);
             if (info.agent.isConnected()) {
@@ -276,7 +283,7 @@
         if (trustMayHaveChanged) {
             updateTrust(userId, false);
         }
-        refreshAgentList();
+        refreshAgentList(userId);
     }
 
     private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
@@ -383,7 +390,7 @@
     private void updateUserHasAuthenticated(int userId) {
         if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
             mUserHasAuthenticatedSinceBoot.put(userId, true);
-            updateTrust(userId, false);
+            refreshAgentList(userId);
         }
     }
 
@@ -391,10 +398,10 @@
     private void requireCredentialEntry(int userId) {
         if (userId == UserHandle.USER_ALL) {
             mUserHasAuthenticatedSinceBoot.clear();
-            updateTrustAll();
+            refreshAgentList(UserHandle.USER_ALL);
         } else {
             mUserHasAuthenticatedSinceBoot.put(userId, false);
-            updateTrust(userId, false);
+            refreshAgentList(userId);
         }
     }
 
@@ -578,7 +585,7 @@
                     dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
                     break;
                 case MSG_ENABLED_AGENTS_CHANGED:
-                    refreshAgentList();
+                    refreshAgentList(UserHandle.USER_ALL);
                     break;
                 case MSG_REQUIRE_CREDENTIAL_ENTRY:
                     requireCredentialEntry(msg.arg1);
@@ -590,7 +597,7 @@
     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
         @Override
         public void onSomePackagesChanged() {
-            refreshAgentList();
+            refreshAgentList(UserHandle.USER_ALL);
         }
 
         @Override
@@ -611,8 +618,8 @@
         public void onReceive(Context context, Intent intent) {
             if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
                     intent.getAction())) {
-                refreshAgentList();
-                updateDevicePolicyFeatures(getSendingUserId());
+                refreshAgentList(getSendingUserId());
+                updateDevicePolicyFeatures();
             } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
                 updateUserHasAuthenticated(getSendingUserId());
             }
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index f02c0e6..d0f00d4 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -352,6 +352,12 @@
         mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
     }
 
+    /* Notifies that the camera lens cover state has changed. */
+    @Override
+    public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
+        mService.mPolicy.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
+    }
+
     /* Provides an opportunity for the window manager policy to intercept early key
      * processing as soon as the key has been read from the device. */
     @Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0a01247..a1afe29 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5432,6 +5432,23 @@
         }
     }
 
+    // Called by window manager policy. Not exposed externally.
+    @Override
+    public int getCameraLensCoverState() {
+        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
+                InputManagerService.SW_CAMERA_LENS_COVER);
+        if (sw > 0) {
+            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
+            return CAMERA_LENS_COVERED;
+        } else if (sw == 0) {
+            // Switch state: AKEY_STATE_UP.
+            return CAMERA_LENS_UNCOVERED;
+        } else {
+            // Switch state: AKEY_STATE_UNKNOWN.
+            return CAMERA_LENS_COVER_ABSENT;
+        }
+    }
+
     // Called by window manager policy.  Not exposed externally.
     @Override
     public void switchKeyboardLayout(int deviceId, int direction) {
@@ -11398,7 +11415,8 @@
                 final WindowList windows = getDefaultWindowListLocked();
                 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
                     final WindowState win = windows.get(winNdx);
-                    if (win.mHasSurface && win.mAppToken != null) {
+                    if (win.mHasSurface
+                            && (win.mAppToken != null || mPolicy.isForceHiding(win.mAttrs))) {
                         win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
                         // Force add to mResizingWindows.
                         win.mLastContentInsets.set(-1, -1, -1, -1);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 4b7dd08..3d4be12 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -524,6 +524,7 @@
         private boolean mShown = false;
         private int mLayerStack;
         private boolean mIsOpaque;
+        private float mDsdx, mDtdx, mDsdy, mDtdy;
         private final String mName;
 
         public SurfaceTrace(SurfaceSession s,
@@ -619,6 +620,19 @@
         }
 
         @Override
+        public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+            if (dsdx != mDsdx || dtdx != mDtdx || dsdy != mDsdy || dtdy != mDtdy) {
+                Slog.v(SURFACE_TAG, "setMatrix(" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy +
+                        "): OLD:" + this + ". Called by " + Debug.getCallers(3));
+                mDsdx = dsdx;
+                mDtdx = dtdx;
+                mDsdy = dsdy;
+                mDtdy = dtdy;
+            }
+            super.setMatrix(dsdx, dtdx, dsdy, dtdy);
+        }
+
+        @Override
         public void hide() {
             if (mShown) {
                 Slog.v(SURFACE_TAG, "hide: OLD:" + this + ". Called by " + Debug.getCallers(3));
@@ -665,7 +679,8 @@
                     + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
                     + " " + mSize.x + "x" + mSize.y
                     + " crop=" + mWindowCrop.toShortString()
-                    + " opaque=" + mIsOpaque;
+                    + " opaque=" + mIsOpaque
+                    + " (" + mDsdx + "," + mDtdx + "," + mDsdy + "," + mDtdy + ")";
         }
     }
 
@@ -1068,6 +1083,14 @@
                     mShownAlpha *= appTransformation.getAlpha();
                     if (appTransformation.hasClipRect()) {
                         mClipRect.set(appTransformation.getClipRect());
+                        if (mWin.mHScale > 0) {
+                            mClipRect.left /= mWin.mHScale;
+                            mClipRect.right /= mWin.mHScale;
+                        }
+                        if (mWin.mVScale > 0) {
+                            mClipRect.top /= mWin.mVScale;
+                            mClipRect.bottom /= mWin.mVScale;
+                        }
                         mHasClipRect = true;
                     }
                 }
@@ -1418,10 +1441,10 @@
             w.mLastVScale = w.mVScale;
             if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
                     "alpha=" + mShownAlpha + " layer=" + mAnimLayer
-                    + " matrix=[" + (mDsDx*w.mHScale)
-                    + "," + (mDtDx*w.mVScale)
-                    + "][" + (mDsDy*w.mHScale)
-                    + "," + (mDtDy*w.mVScale) + "]", null);
+                    + " matrix=[" + mDsDx + "*" + w.mHScale
+                    + "," + mDtDx + "*" + w.mVScale
+                    + "][" + mDsDy + "*" + w.mHScale
+                    + "," + mDtDy + "*" + w.mVScale + "]", null);
             if (mSurfaceControl != null) {
                 try {
                     mSurfaceAlpha = mShownAlpha;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 564a3df..09584f4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -40,7 +40,6 @@
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
@@ -70,7 +69,6 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.security.Credentials;
-import android.security.IKeyChainService;
 import android.security.KeyChain;
 import android.security.KeyChain.KeyChainConnection;
 import android.util.Log;
@@ -2749,7 +2747,8 @@
         return !"".equals(state);
     }
 
-    public boolean installCaCert(ComponentName who, byte[] certBuffer) throws RemoteException {
+    @Override
+    public void enforceCanManageCaCerts(ComponentName who) {
         if (who == null) {
             mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
         } else {
@@ -2757,6 +2756,11 @@
                 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             }
         }
+    }
+
+    @Override
+    public boolean installCaCert(ComponentName admin, byte[] certBuffer) throws RemoteException {
+        enforceCanManageCaCerts(admin);
 
         byte[] pemCert;
         try {
@@ -2791,21 +2795,15 @@
         return false;
     }
 
-    private static X509Certificate parseCert(byte[] certBuffer)
-            throws CertificateException, IOException {
+    private static X509Certificate parseCert(byte[] certBuffer) throws CertificateException {
         CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
         return (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(
                 certBuffer));
     }
 
-    public void uninstallCaCert(ComponentName who, String alias) {
-        if (who == null) {
-            mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
-        } else {
-            synchronized (this) {
-                getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            }
-        }
+    @Override
+    public void uninstallCaCert(ComponentName admin, String alias) {
+        enforceCanManageCaCerts(admin);
 
         final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
         final long id = Binder.clearCallingIdentity();
@@ -2998,10 +2996,12 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
 
-        synchronized (this) {
-            DevicePolicyData policy = getUserData(userHandle);
-            long ident = Binder.clearCallingIdentity();
-            try {
+        long ident = Binder.clearCallingIdentity();
+        try {
+            boolean wipeData = false;
+            int identifier = 0;
+            synchronized (this) {
+                DevicePolicyData policy = getUserData(userHandle);
                 policy.mFailedPasswordAttempts++;
                 saveSettingsLocked(userHandle);
                 if (mHasFeature) {
@@ -3013,15 +3013,20 @@
                         // Wipe the user/profile associated with the policy that was violated. This
                         // is not necessarily calling user: if the policy that fired was from a
                         // managed profile rather than the main user profile, we wipe former only.
-                        wipeDeviceOrUserLocked(0, strictestAdmin.getUserHandle().getIdentifier());
+                        wipeData = true;
+                        identifier = strictestAdmin.getUserHandle().getIdentifier();
                     }
                     sendAdminCommandToSelfAndProfilesLocked(
                             DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
                             DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
                 }
-            } finally {
-                Binder.restoreCallingIdentity(ident);
             }
+            if (wipeData) {
+                // Call without holding lock.
+                wipeDeviceOrUserLocked(0, identifier);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -3656,11 +3661,15 @@
         }
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
 
-        if (mUserManager.getUserInfo(userHandle) == null) {
+        UserInfo info = mUserManager.getUserInfo(userHandle);
+        if (info == null) {
             // User doesn't exist.
             throw new IllegalArgumentException(
                     "Attempted to set profile owner for invalid userId: " + userHandle);
         }
+        if (info.isGuest()) {
+            throw new IllegalStateException("Cannot set a profile owner on a guest");
+        }
 
         if (who == null
                 || !DeviceOwner.isInstalledForUser(who.getPackageName(), userHandle)) {
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index ce91f3d..6785cb8 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -26,6 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
@@ -626,26 +627,40 @@
             return userState;
         }
 
-        private void handleUserStarted(int userId) {
-            UserState userState;
-            synchronized (mLock) {
-                userState = getOrCreateUserStateLocked(userId);
-                userState.updateIfNeededLocked();
-            }
-            // This is the first time we switch to this user after boot, so
-            // now is the time to remove obsolete print jobs since they
-            // are from the last boot and no application would query them.
-            userState.removeObsoletePrintJobs();
+        private void handleUserStarted(final int userId) {
+            // This code will touch the remote print spooler which
+            // must be called off the main thread, so post the work.
+            BackgroundThread.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    UserState userState;
+                    synchronized (mLock) {
+                        userState = getOrCreateUserStateLocked(userId);
+                        userState.updateIfNeededLocked();
+                    }
+                    // This is the first time we switch to this user after boot, so
+                    // now is the time to remove obsolete print jobs since they
+                    // are from the last boot and no application would query them.
+                    userState.removeObsoletePrintJobs();
+                }
+            });
         }
 
-        private void handleUserStopped(int userId) {
-            synchronized (mLock) {
-                UserState userState = mUserStates.get(userId);
-                if (userState != null) {
-                    userState.destroyLocked();
-                    mUserStates.remove(userId);
+        private void handleUserStopped(final int userId) {
+            // This code will touch the remote print spooler which
+            // must be called off the main thread, so post the work.
+            BackgroundThread.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    synchronized (mLock) {
+                        UserState userState = mUserStates.get(userId);
+                        if (userState != null) {
+                            userState.destroyLocked();
+                            mUserStates.remove(userId);
+                        }
+                    }
                 }
-            }
+            });
         }
 
         private int resolveCallingProfileParentLocked(int userId) {
@@ -730,7 +745,14 @@
                     PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT, null,
                     userHandle);
 
-            Notification.Builder builder = new Notification.Builder(mContext)
+            Context builderContext = mContext;
+            try {
+                builderContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
+                        userHandle);
+            } catch (NameNotFoundException e) {
+                // Ignore can't find the package the system is running as.
+            }
+            Notification.Builder builder = new Notification.Builder(builderContext)
                     .setSmallIcon(R.drawable.ic_print)
                     .setContentTitle(mContext.getString(R.string.print_service_installed_title,
                             label))
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 6e13732..a0b8c94 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -125,7 +125,8 @@
                 UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_OWNER);
         assertNotNull(userInfo1);
         assertNull(userInfo2);
-
+        // Verify that current user is not a managed profile
+        assertFalse(mUserManager.isManagedProfile());
         // Cleanup
         removeUser(userInfo1.id);
     }
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index dc036e2..6c80a65 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -15,17 +15,23 @@
  */
 package com.android.server.usage;
 
+import android.app.usage.ConfigurationStats;
 import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
+import android.content.res.Configuration;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
+import java.util.ArrayList;
+
 class IntervalStats {
     public long beginTime;
     public long endTime;
     public long lastTimeSaved;
     public final ArrayMap<String, UsageStats> stats = new ArrayMap<>();
+    public final ArrayMap<Configuration, ConfigurationStats> configurations = new ArrayMap<>();
+    public Configuration activeConfiguration;
     public TimeSparseArray<UsageEvents.Event> events;
 
     // A string cache. This is important as when we're parsing XML files, we don't want to
@@ -34,18 +40,49 @@
     // strings that had identical copies in the cache.
     private final ArraySet<String> mStringCache = new ArraySet<>();
 
+    /**
+     * Gets the UsageStats object for the given package, or creates one and adds it internally.
+     */
     UsageStats getOrCreateUsageStats(String packageName) {
         UsageStats usageStats = stats.get(packageName);
         if (usageStats == null) {
             usageStats = new UsageStats();
-            usageStats.mPackageName = packageName;
+            usageStats.mPackageName = getCachedStringRef(packageName);
             usageStats.mBeginTimeStamp = beginTime;
             usageStats.mEndTimeStamp = endTime;
-            stats.put(packageName, usageStats);
+            stats.put(usageStats.mPackageName, usageStats);
         }
         return usageStats;
     }
 
+    /**
+     * Gets the ConfigurationStats object for the given configuration, or creates one and adds it
+     * internally.
+     */
+    ConfigurationStats getOrCreateConfigurationStats(Configuration config) {
+        ConfigurationStats configStats = configurations.get(config);
+        if (configStats == null) {
+            configStats = new ConfigurationStats();
+            configStats.mBeginTimeStamp = beginTime;
+            configStats.mEndTimeStamp = endTime;
+            configStats.mConfiguration = config;
+            configurations.put(config, configStats);
+        }
+        return configStats;
+    }
+
+    /**
+     * Builds a UsageEvents.Event, but does not add it internally.
+     */
+    UsageEvents.Event buildEvent(String packageName, String className) {
+        UsageEvents.Event event = new UsageEvents.Event();
+        event.mPackage = getCachedStringRef(packageName);
+        if (className != null) {
+            event.mClass = getCachedStringRef(className);
+        }
+        return event;
+    }
+
     void update(String packageName, long timeStamp, int eventType) {
         UsageStats usageStats = getOrCreateUsageStats(packageName);
 
@@ -61,6 +98,28 @@
         usageStats.mLastEvent = eventType;
         usageStats.mLastTimeUsed = timeStamp;
         usageStats.mEndTimeStamp = timeStamp;
+
+        if (eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
+            usageStats.mLaunchCount += 1;
+        }
+
+        endTime = timeStamp;
+    }
+
+    void updateConfigurationStats(Configuration config, long timeStamp) {
+        if (activeConfiguration != null) {
+            ConfigurationStats activeStats = configurations.get(activeConfiguration);
+            activeStats.mTotalTimeActive += timeStamp - activeStats.mLastTimeActive;
+            activeStats.mLastTimeActive = timeStamp - 1;
+        }
+
+        if (config != null) {
+            ConfigurationStats configStats = getOrCreateConfigurationStats(config);
+            configStats.mLastTimeActive = timeStamp;
+            configStats.mActivationCount += 1;
+            activeConfiguration = configStats.mConfiguration;
+        }
+
         endTime = timeStamp;
     }
 
@@ -72,13 +131,4 @@
         }
         return mStringCache.valueAt(index);
     }
-
-    UsageEvents.Event buildEvent(String packageName, String className) {
-        UsageEvents.Event event = new UsageEvents.Event();
-        event.mPackage = getCachedStringRef(packageName);
-        if (className != null) {
-            event.mClass = getCachedStringRef(className);
-        }
-        return event;
-    }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index e6ce0fe..37340a4 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -17,7 +17,6 @@
 package com.android.server.usage;
 
 import android.app.usage.TimeSparseArray;
-import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.util.AtomicFile;
 import android.util.Slog;
@@ -133,9 +132,30 @@
     }
 
     /**
-     * Find all {@link UsageStats} for the given range and interval type.
+     * Figures out what to extract from the given IntervalStats object.
      */
-    public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime) {
+    interface StatCombiner<T> {
+
+        /**
+         * Implementations should extract interesting from <code>stats</code> and add it
+         * to the <code>accumulatedResult</code> list.
+         *
+         * If the <code>stats</code> object is mutable, <code>mutable</code> will be true,
+         * which means you should make a copy of the data before adding it to the
+         * <code>accumulatedResult</code> list.
+         *
+         * @param stats The {@link IntervalStats} object selected.
+         * @param mutable Whether or not the data inside the stats object is mutable.
+         * @param accumulatedResult The list to which to add extracted data.
+         */
+        void combine(IntervalStats stats, boolean mutable, List<T> accumulatedResult);
+    }
+
+    /**
+     * Find all {@link IntervalStats} for the given range and interval type.
+     */
+    public <T> List<T> queryUsageStats(int intervalType, long beginTime, long endTime,
+            StatCombiner<T> combiner) {
         synchronized (mLock) {
             if (intervalType < 0 || intervalType >= mIntervalDirs.length) {
                 throw new IllegalArgumentException("Bad interval type " + intervalType);
@@ -157,7 +177,7 @@
 
             try {
                 IntervalStats stats = new IntervalStats();
-                ArrayList<UsageStats> results = new ArrayList<>();
+                ArrayList<T> results = new ArrayList<>();
                 for (int i = startIndex; i <= endIndex; i++) {
                     final AtomicFile f = mSortedStatFiles[intervalType].valueAt(i);
 
@@ -167,7 +187,7 @@
 
                     UsageStatsXml.read(f, stats);
                     if (beginTime < stats.endTime) {
-                        results.addAll(stats.stats.values());
+                        combiner.combine(stats, false, results);
                     }
                 }
                 return results;
@@ -209,6 +229,10 @@
     public void prune() {
         synchronized (mLock) {
             long timeNow = System.currentTimeMillis();
+            mCal.setTimeInMillis(timeNow);
+            mCal.add(Calendar.YEAR, -3);
+            pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_YEARLY],
+                    mCal.getTimeInMillis());
 
             mCal.setTimeInMillis(timeNow);
             mCal.add(Calendar.MONTH, -6);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 0e8b427..e77bf86 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -18,6 +18,7 @@
 
 import android.Manifest;
 import android.app.AppOpsManager;
+import android.app.usage.ConfigurationStats;
 import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
@@ -30,11 +31,13 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.UserInfo;
+import android.content.res.Configuration;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.ArraySet;
@@ -218,8 +221,7 @@
      * Called by the Binder stub.
      */
     List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) {
-        final long timeNow = System.currentTimeMillis();
-        if (beginTime > timeNow) {
+        if (!validRange(beginTime, endTime)) {
             return null;
         }
 
@@ -232,15 +234,23 @@
     /**
      * Called by the Binder stub.
      */
+    List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
+            long endTime) {
+        if (!validRange(beginTime, endTime)) {
+            return null;
+        }
+
+        synchronized (mLock) {
+            UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId);
+            return service.queryConfigurationStats(bucketType, beginTime, endTime);
+        }
+    }
+
+    /**
+     * Called by the Binder stub.
+     */
     UsageEvents queryEvents(int userId, long beginTime, long endTime) {
-        final long timeNow = System.currentTimeMillis();
-
-        // Adjust the endTime so that we don't query for the latest events.
-        // This is to prevent apps from making decision based on what app launched them,
-        // etc.
-        endTime = Math.min(endTime, timeNow - END_TIME_DELAY);
-
-        if (beginTime > endTime) {
+        if (!validRange(beginTime, endTime)) {
             return null;
         }
 
@@ -250,6 +260,11 @@
         }
     }
 
+    private static boolean validRange(long beginTime, long endTime) {
+        final long timeNow = System.currentTimeMillis();
+        return beginTime <= timeNow && beginTime < endTime;
+    }
+
     private void flushToDiskLocked() {
         final int userCount = mUserState.size();
         for (int i = 0; i < userCount; i++) {
@@ -323,6 +338,28 @@
         }
 
         @Override
+        public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
+                long beginTime, long endTime, String callingPackage) throws RemoteException {
+            if (!hasPermission(callingPackage)) {
+                return null;
+            }
+
+            final int userId = UserHandle.getCallingUserId();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                final List<ConfigurationStats> results =
+                        UsageStatsService.this.queryConfigurationStats(userId, bucketType,
+                                beginTime, endTime);
+                if (results != null) {
+                    return new ParceledListSlice<>(results);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+            return null;
+        }
+
+        @Override
         public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
             if (!hasPermission(callingPackage)) {
                 return null;
@@ -346,8 +383,7 @@
     private class LocalService extends UsageStatsManagerInternal {
 
         @Override
-        public void reportEvent(ComponentName component, int userId,
-                long timeStamp, int eventType) {
+        public void reportEvent(ComponentName component, int userId, int eventType) {
             if (component == null) {
                 Slog.w(TAG, "Event reported without a component name");
                 return;
@@ -356,12 +392,27 @@
             UsageEvents.Event event = new UsageEvents.Event();
             event.mPackage = component.getPackageName();
             event.mClass = component.getClassName();
-            event.mTimeStamp = timeStamp;
+            event.mTimeStamp = System.currentTimeMillis();
             event.mEventType = eventType;
             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
         }
 
         @Override
+        public void reportConfigurationChange(Configuration config, int userId) {
+            if (config == null) {
+                Slog.w(TAG, "Configuration event reported with a null config");
+                return;
+            }
+
+            UsageEvents.Event event = new UsageEvents.Event();
+            event.mPackage = "android";
+            event.mTimeStamp = System.currentTimeMillis();
+            event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE;
+            event.mConfiguration = new Configuration(config);
+            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
+        }
+
+        @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
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index 374429a..6529950 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -20,68 +20,69 @@
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
 
+import android.app.usage.ConfigurationStats;
 import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.content.ComponentName;
+import android.content.res.Configuration;
 
 import java.io.IOException;
 import java.net.ProtocolException;
+import java.util.Locale;
 
 /**
  * UsageStats reader/writer for version 1 of the XML format.
  */
 final class UsageStatsXmlV1 {
+    private static final String PACKAGE_TAG = "package";
+    private static final String CONFIGURATION_TAG = "config";
+    private static final String EVENT_LOG_TAG = "event-log";
+
     private static final String BEGIN_TIME_ATTR = "beginTime";
     private static final String END_TIME_ATTR = "endTime";
-    private static final String PACKAGE_TAG = "package";
     private static final String NAME_ATTR = "name";
     private static final String PACKAGE_ATTR = "package";
     private static final String CLASS_ATTR = "class";
     private static final String TOTAL_TIME_ACTIVE_ATTR = "totalTimeActive";
     private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+    private static final String COUNT_ATTR = "count";
+    private static final String ACTIVE_ATTR = "active";
     private static final String LAST_EVENT_ATTR = "lastEvent";
-    private static final String EVENT_LOG_TAG = "event-log";
     private static final String TYPE_ATTR = "type";
     private static final String TIME_ATTR = "time";
 
-    private static UsageStats readNextUsageStats(XmlPullParser parser)
+    private static void loadUsageStats(XmlPullParser parser, IntervalStats statsOut)
             throws XmlPullParserException, IOException {
-        if (parser.getEventType() != XmlPullParser.START_TAG) {
-            XmlUtils.nextElement(parser);
-        }
-
-        if (parser.getEventType() != XmlPullParser.START_TAG ||
-                !parser.getName().equals(PACKAGE_TAG)) {
-            return null;
-        }
-
         final String name = parser.getAttributeValue(null, NAME_ATTR);
         if (name == null) {
             throw new ProtocolException("no " + NAME_ATTR + " attribute present");
         }
 
-        UsageStats stats = new UsageStats();
-        stats.mPackageName = name;
+        UsageStats stats = statsOut.getOrCreateUsageStats(name);
         stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
         stats.mLastTimeUsed = XmlUtils.readLongAttribute(parser, LAST_TIME_ACTIVE_ATTR);
         stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR);
-        XmlUtils.skipCurrentTag(parser);
-        return stats;
     }
 
-    private static UsageEvents.Event readNextEvent(XmlPullParser parser, IntervalStats statsOut)
+    private static void loadConfigStats(XmlPullParser parser, IntervalStats statsOut)
             throws XmlPullParserException, IOException {
-        if (parser.getEventType() != XmlPullParser.START_TAG) {
-            XmlUtils.nextElement(parser);
-        }
+        final Configuration config = new Configuration();
+        Configuration.readXmlAttrs(parser, config);
 
-        if (parser.getEventType() != XmlPullParser.START_TAG ||
-                !parser.getName().equals(EVENT_LOG_TAG)) {
-            return null;
+        ConfigurationStats configStats = statsOut.getOrCreateConfigurationStats(config);
+        configStats.mLastTimeActive = XmlUtils.readLongAttribute(parser, LAST_TIME_ACTIVE_ATTR);
+        configStats.mTotalTimeActive = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
+        configStats.mActivationCount = XmlUtils.readIntAttribute(parser, COUNT_ATTR);
+        if (XmlUtils.readBooleanAttribute(parser, ACTIVE_ATTR)) {
+            statsOut.activeConfiguration = configStats.mConfiguration;
         }
+    }
 
+    private static void loadEvent(XmlPullParser parser, IntervalStats statsOut)
+            throws XmlPullParserException, IOException {
         String packageName = XmlUtils.readStringAttribute(parser, PACKAGE_ATTR);
         String className;
         if (packageName == null) {
@@ -105,31 +106,60 @@
         UsageEvents.Event event = statsOut.buildEvent(packageName, className);
         event.mEventType = XmlUtils.readIntAttribute(parser, TYPE_ATTR);
         event.mTimeStamp = XmlUtils.readLongAttribute(parser, TIME_ATTR);
-        XmlUtils.skipCurrentTag(parser);
-        return event;
-    }
 
-    private static void writeUsageStats(FastXmlSerializer serializer, UsageStats stats)
-            throws IOException {
-        serializer.startTag(null, PACKAGE_TAG);
-        serializer.attribute(null, NAME_ATTR, stats.mPackageName);
-        serializer.attribute(null, TOTAL_TIME_ACTIVE_ATTR,
-                Long.toString(stats.mTotalTimeInForeground));
-        serializer.attribute(null, LAST_TIME_ACTIVE_ATTR, Long.toString(stats.mLastTimeUsed));
-        serializer.attribute(null, LAST_EVENT_ATTR, Integer.toString(stats.mLastEvent));
-        serializer.endTag(null, PACKAGE_TAG);
-    }
-
-    private static void writeEvent(FastXmlSerializer serializer, UsageEvents.Event event)
-            throws IOException {
-        serializer.startTag(null, EVENT_LOG_TAG);
-        serializer.attribute(null, PACKAGE_ATTR, event.mPackage);
-        if (event.mClass != null) {
-            serializer.attribute(null, CLASS_ATTR, event.mClass);
+        if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
+            event.mConfiguration = new Configuration();
+            Configuration.readXmlAttrs(parser, event.mConfiguration);
         }
-        serializer.attribute(null, TYPE_ATTR, Integer.toString(event.getEventType()));
-        serializer.attribute(null, TIME_ATTR, Long.toString(event.getTimeStamp()));
-        serializer.endTag(null, EVENT_LOG_TAG);
+
+        if (statsOut.events == null) {
+            statsOut.events = new TimeSparseArray<>();
+        }
+        statsOut.events.put(event.mTimeStamp, event);
+    }
+
+    private static void writeUsageStats(XmlSerializer xml, final UsageStats stats)
+            throws IOException {
+        xml.startTag(null, PACKAGE_TAG);
+        XmlUtils.writeStringAttribute(xml, NAME_ATTR, stats.mPackageName);
+        XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, stats.mTotalTimeInForeground);
+        XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR, stats.mLastTimeUsed);
+        XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, stats.mLastEvent);
+        xml.endTag(null, PACKAGE_TAG);
+    }
+
+    private static void writeConfigStats(XmlSerializer xml, final ConfigurationStats stats,
+            boolean isActive) throws IOException {
+        xml.startTag(null, CONFIGURATION_TAG);
+        XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR, stats.mLastTimeActive);
+        XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, stats.mTotalTimeActive);
+        XmlUtils.writeIntAttribute(xml, COUNT_ATTR, stats.mActivationCount);
+        if (isActive) {
+            XmlUtils.writeBooleanAttribute(xml, ACTIVE_ATTR, true);
+        }
+
+        // Now write the attributes representing the configuration object.
+        Configuration.writeXmlAttrs(xml, stats.mConfiguration);
+
+        xml.endTag(null, CONFIGURATION_TAG);
+    }
+
+    private static void writeEvent(XmlSerializer xml, final UsageEvents.Event event)
+            throws IOException {
+        xml.startTag(null, EVENT_LOG_TAG);
+        XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, event.mPackage);
+        if (event.mClass != null) {
+            XmlUtils.writeStringAttribute(xml, CLASS_ATTR, event.mClass);
+        }
+        XmlUtils.writeIntAttribute(xml, TYPE_ATTR, event.mEventType);
+        XmlUtils.writeLongAttribute(xml, TIME_ATTR, event.mTimeStamp);
+
+        if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE
+                && event.mConfiguration != null) {
+            Configuration.writeXmlAttrs(xml, event.mConfiguration);
+        }
+
+        xml.endTag(null, EVENT_LOG_TAG);
     }
 
     /**
@@ -142,6 +172,8 @@
     public static void read(XmlPullParser parser, IntervalStats statsOut)
             throws XmlPullParserException, IOException {
         statsOut.stats.clear();
+        statsOut.configurations.clear();
+        statsOut.activeConfiguration = null;
 
         if (statsOut.events != null) {
             statsOut.events.clear();
@@ -149,21 +181,29 @@
 
         statsOut.beginTime = XmlUtils.readLongAttribute(parser, BEGIN_TIME_ATTR);
         statsOut.endTime = XmlUtils.readLongAttribute(parser, END_TIME_ATTR);
-        XmlUtils.nextElement(parser);
 
-        UsageStats pkgStats;
-        while ((pkgStats = readNextUsageStats(parser)) != null) {
-            pkgStats.mBeginTimeStamp = statsOut.beginTime;
-            pkgStats.mEndTimeStamp = statsOut.endTime;
-            statsOut.stats.put(pkgStats.mPackageName, pkgStats);
-        }
-
-        UsageEvents.Event event;
-        while ((event = readNextEvent(parser, statsOut)) != null) {
-            if (statsOut.events == null) {
-                statsOut.events = new TimeSparseArray<>();
+        int eventCode;
+        int outerDepth = parser.getDepth();
+        while ((eventCode = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (eventCode != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (eventCode != XmlPullParser.START_TAG) {
+                continue;
             }
-            statsOut.events.put(event.getTimeStamp(), event);
+
+            final String tag = parser.getName();
+            switch (tag) {
+                case PACKAGE_TAG:
+                    loadUsageStats(parser, statsOut);
+                    break;
+
+                case CONFIGURATION_TAG:
+                    loadConfigStats(parser, statsOut);
+                    break;
+
+                case EVENT_LOG_TAG:
+                    loadEvent(parser, statsOut);
+                    break;
+            }
         }
     }
 
@@ -184,11 +224,15 @@
             writeUsageStats(serializer, stats.stats.valueAt(i));
         }
 
-        if (stats.events != null) {
-            final int eventCount = stats.events.size();
-            for (int i = 0; i < eventCount; i++) {
-                writeEvent(serializer, stats.events.valueAt(i));
-            }
+        final int configCount = stats.configurations.size();
+        for (int i = 0; i < configCount; i++) {
+            boolean active = stats.activeConfiguration.equals(stats.configurations.keyAt(i));
+            writeConfigStats(serializer, stats.configurations.valueAt(i), active);
+        }
+
+        final int eventCount = stats.events != null ? stats.events.size() : 0;
+        for (int i = 0; i < eventCount; i++) {
+            writeEvent(serializer, stats.events.valueAt(i));
         }
     }
 
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 6951590..7142a99 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -16,13 +16,17 @@
 
 package com.android.server.usage;
 
+import android.app.usage.ConfigurationStats;
 import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
+import android.content.res.Configuration;
 import android.util.ArraySet;
 import android.util.Slog;
 
+import com.android.server.usage.UsageStatsDatabase.StatCombiner;
+
 import java.io.File;
 import java.io.IOException;
 import java.text.SimpleDateFormat;
@@ -108,35 +112,91 @@
                     notifyStatsChanged();
                 }
             }
+
+            stat.updateConfigurationStats(null, stat.lastTimeSaved);
         }
     }
 
     void reportEvent(UsageEvents.Event event) {
         if (DEBUG) {
             Slog.d(TAG, mLogPrefix + "Got usage event for " + event.mPackage
-                    + "[" + event.getTimeStamp() + "]: "
-                    + eventToString(event.getEventType()));
+                    + "[" + event.mTimeStamp + "]: "
+                    + eventToString(event.mEventType));
         }
 
-        if (event.getTimeStamp() >= mDailyExpiryDate.getTimeInMillis()) {
+        if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
             // Need to rollover
             rolloverStats();
         }
 
-        if (mCurrentStats[UsageStatsManager.INTERVAL_DAILY].events == null) {
-            mCurrentStats[UsageStatsManager.INTERVAL_DAILY].events = new TimeSparseArray<>();
+        final IntervalStats currentDailyStats = mCurrentStats[UsageStatsManager.INTERVAL_DAILY];
+
+        final Configuration newFullConfig = event.mConfiguration;
+        if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE &&
+                currentDailyStats.activeConfiguration != null) {
+            // Make the event configuration a delta.
+            event.mConfiguration = Configuration.generateDelta(
+                    currentDailyStats.activeConfiguration, newFullConfig);
         }
-        mCurrentStats[UsageStatsManager.INTERVAL_DAILY].events.put(event.getTimeStamp(), event);
+
+        // Add the event to the daily list.
+        if (currentDailyStats.events == null) {
+            currentDailyStats.events = new TimeSparseArray<>();
+        }
+        currentDailyStats.events.put(event.mTimeStamp, event);
 
         for (IntervalStats stats : mCurrentStats) {
-            stats.update(event.mPackage, event.getTimeStamp(),
-                    event.getEventType());
+            if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
+                stats.updateConfigurationStats(newFullConfig, event.mTimeStamp);
+            } else {
+                stats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+            }
         }
 
         notifyStatsChanged();
     }
 
-    List<UsageStats> queryUsageStats(int bucketType, long beginTime, long endTime) {
+    private static final StatCombiner<UsageStats> sUsageStatsCombiner =
+            new StatCombiner<UsageStats>() {
+                @Override
+                public void combine(IntervalStats stats, boolean mutable,
+                        List<UsageStats> accResult) {
+                    if (!mutable) {
+                        accResult.addAll(stats.stats.values());
+                        return;
+                    }
+
+                    final int statCount = stats.stats.size();
+                    for (int i = 0; i < statCount; i++) {
+                        accResult.add(new UsageStats(stats.stats.valueAt(i)));
+                    }
+                }
+            };
+
+    private static final StatCombiner<ConfigurationStats> sConfigStatsCombiner =
+            new StatCombiner<ConfigurationStats>() {
+                @Override
+                public void combine(IntervalStats stats, boolean mutable,
+                        List<ConfigurationStats> accResult) {
+                    if (!mutable) {
+                        accResult.addAll(stats.configurations.values());
+                        return;
+                    }
+
+                    final int configCount = stats.configurations.size();
+                    for (int i = 0; i < configCount; i++) {
+                        accResult.add(new ConfigurationStats(stats.configurations.valueAt(i)));
+                    }
+                }
+            };
+
+    /**
+     * Generic query method that selects the appropriate IntervalStats for the specified time range
+     * and bucket, then calls the {@link com.android.server.usage.UsageStatsDatabase.StatCombiner}
+     * provided to select the stats to use from the IntervalStats object.
+     */
+    private <T> List<T> queryStats(int bucketType, long beginTime, long endTime,
+            StatCombiner<T> combiner) {
         if (bucketType == UsageStatsManager.INTERVAL_BEST) {
             bucketType = mDatabase.findBestFitBucket(beginTime, endTime);
         }
@@ -161,11 +221,8 @@
                 Slog.d(TAG, mLogPrefix + "Returning in-memory stats for bucket " + bucketType);
             }
             // Fast path for retrieving in-memory state.
-            ArrayList<UsageStats> results = new ArrayList<>();
-            final int packageCount = mCurrentStats[bucketType].stats.size();
-            for (int i = 0; i < packageCount; i++) {
-                results.add(new UsageStats(mCurrentStats[bucketType].stats.valueAt(i)));
-            }
+            ArrayList<T> results = new ArrayList<>();
+            combiner.combine(mCurrentStats[bucketType], true, results);
             return results;
         }
 
@@ -178,13 +235,21 @@
                     + beginTime + " AND endTime < " + endTime);
         }
 
-        final List<UsageStats> results = mDatabase.queryUsageStats(bucketType, beginTime, endTime);
+        final List<T> results = mDatabase.queryUsageStats(bucketType, beginTime, endTime, combiner);
         if (DEBUG) {
             Slog.d(TAG, mLogPrefix + "Results: " + (results == null ? 0 : results.size()));
         }
         return results;
     }
 
+    List<UsageStats> queryUsageStats(int bucketType, long beginTime, long endTime) {
+        return queryStats(bucketType, beginTime, endTime, sUsageStatsCombiner);
+    }
+
+    List<ConfigurationStats> queryConfigurationStats(int bucketType, long beginTime, long endTime) {
+        return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner);
+    }
+
     UsageEvents queryEvents(long beginTime, long endTime) {
         if (endTime > mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime) {
             if (beginTime > mCurrentStats[UsageStatsManager.INTERVAL_DAILY].endTime) {
@@ -245,6 +310,8 @@
 
         // Finish any ongoing events with an END_OF_DAY event. Make a note of which components
         // need a new CONTINUE_PREVIOUS_DAY entry.
+        final Configuration previousConfig =
+                mCurrentStats[UsageStatsManager.INTERVAL_DAILY].activeConfiguration;
         ArraySet<String> continuePreviousDay = new ArraySet<>();
         for (IntervalStats stat : mCurrentStats) {
             final int pkgCount = stat.stats.size();
@@ -253,11 +320,13 @@
                 if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
                         pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
                     continuePreviousDay.add(pkgStats.mPackageName);
-                    stat.update(pkgStats.mPackageName,
-                            mDailyExpiryDate.getTimeInMillis() - 1, UsageEvents.Event.END_OF_DAY);
+                    stat.update(pkgStats.mPackageName, mDailyExpiryDate.getTimeInMillis() - 1,
+                            UsageEvents.Event.END_OF_DAY);
                     mStatsChanged = true;
                 }
             }
+
+            stat.updateConfigurationStats(null, mDailyExpiryDate.getTimeInMillis() - 1);
         }
 
         persistActiveStats();
@@ -267,9 +336,10 @@
         final int continueCount = continuePreviousDay.size();
         for (int i = 0; i < continueCount; i++) {
             String name = continuePreviousDay.valueAt(i);
+            final long beginTime = mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime;
             for (IntervalStats stat : mCurrentStats) {
-                stat.update(name, mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime,
-                        UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+                stat.update(name, beginTime, UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+                stat.updateConfigurationStats(previousConfig, beginTime);
                 mStatsChanged = true;
             }
         }
@@ -353,6 +423,8 @@
                 return "END_OF_DAY";
             case UsageEvents.Event.CONTINUE_PREVIOUS_DAY:
                 return "CONTINUE_PREVIOUS_DAY";
+            case UsageEvents.Event.CONFIGURATION_CHANGE:
+                return "CONFIGURATION_CHANGE";
             default:
                 return "UNKNOWN";
         }
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index 7c596c1..5bf0855 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -347,14 +347,6 @@
         public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
 
         /**
-         * Launches an activity for this connection on top of the in-call UI.
-         *
-         * @param call The {@code Call} invoking this method.
-         * @param intent The intent to use to start the activity.
-         */
-        public void onStartActivity(Call call, PendingIntent intent) {}
-
-        /**
          * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
          * up their UI for the {@code Call} in response to state transitions. Specifically,
          * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
@@ -753,11 +745,6 @@
     }
 
     /** {@hide} */
-    final void internalStartActivity(PendingIntent intent) {
-        fireStartActivity(intent);
-    }
-
-    /** {@hide} */
     final void internalSetDisconnected() {
         if (mState != Call.STATE_DISCONNECTED) {
             mState = Call.STATE_DISCONNECTED;
@@ -809,12 +796,6 @@
         }
     }
 
-    private void fireStartActivity(PendingIntent intent) {
-        for (Listener listener : mListeners) {
-            listener.onStartActivity(this, intent);
-        }
-    }
-
     private void fireCallDestroyed() {
         for (Listener listener : mListeners) {
             listener.onCallDestroyed(this);
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index f349659..4d6e267 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -81,7 +81,6 @@
                 Connection c, VideoProvider videoProvider) {}
         public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
         public void onStatusHintsChanged(Connection c, StatusHints statusHints) {}
-        public void onStartActivityFromInCall(Connection c, PendingIntent intent) {}
         public void onConferenceableConnectionsChanged(
                 Connection c, List<Connection> conferenceableConnections) {}
         public void onConferenceChanged(Connection c, Conference conference) {}
@@ -942,20 +941,6 @@
     }
 
     /**
-     * Launches an activity for this connection on top of the in-call UI.
-     *
-     * @param intent The intent to use to start the activity.
-     */
-    public final void startActivityFromInCall(PendingIntent intent) {
-        if (!intent.isActivity()) {
-            throw new IllegalArgumentException("Activity intent required.");
-        }
-        for (Listener l : mListeners) {
-            l.onStartActivityFromInCall(this, intent);
-        }
-    }
-
-    /**
      * Notifies this Connection that the {@link #getAudioState()} property has a new value.
      *
      * @param state The new call audio state.
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 19cf622..2dc6910 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -463,12 +463,6 @@
         }
 
         @Override
-        public void onStartActivityFromInCall(Connection c, PendingIntent intent) {
-            String id = mIdByConnection.get(c);
-            mAdapter.startActivityFromInCall(id, intent);
-        }
-
-        @Override
         public void onConferenceableConnectionsChanged(
                 Connection connection, List<Connection> conferenceableConnections) {
             mAdapter.setConferenceableConnections(
@@ -834,24 +828,6 @@
      */
     public void onConference(Connection connection1, Connection connection2) {}
 
-    /**
-     * Notifies that a connection has been added to this connection service and sent to Telecomm.
-     *
-     * @param connection The connection which was added.
-     */
-    public void onConnectionAdded(Connection connection) {}
-
-    /**
-     * Notified that a connection has been removed from this connection service.
-     * <p>
-     * TODO: Deprecate this since we can listen to the Connection onDestroyed() to determine when
-     * it is destroyed. This then percolates down to the RemoteConference stuff, where we can also
-     * have a callback for one being added, but we don't need one for being destroyed.
-     *
-     * @param connection The connection which was removed.
-     */
-    public void onConnectionRemoved(Connection connection) {}
-
     public void onRemoteConferenceAdded(RemoteConference conference) {}
 
     /**
@@ -879,7 +855,6 @@
         mIdByConnection.put(connection, callId);
         connection.addConnectionListener(mConnectionListener);
         connection.setConnectionService(this);
-        onConnectionAdded(connection);
     }
 
     private void removeConnection(Connection connection) {
@@ -888,7 +863,6 @@
         connection.removeConnectionListener(mConnectionListener);
         mConnectionById.remove(mIdByConnection.get(connection));
         mIdByConnection.remove(connection);
-        onConnectionRemoved(connection);
         mAdapter.removeCall(id);
     }
 
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
index cb63646..e3dc713 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
@@ -346,13 +346,4 @@
             }
         }
     }
-
-    void startActivityFromInCall(String callId, PendingIntent intent) {
-        for (IConnectionServiceAdapter adapter : mAdapters) {
-            try {
-                adapter.startActivityFromInCall(callId, intent);
-            } catch (RemoteException e) {
-            }
-        }
-    }
 }
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
index 0e1c516..21e99db 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapterServant.java
@@ -57,8 +57,7 @@
     private static final int MSG_SET_STATUS_HINTS = 17;
     private static final int MSG_SET_HANDLE = 18;
     private static final int MSG_SET_CALLER_DISPLAY_NAME = 19;
-    private static final int MSG_START_ACTIVITY_FROM_IN_CALL = 20;
-    private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 21;
+    private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20;
 
     private final IConnectionServiceAdapter mDelegate;
 
@@ -192,16 +191,6 @@
                     }
                     break;
                 }
-                case MSG_START_ACTIVITY_FROM_IN_CALL: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        mDelegate.startActivityFromInCall(
-                                (String) args.arg1, (PendingIntent) args.arg2);
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
-                }
                 case MSG_SET_CONFERENCEABLE_CONNECTIONS: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
@@ -352,14 +341,6 @@
         }
 
         @Override
-        public final void startActivityFromInCall(String connectionId, PendingIntent intent) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = connectionId;
-            args.arg2 = intent;
-            mHandler.obtainMessage(MSG_START_ACTIVITY_FROM_IN_CALL, args).sendToTarget();
-        }
-
-        @Override
         public final void setConferenceableConnections(
                 String connectionId, List<String> conferenceableConnectionIds) {
             SomeArgs args = SomeArgs.obtain();
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index cbcee75..51cd537 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -55,7 +55,6 @@
     private static final int MSG_SET_POST_DIAL_WAIT = 4;
     private static final int MSG_ON_AUDIO_STATE_CHANGED = 5;
     private static final int MSG_BRING_TO_FOREGROUND = 6;
-    private static final int MSG_START_ACTIVITY = 7;
 
     /** Default Handler used to consolidate binder method calls onto a single thread. */
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -89,15 +88,6 @@
                 case MSG_BRING_TO_FOREGROUND:
                     mPhone.internalBringToForeground(msg.arg1 == 1);
                     break;
-                case MSG_START_ACTIVITY:
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        mPhone.internalStartActivity(
-                                (String) args.arg1, (PendingIntent) args.arg2);
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
                 default:
                     break;
             }
@@ -143,14 +133,6 @@
         public void bringToForeground(boolean showDialpad) {
             mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget();
         }
-
-        @Override
-        public void startActivity(String callId, PendingIntent intent) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = callId;
-            args.arg2 = intent;
-            mHandler.obtainMessage(MSG_START_ACTIVITY, args).sendToTarget();
-        }
     }
 
     private Phone mPhone;
@@ -165,11 +147,13 @@
 
     @Override
     public boolean onUnbind(Intent intent) {
-        Phone oldPhone = mPhone;
-        mPhone = null;
+        if (mPhone != null) {
+            Phone oldPhone = mPhone;
+            mPhone = null;
 
-        oldPhone.destroy();
-        onPhoneDestroyed(oldPhone);
+            oldPhone.destroy();
+            onPhoneDestroyed(oldPhone);
+        }
         return false;
     }
 
diff --git a/telecomm/java/android/telecomm/Log.java b/telecomm/java/android/telecomm/Log.java
index b8dfb11..446ae75 100644
--- a/telecomm/java/android/telecomm/Log.java
+++ b/telecomm/java/android/telecomm/Log.java
@@ -31,7 +31,7 @@
     // Generic tag for all Telecomm Framework logging
     private static final String TAG = "TelecommFramework";
 
-    public static final boolean FORCE_LOGGING = true; /* STOP SHIP if true */
+    public static final boolean FORCE_LOGGING = false; /* STOP SHIP if true */
     public static final boolean DEBUG = isLoggable(android.util.Log.DEBUG);
     public static final boolean INFO = isLoggable(android.util.Log.INFO);
     public static final boolean VERBOSE = isLoggable(android.util.Log.VERBOSE);
diff --git a/telecomm/java/android/telecomm/Phone.java b/telecomm/java/android/telecomm/Phone.java
index d90d954..8831f8f 100644
--- a/telecomm/java/android/telecomm/Phone.java
+++ b/telecomm/java/android/telecomm/Phone.java
@@ -150,14 +150,6 @@
         fireBringToForeground(showDialpad);
     }
 
-    /** {@hide} */
-    final void internalStartActivity(String telecommId, PendingIntent intent) {
-        Call call = mCallByTelecommCallId.get(telecommId);
-        if (call != null) {
-            call.internalStartActivity(intent);
-        }
-    }
-
     /**
      * Called to destroy the phone and cleanup any lingering calls.
      * @hide
diff --git a/telecomm/java/android/telecomm/PhoneAccount.java b/telecomm/java/android/telecomm/PhoneAccount.java
index 5b46409..1d61a6e 100644
--- a/telecomm/java/android/telecomm/PhoneAccount.java
+++ b/telecomm/java/android/telecomm/PhoneAccount.java
@@ -23,7 +23,12 @@
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
+import java.lang.String;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.MissingResourceException;
 
 /**
@@ -77,6 +82,21 @@
      */
     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
 
+    /**
+     * URI scheme for telephone number URIs.
+     */
+    public static final String SCHEME_TEL = "tel";
+
+    /**
+     * URI scheme for voicemail URIs.
+     */
+    public static final String SCHEME_VOICEMAIL = "voicemail";
+
+    /**
+     * URI scheme for SIP URIs.
+     */
+    public static final String SCHEME_SIP = "sip";
+
     private final PhoneAccountHandle mAccountHandle;
     private final Uri mHandle;
     private final String mSubscriptionNumber;
@@ -84,6 +104,7 @@
     private final int mIconResId;
     private final CharSequence mLabel;
     private final CharSequence mShortDescription;
+    private final List<String> mSupportedUriSchemes;
 
     public static class Builder {
         private PhoneAccountHandle mAccountHandle;
@@ -93,6 +114,7 @@
         private int mIconResId;
         private CharSequence mLabel;
         private CharSequence mShortDescription;
+        private List<String> mSupportedUriSchemes = new ArrayList<String>();
 
         public Builder() {}
 
@@ -131,7 +153,40 @@
             return this;
         }
 
+        /**
+         * Specifies an additional URI scheme supported by the {@link PhoneAccount}.
+         *
+         * @param uriScheme The URI scheme.
+         * @return The Builder.
+         */
+        public Builder withSupportedUriScheme(String uriScheme) {
+            if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
+                this.mSupportedUriSchemes.add(uriScheme);
+            }
+            return this;
+        }
+
+        /**
+         * Specifies additional URI schemes supported by the {@link PhoneAccount}.
+         *
+         * @param uriSchemes The URI schemes.
+         * @return The Builder.
+         */
+        public Builder withSupportedUriSchemes(List<String> uriSchemes) {
+            if (uriSchemes != null && !uriSchemes.isEmpty()) {
+                for (String uriScheme : uriSchemes) {
+                    withSupportedUriScheme(uriScheme);
+                }
+            }
+            return this;
+        }
+
         public PhoneAccount build() {
+            // If no supported URI schemes were defined, assume "tel" is supported.
+            if (mSupportedUriSchemes.isEmpty()) {
+                withSupportedUriScheme(SCHEME_TEL);
+            }
+
             return new PhoneAccount(
                     mAccountHandle,
                     mHandle,
@@ -139,7 +194,8 @@
                     mCapabilities,
                     mIconResId,
                     mLabel,
-                    mShortDescription);
+                    mShortDescription,
+                    mSupportedUriSchemes);
         }
     }
 
@@ -150,7 +206,8 @@
             int capabilities,
             int iconResId,
             CharSequence label,
-            CharSequence shortDescription) {
+            CharSequence shortDescription,
+            List<String> supportedUriSchemes) {
         mAccountHandle = account;
         mHandle = handle;
         mSubscriptionNumber = subscriptionNumber;
@@ -158,6 +215,7 @@
         mIconResId = iconResId;
         mLabel = label;
         mShortDescription = shortDescription;
+        mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
     }
 
     public static Builder builder() { return new Builder(); }
@@ -228,6 +286,36 @@
     }
 
     /**
+     * The URI schemes supported by this {@code PhoneAccount}.
+     *
+     * @return The URI schemes.
+     */
+    public List<String> getSupportedUriSchemes() {
+        return mSupportedUriSchemes;
+    }
+
+    /**
+     * Determines if the {@link PhoneAccount} supports calls to/from handles with a specified URI
+     * scheme.
+     *
+     * @param uriScheme The URI scheme to check.
+     * @return {@code True} if the {@code PhoneAccount} supports calls to/from handles with the
+     * specified URI scheme.
+     */
+    public boolean supportsUriScheme(String uriScheme) {
+        if (mSupportedUriSchemes == null || uriScheme == null) {
+            return false;
+        }
+
+        for (String scheme : mSupportedUriSchemes) {
+            if (scheme != null && scheme.equals(uriScheme)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * The icon resource ID for the icon of this {@code PhoneAccount}.
      *
      * @return A resource ID.
@@ -281,6 +369,7 @@
         out.writeInt(mIconResId);
         out.writeCharSequence(mLabel);
         out.writeCharSequence(mShortDescription);
+        out.writeList(mSupportedUriSchemes);
     }
 
     public static final Creator<PhoneAccount> CREATOR
@@ -297,6 +386,8 @@
     };
 
     private PhoneAccount(Parcel in) {
+        ClassLoader classLoader = PhoneAccount.class.getClassLoader();
+
         mAccountHandle = in.readParcelable(getClass().getClassLoader());
         mHandle = in.readParcelable(getClass().getClassLoader());
         mSubscriptionNumber = in.readString();
@@ -304,5 +395,9 @@
         mIconResId = in.readInt();
         mLabel = in.readCharSequence();
         mShortDescription = in.readCharSequence();
+
+        List<String> supportedUriSchemes = new ArrayList<>();
+        in.readList(supportedUriSchemes, classLoader);
+        mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
     }
 }
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index b7e4b2a..31afb4b 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -163,16 +163,6 @@
         public void onVideoStateChanged(RemoteConnection connection, int videoState) {}
 
         /**
-         * Indicates that this {@code RemoteConnection} is requesting that the in-call UI
-         * launch the specified activity.
-         *
-         * @param connection The {@code RemoteConnection} invoking this method.
-         * @param intent A {@link PendingIntent} that the {@code RemoteConnection} wishes to
-         *         have launched on its behalf.
-         */
-        public void onStartActivityFromInCall(RemoteConnection connection, PendingIntent intent) {}
-
-        /**
          * Indicates that this {@code RemoteConnection} has been destroyed. No further requests
          * should be made to the {@code RemoteConnection}, and references to it should be cleared.
          *
@@ -729,13 +719,6 @@
     }
 
     /** @hide */
-    void startActivityFromInCall(PendingIntent intent) {
-        for (Listener l : mListeners) {
-            l.onStartActivityFromInCall(this, intent);
-        }
-    }
-
-    /** @hide */
     void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) {
         mConferenceableConnections.clear();
         mConferenceableConnections.addAll(conferenceableConnections);
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 51722fe..0b6badb 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -261,12 +261,6 @@
         }
 
         @Override
-        public void startActivityFromInCall(String callId, PendingIntent intent) {
-            findConnectionForAction(callId, "startActivityFromInCall")
-                    .startActivityFromInCall(intent);
-        }
-
-        @Override
         public IBinder asBinder() {
             throw new UnsupportedOperationException();
         }
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index 2243288..b8f6964 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -62,6 +62,13 @@
             "android.telecomm.intent.action.SHOW_CALL_SETTINGS";
 
     /**
+     * The {@link android.content.Intent} action used to show the settings page used to configure
+     * {@link PhoneAccount} preferences.
+     */
+    public static final String ACTION_CHANGE_PHONE_ACCOUNTS =
+            "android.telecomm.intent.action.CHANGE_PHONE_ACCOUNTS";
+
+    /**
      * Optional extra for {@link android.content.Intent#ACTION_CALL} containing a boolean that
      * determines whether the speakerphone should be automatically turned on for an outgoing call.
      */
@@ -258,8 +265,8 @@
 
     /**
      * Return the {@link PhoneAccount} which is the user-chosen default for making outgoing phone
-     * calls. This {@code PhoneAccount} will always be a member of the list which is returned from
-     * calling {@link #getEnabledPhoneAccounts()}.
+     * calls with a specified URI scheme. This {@code PhoneAccount} will always be a member of the
+     * list which is returned from calling {@link #getEnabledPhoneAccounts()}.
      * <p>
      * Apps must be prepared for this method to return {@code null}, indicating that there currently
      * exists no user-chosen default {@code PhoneAccount}. In this case, apps wishing to initiate a
@@ -272,11 +279,13 @@
      * {@code Intent} with no {@link TelecommManager#EXTRA_PHONE_ACCOUNT_HANDLE} is valid, and
      * subsequent steps in the phone call flow are responsible for presenting the user with an
      * affordance, if necessary, to choose a {@code PhoneAccount}.
+     *
+     * @param uriScheme The URI scheme.
      */
-    public PhoneAccountHandle getDefaultOutgoingPhoneAccount() {
+    public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) {
         try {
             if (isServiceConnected()) {
-                return getTelecommService().getDefaultOutgoingPhoneAccount();
+                return getTelecommService().getDefaultOutgoingPhoneAccount(uriScheme);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelecommService#getDefaultOutgoingPhoneAccount", e);
@@ -285,16 +294,38 @@
     }
 
     /**
+     * Return the {@link PhoneAccount} which is the user-chosen default for making outgoing phone
+     * calls. This {@code PhoneAccount} will always be a member of the list which is returned from
+     * calling {@link #getEnabledPhoneAccounts()}
+     *
+     * Apps must be prepared for this method to return {@code null}, indicating that there currently
+     * exists no user-chosen default {@code PhoneAccount}.
+     *
+     * @return The user outgoing phone account selected by the user.
+     * @hide
+     */
+    public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
+        try {
+            if (isServiceConnected()) {
+                return getTelecommService().getUserSelectedOutgoingPhoneAccount();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelecommService#getUserSelectedOutgoingPhoneAccount", e);
+        }
+        return null;
+    }
+
+    /**
      * Sets the default account for making outgoing phone calls.
      * @hide
      */
-    public void setDefaultOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
+    public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
         try {
             if (isServiceConnected()) {
-                getTelecommService().setDefaultOutgoingPhoneAccount(accountHandle);
+                getTelecommService().setUserSelectedOutgoingPhoneAccount(accountHandle);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelecommService#setDefaultOutgoingPhoneAccount");
+            Log.e(TAG, "Error calling ITelecommService#setUserSelectedOutgoingPhoneAccount");
         }
     }
 
@@ -366,6 +397,40 @@
     }
 
     /**
+     * Returns the current connection manager. Apps must be prepared for this method to return
+     * {@code null}, indicating that there currently exists no user-chosen default
+     * {@code PhoneAccount}.
+     *
+     * @return The phone account handle of the current connection manager.
+     */
+    public PhoneAccountHandle getConnectionManager() {
+        return getSimCallManager();
+    }
+
+    /**
+     * Returns a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
+     * calls which support the specified URI scheme.
+     * <P>
+     * For example, invoking with {@code "tel"} will find all {@link PhoneAccountHandle}s which
+     * support telephone calls (e.g. URIs such as {@code tel:555-555-1212}).  Invoking with
+     * {@code "sip"} will find all {@link PhoneAccountHandle}s which support SIP calls (e.g. URIs
+     * such as {@code sip:example@sipexample.com}).
+     *
+     * @param uriScheme The URI scheme.
+     * @return A list of {@code PhoneAccountHandle} objects supporting the URI scheme.
+     */
+    public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) {
+        try {
+            if (isServiceConnected()) {
+                return getTelecommService().getPhoneAccountsSupportingScheme(uriScheme);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelecommService#getPhoneAccountsSupportingScheme", e);
+        }
+        return new ArrayList<>();
+    }
+
+    /**
      * Determine whether the device has more than one account registered and enabled.
      *
      * @return {@code true} if the device has more than one account registered and enabled and
@@ -677,4 +742,4 @@
         }
         return isConnected;
     }
-}
\ No newline at end of file
+}
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
index ef1769f..610178e 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
@@ -76,6 +76,4 @@
     void setCallerDisplayName(String callId, String callerDisplayName, int presentation);
 
     void setConferenceableConnections(String callId, in List<String> conferenceableCallIds);
-
-    void startActivityFromInCall(String callId, in PendingIntent intent);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallService.aidl b/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
index 5d4992f..23dbaf4 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
@@ -43,6 +43,4 @@
     void onAudioStateChanged(in AudioState audioState);
 
     void bringToForeground(boolean showDialpad);
-
-    void startActivity(String callId, in PendingIntent intent);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
index 131307a..6ab78c4 100644
--- a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
@@ -37,12 +37,17 @@
     /**
      * @see TelecommServiceImpl#getDefaultOutgoingPhoneAccount
      */
-    PhoneAccountHandle getDefaultOutgoingPhoneAccount();
+    PhoneAccountHandle getDefaultOutgoingPhoneAccount(in String uriScheme);
 
     /**
-     * @see TelecommServiceImpl#setDefaultOutgoingPhoneAccount
+     * @see TelecommServiceImpl#getUserSelectedOutgoingPhoneAccount
      */
-    void setDefaultOutgoingPhoneAccount(in PhoneAccountHandle account);
+    PhoneAccountHandle getUserSelectedOutgoingPhoneAccount();
+
+    /**
+     * @see TelecommServiceImpl#setUserSelectedOutgoingPhoneAccount
+     */
+    void setUserSelectedOutgoingPhoneAccount(in PhoneAccountHandle account);
 
     /**
      * @see TelecommServiceImpl#getOutgoingPhoneAccounts
@@ -50,7 +55,12 @@
     List<PhoneAccountHandle> getOutgoingPhoneAccounts();
 
     /**
-     * @see TelecommServiceImpl#getPhoneAccount
+     * @see TelecommManager#getPhoneAccountsSupportingScheme
+     */
+    List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme);
+
+    /**
+     * @see TelecommManager#getPhoneAccount
      */
     PhoneAccount getPhoneAccount(in PhoneAccountHandle account);
 
diff --git a/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
index dbe38ea..4621f91 100644
--- a/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
+++ b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
@@ -27,7 +27,7 @@
     /**
      * Indicates an invalid channel.
      */
-    public static int INVALID_CHANNEL = -1;
+    public static final int INVALID_CHANNEL = -1;
 
     /**
      * Possible status values returned by open channel command.
@@ -37,10 +37,10 @@
      * STATUS_NO_SUCH_ELEMENT: AID not found on UICC.
      * STATUS_UNKNOWN_ERROR: Unknown error in open channel command.
      */
-    public static int STATUS_NO_ERROR = 1;
-    public static int STATUS_MISSING_RESOURCE = 2;
-    public static int STATUS_NO_SUCH_ELEMENT = 3;
-    public static int STATUS_UNKNOWN_ERROR = 4;
+    public static final int STATUS_NO_ERROR = 1;
+    public static final int STATUS_MISSING_RESOURCE = 2;
+    public static final int STATUS_NO_SUCH_ELEMENT = 3;
+    public static final int STATUS_UNKNOWN_ERROR = 4;
 
     private final int mChannel;
     private final int mStatus;
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index acb97a0..8af5e98 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -164,14 +164,6 @@
             return uri.getSchemeSpecificPart();
         }
 
-        // TODO: We don't check for SecurityException here (requires
-        // CALL_PRIVILEGED permission).
-        if (scheme.equals("voicemail")) {
-            long subId = intent.getLongExtra(SUBSCRIPTION_KEY,
-                    SubscriptionManager.getDefaultVoiceSubId());
-            return TelephonyManager.getDefault().getCompleteVoiceMailNumber(subId);
-        }
-
         if (context == null) {
             return null;
         }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 350c27e..34da1c9 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -221,18 +221,39 @@
 
     private final Handler mHandler;
 
+    /**
+     * Create a PhoneStateListener for the Phone with the default subscription.
+     * This class requires Looper.myLooper() not return null. To supply your
+     * own non-null looper use PhoneStateListener(Looper looper) below.
+     */
     public PhoneStateListener() {
         this(SubscriptionManager.DEFAULT_SUB_ID, Looper.myLooper());
     }
 
     /**
+     * Create a PhoneStateListener for the Phone with the default subscription
+     * using a particular non-null Looper.
+     * @hide
+     */
+    public PhoneStateListener(Looper looper) {
+        this(SubscriptionManager.DEFAULT_SUB_ID, looper);
+    }
+
+    /**
+     * Create a PhoneStateListener for the Phone using the specified subscription.
+     * This class requires Looper.myLooper() not return null. To supply your
+     * own non-null Looper use PhoneStateListener(long subId, Looper looper) below.
      * @hide
      */
     public PhoneStateListener(long subId) {
         this(subId, Looper.myLooper());
     }
 
-    /** @hide */
+    /**
+     * Create a PhoneStateListener for the Phone using the specified subscription
+     * and non-null Looper.
+     * @hide
+     */
     public PhoneStateListener(long subId, Looper looper) {
         if (DBG) log("ctor: subId=" + subId + " looper=" + looper);
         mSubId = subId;
diff --git a/telephony/java/android/telephony/SubInfoRecord.java b/telephony/java/android/telephony/SubInfoRecord.java
index ced8e2f..805f787 100644
--- a/telephony/java/android/telephony/SubInfoRecord.java
+++ b/telephony/java/android/telephony/SubInfoRecord.java
@@ -1,18 +1,18 @@
 /*
-* Copyright (C) 2011-2014 MediaTek Inc.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ * 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.telephony;
 
@@ -20,96 +20,148 @@
 import android.os.Parcelable;
 
 /**
- *  A parcelable holder class of byte[] for ISms aidl implementation
- *  @hide
+ * A Parcelable class for Subscription Information.
+ * @hide - to be unhidden
  */
-
 public class SubInfoRecord implements Parcelable {
 
-    public long mSubId;
-    public String mIccId;
-    public int mSlotId;
-    public String mDisplayName;
-    public int mNameSource;
-    public int mColor;
-    public String mNumber;
-    public int mDispalyNumberFormat;
-    public int mDataRoaming;
-    public int[] mSimIconRes;
+    /**
+     * Subscription Identifier, this is a device unique number
+     * and not an index into an array
+     */
+    public long subId;
+    /** The GID for a SIM that maybe associated with this subscription, empty if unknown */
+    public String iccId;
+    /**
+     * The slot identifier for that currently contains the subscription
+     * and not necessarily unique and maybe INVALID_SLOT_ID if unknown
+     */
+    public int slotId;
+    /**
+     * The string displayed to the user that identifies this subscription
+     */
+    public String displayName;
+    /**
+     * The source of the name, NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE,
+     * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
+     */
+    public int nameSource;
+    /**
+     * The color to be used for when displaying to the user
+     */
+    public int color;
+    /**
+     * A number presented to the user identify this subscription
+     */
+    public String number;
+    /**
+     * How to display the phone number, DISPLAY_NUMBER_NONE, DISPLAY_NUMBER_FIRST,
+     * DISPLAY_NUMBER_LAST
+     */
+    public int displayNumberFormat;
+    /**
+     * Data roaming state, DATA_RAOMING_ENABLE, DATA_RAOMING_DISABLE
+     */
+    public int dataRoaming;
+    /**
+     * SIM Icon resource identifiers. FIXME: Check with MTK what it really is
+     */
+    public int[] simIconRes;
+    /**
+     * Mobile Country Code
+     */
+    public int mcc;
+    /**
+     * Mobile Network Code
+     */
+    public int mnc;
 
     public SubInfoRecord() {
-        this.mSubId = -1;
-        this.mIccId = "";
-        this.mSlotId = -1;
-        this.mDisplayName = "";
-        this.mNameSource = 0;
-        this.mColor = 0;
-        this.mNumber = "";
-        this.mDispalyNumberFormat = 0;
-        this.mDataRoaming = 0;
-        this.mSimIconRes = new int[2];
+        this.subId = SubscriptionManager.INVALID_SUB_ID;
+        this.iccId = "";
+        this.slotId = SubscriptionManager.INVALID_SLOT_ID;
+        this.displayName = "";
+        this.nameSource = 0;
+        this.color = 0;
+        this.number = "";
+        this.displayNumberFormat = 0;
+        this.dataRoaming = 0;
+        this.simIconRes = new int[2];
+        this.mcc = 0;
+        this.mnc = 0;
     }
 
-
-    public SubInfoRecord(long subId, String iccId, int slotId, String displayname, int nameSource,
-            int mColor, String mNumber, int displayFormat, int roaming, int[] iconRes) {
-        this.mSubId = subId;
-        this.mIccId = iccId;
-        this.mSlotId = slotId;
-        this.mDisplayName = displayname;
-        this.mNameSource = nameSource;
-        this.mColor = mColor;
-        this.mNumber = mNumber;
-        this.mDispalyNumberFormat = displayFormat;
-        this.mDataRoaming = roaming;
-        this.mSimIconRes = iconRes;
+    public SubInfoRecord(long subId, String iccId, int slotId, String displayName, int nameSource,
+            int color, String number, int displayFormat, int roaming, int[] iconRes,
+            int mcc, int mnc) {
+        this.subId = subId;
+        this.iccId = iccId;
+        this.slotId = slotId;
+        this.displayName = displayName;
+        this.nameSource = nameSource;
+        this.color = color;
+        this.number = number;
+        this.displayNumberFormat = displayFormat;
+        this.dataRoaming = roaming;
+        this.simIconRes = iconRes;
+        this.mcc = mcc;
+        this.mnc = mnc;
     }
 
     public static final Parcelable.Creator<SubInfoRecord> CREATOR = new Parcelable.Creator<SubInfoRecord>() {
+        @Override
         public SubInfoRecord createFromParcel(Parcel source) {
-            long mSubId = source.readLong();
-            String mIccId = source.readString();
-            int mSlotId = source.readInt();
-            String mDisplayName = source.readString();
-            int mNameSource = source.readInt();
-            int mColor = source.readInt();
-            String mNumber = source.readString();
-            int mDispalyNumberFormat = source.readInt();
-            int mDataRoaming = source.readInt();
+            long subId = source.readLong();
+            String iccId = source.readString();
+            int slotId = source.readInt();
+            String displayName = source.readString();
+            int nameSource = source.readInt();
+            int color = source.readInt();
+            String number = source.readString();
+            int displayNumberFormat = source.readInt();
+            int dataRoaming = source.readInt();
             int[] iconRes = new int[2];
             source.readIntArray(iconRes);
+            int mcc = source.readInt();
+            int mnc = source.readInt();
 
-            return new SubInfoRecord(mSubId, mIccId, mSlotId, mDisplayName, mNameSource, mColor, mNumber,
-                mDispalyNumberFormat, mDataRoaming, iconRes);
+            return new SubInfoRecord(subId, iccId, slotId, displayName, nameSource, color, number,
+                displayNumberFormat, dataRoaming, iconRes, mcc, mnc);
         }
 
+        @Override
         public SubInfoRecord[] newArray(int size) {
             return new SubInfoRecord[size];
         }
     };
 
+    @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeLong(mSubId);
-        dest.writeString(mIccId);
-        dest.writeInt(mSlotId);
-        dest.writeString(mDisplayName);
-        dest.writeInt(mNameSource);
-        dest.writeInt(mColor);
-        dest.writeString(mNumber);
-        dest.writeInt(mDispalyNumberFormat);
-        dest.writeInt(mDataRoaming);
-        dest.writeIntArray(mSimIconRes);
+        dest.writeLong(subId);
+        dest.writeString(iccId);
+        dest.writeInt(slotId);
+        dest.writeString(displayName);
+        dest.writeInt(nameSource);
+        dest.writeInt(color);
+        dest.writeString(number);
+        dest.writeInt(displayNumberFormat);
+        dest.writeInt(dataRoaming);
+        dest.writeIntArray(simIconRes);
+        dest.writeInt(mcc);
+        dest.writeInt(mnc);
     }
 
+    @Override
     public int describeContents() {
         return 0;
     }
 
+    @Override
     public String toString() {
-        return "{mSubId=" + mSubId + ", mIccId=" + mIccId + " mSlotId=" + mSlotId
-                + " mDisplayName=" + mDisplayName + " mNameSource=" + mNameSource
-                + " mColor=" + mColor + " mNumber=" + mNumber
-                + " mDispalyNumberFormat=" + mDispalyNumberFormat + " mDataRoaming=" + mDataRoaming
-                + " mSimIconRes=" + mSimIconRes + "}";
+        return "{mSubId=" + subId + ", mIccId=" + iccId + " mSlotId=" + slotId
+                + " mDisplayName=" + displayName + " mNameSource=" + nameSource
+                + " mColor=" + color + " mNumber=" + number
+                + " mDisplayNumberFormat=" + displayNumberFormat + " mDataRoaming=" + dataRoaming
+                + " mSimIconRes=" + simIconRes + " mMcc " + mcc + " mMnc " + mnc + "}";
     }
 }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 79e9fd5..58d30f1 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1,31 +1,24 @@
 /*
-* Copyright (C) 2011-2014 MediaTek Inc.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ * 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.telephony;
 
-import static android.Manifest.permission.READ_PHONE_STATE;
-
-import android.app.ActivityManagerNative;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Intent;
-import android.database.Cursor;
-import android.os.UserHandle;
 import android.net.Uri;
 import android.provider.BaseColumns;
 import android.telephony.Rlog;
@@ -34,149 +27,247 @@
 
 import com.android.internal.telephony.ISub;
 import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.TelephonyIntents;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map.Entry;
 
 /**
- *@hide
+ * SubscriptionManager is the application interface to SubscriptionController
+ * and provides information about the current Telephony Subscriptions.
+ *
+ * The android.Manifest.permission.READ_PHONE_STATE to retrieve the information, except
+ * getActiveSubIdList and getActiveSubIdCount for which no permission is needed.
+ *
+ * @hide - to be unhidden
  */
 public class SubscriptionManager implements BaseColumns {
     private static final String LOG_TAG = "SUB";
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
-    // An invalid subscription identifier
-    public static final long INVALID_SUB_ID = Long.MAX_VALUE;
+    /** An invalid phone identifier */
+    /** @hide - to be unhidden */
+    public static final int INVALID_PHONE_ID = -1000;
 
-    // The default subscription identifier
-    public static final long DEFAULT_SUB_ID = Long.MAX_VALUE - 1;
+    /** Indicates the caller wants the default phone id. */
+    /** @hide - to be unhidden */
+    public static final int DEFAULT_PHONE_ID = Integer.MAX_VALUE;
 
+    /** An invalid slot identifier */
+    /** @hide - to be unhidden */
+    public static final int INVALID_SLOT_ID = -1000;
+
+    /** Indicates the caller wants the default slot id. */
+    /** @hide */
+    public static final int DEFAULT_SLOT_ID = Integer.MAX_VALUE;
+
+    /** Indicates the user should be asked which sub to use. */
+    /** @hide */
+    public static final long ASK_USER_SUB_ID = -1001;
+
+    /** An invalid subscription identifier */
+    public static final long INVALID_SUB_ID = -1000;
+
+    /** Indicates the caller wants the default sub id. */
+    /** @hide - to be unhidden */
+    public static final long DEFAULT_SUB_ID = Long.MAX_VALUE;
+
+    /** @hide */
     public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
 
+    /** @hide */
     public static final int DEFAULT_INT_VALUE = -100;
 
+    /** @hide */
     public static final String DEFAULT_STRING_VALUE = "N/A";
 
+    /** @hide */
     public static final int EXTRA_VALUE_NEW_SIM = 1;
+
+    /** @hide */
     public static final int EXTRA_VALUE_REMOVE_SIM = 2;
+    /** @hide */
     public static final int EXTRA_VALUE_REPOSITION_SIM = 3;
+    /** @hide */
     public static final int EXTRA_VALUE_NOCHANGE = 4;
 
+    /** @hide */
     public static final String INTENT_KEY_DETECT_STATUS = "simDetectStatus";
+    /** @hide */
     public static final String INTENT_KEY_SIM_COUNT = "simCount";
+    /** @hide */
     public static final String INTENT_KEY_NEW_SIM_SLOT = "newSIMSlot";
+    /** @hide */
     public static final String INTENT_KEY_NEW_SIM_STATUS = "newSIMStatus";
 
     /**
      * The ICC ID of a SIM.
      * <P>Type: TEXT (String)</P>
      */
+    /** @hide */
     public static final String ICC_ID = "icc_id";
 
     /**
      * <P>Type: INTEGER (int)</P>
      */
+    /** @hide */
     public static final String SIM_ID = "sim_id";
 
+    /** SIM is not inserted */
+    /** @hide - to be unhidden */
     public static final int SIM_NOT_INSERTED = -1;
 
     /**
-     * The display name of a SIM.
+     * TelephonyProvider column name for user displayed name.
      * <P>Type: TEXT (String)</P>
      */
+    /** @hide */
     public static final String DISPLAY_NAME = "display_name";
 
+    /**
+     * Default name resource
+     * @hide
+     */
     public static final int DEFAULT_NAME_RES = com.android.internal.R.string.unknownName;
 
     /**
-     * The display name source of a SIM.
-     * <P>Type: INT (int)</P>
+     * TelephonyProvider column name for source of the user displayed name.
+     * <P>Type: INT (int)</P> with one of the NAME_SOURCE_XXXX values below
+     *
+     * @hide
      */
     public static final String NAME_SOURCE = "name_source";
 
-    public static final int DEFAULT_SOURCE = 0;
-
-    public static final int SIM_SOURCE = 1;
-
-    public static final int USER_INPUT = 2;
+    /**
+     * The name_source is undefined
+     * @hide
+     */
+    public static final int NAME_SOURCE_UNDEFINDED = -1;
 
     /**
-     * The color of a SIM.
+     * The name_source is the default
+     * @hide
+     */
+    public static final int NAME_SOURCE_DEFAULT_SOURCE = 0;
+
+    /**
+     * The name_source is from the SIM
+     * @hide
+     */
+    public static final int NAME_SOURCE_SIM_SOURCE = 1;
+
+    /**
+     * The name_source is from the user
+     * @hide
+     */
+    public static final int NAME_SOURCE_USER_INPUT = 2;
+
+    /**
+     * TelephonyProvider column name for the color of a SIM.
      * <P>Type: INTEGER (int)</P>
      */
+    /** @hide */
     public static final String COLOR = "color";
 
+    /** @hide */
     public static final int COLOR_1 = 0;
 
+    /** @hide */
     public static final int COLOR_2 = 1;
 
+    /** @hide */
     public static final int COLOR_3 = 2;
 
+    /** @hide */
     public static final int COLOR_4 = 3;
 
+    /** @hide */
     public static final int COLOR_DEFAULT = COLOR_1;
 
     /**
-     * The phone number of a SIM.
+     * TelephonyProvider column name for the phone number of a SIM.
      * <P>Type: TEXT (String)</P>
      */
+    /** @hide */
     public static final String NUMBER = "number";
 
     /**
-     * The number display format of a SIM.
+     * TelephonyProvider column name for the number display format of a SIM.
      * <P>Type: INTEGER (int)</P>
      */
+    /** @hide */
     public static final String DISPLAY_NUMBER_FORMAT = "display_number_format";
 
-    public static final int DISPALY_NUMBER_NONE = 0;
+    /** @hide */
+    public static final int DISPLAY_NUMBER_NONE = 0;
 
+    /** @hide */
     public static final int DISPLAY_NUMBER_FIRST = 1;
 
+    /** @hide */
     public static final int DISPLAY_NUMBER_LAST = 2;
 
+    /** @hide */
     public static final int DISLPAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST;
 
     /**
-     * Permission for data roaming of a SIM.
+     * TelephonyProvider column name for permission for data roaming of a SIM.
      * <P>Type: INTEGER (int)</P>
      */
+    /** @hide */
     public static final String DATA_ROAMING = "data_roaming";
 
+    /** @hide */
     public static final int DATA_ROAMING_ENABLE = 1;
 
+    /** @hide */
     public static final int DATA_ROAMING_DISABLE = 0;
 
+    /** @hide */
     public static final int DATA_ROAMING_DEFAULT = DATA_ROAMING_DISABLE;
 
+    /**
+     * TelephonyProvider column name for the MCC associated with a SIM.
+     * <P>Type: INTEGER (int)</P>
+     */
+    public static final String MCC = "mcc";
+
+    /**
+     * TelephonyProvider column name for the MNC associated with a SIM.
+     * <P>Type: INTEGER (int)</P>
+     */
+    public static final String MNC = "mnc";
+
+
     private static final int RES_TYPE_BACKGROUND_DARK = 0;
 
     private static final int RES_TYPE_BACKGROUND_LIGHT = 1;
 
     private static final int[] sSimBackgroundDarkRes = setSimResource(RES_TYPE_BACKGROUND_DARK);
 
-    private static final int[] sSimBackgroundLightRes = setSimResource(RES_TYPE_BACKGROUND_LIGHT);
+    /**
+     * Broadcast Action: The user has changed one of the default subs related to
+     * data, phone calls, or sms</p>
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String SUB_DEFAULT_CHANGED_ACTION =
+        "android.intent.action.SUB_DEFAULT_CHANGED";
 
-    private static HashMap<Integer, Long> mSimInfo = new HashMap<Integer, Long>();
-
+    /** @hide */
     public SubscriptionManager() {
         if (DBG) logd("SubscriptionManager created");
     }
 
     /**
-     * Get the SubInfoRecord according to an index
-     * @param context Context provided by caller
+     * Get the SubInfoRecord associated with the subId
      * @param subId The unique SubInfoRecord index in database
      * @return SubInfoRecord, maybe null
+     * @hide - to be unhidden
      */
-    public static SubInfoRecord getSubInfoUsingSubId(Context context, long subId) {
-        if (VDBG) logd("[getSubInfoUsingSubIdx]+ subId:" + subId);
-        if (subId <= 0) {
-            if (VDBG) logd("[getSubInfoUsingSubIdx]- subId <= 0");
+    public static SubInfoRecord getSubInfoUsingSubId(long subId) {
+        if (!isValidSubId(subId)) {
+            logd("[getSubInfoUsingSubIdx]- invalid subId");
             return null;
         }
 
@@ -197,11 +288,11 @@
 
     /**
      * Get the SubInfoRecord according to an IccId
-     * @param context Context provided by caller
      * @param iccId the IccId of SIM card
-     * @return SubInfoRecord, maybe null
+     * @return SubInfoRecord List, maybe empty but not null
+     * @hide
      */
-    public static List<SubInfoRecord> getSubInfoUsingIccId(Context context, String iccId) {
+    public static List<SubInfoRecord> getSubInfoUsingIccId(String iccId) {
         if (VDBG) logd("[getSubInfoUsingIccId]+ iccId=" + iccId);
         if (iccId == null) {
             logd("[getSubInfoUsingIccId]- null iccid");
@@ -219,19 +310,23 @@
             // ignore it
         }
 
+
+        if (result == null) {
+            result = new ArrayList<SubInfoRecord>();
+        }
         return result;
     }
 
     /**
      * Get the SubInfoRecord according to slotId
-     * @param context Context provided by caller
      * @param slotId the slot which the SIM is inserted
-     * @return SubInfoRecord, maybe null
+     * @return SubInfoRecord list, maybe empty but not null
+     * @hide - to be unhidden
      */
-    public static List<SubInfoRecord> getSubInfoUsingSlotId(Context context, int slotId) {
-        if (VDBG) logd("[getSubInfoUsingSlotId]- slotId=" + slotId);
-        if (slotId < 0) {
-            logd("[getSubInfoUsingSlotId]- return null, slotId < 0");
+    public static List<SubInfoRecord> getSubInfoUsingSlotId(int slotId) {
+        // FIXME: Consider never returning null
+        if (!isValidSlotId(slotId)) {
+            logd("[getSubInfoUsingSlotId]- invalid slotId");
             return null;
         }
 
@@ -246,15 +341,20 @@
             // ignore it
         }
 
+
+        if (result == null) {
+            result = new ArrayList<SubInfoRecord>();
+        }
         return result;
     }
 
     /**
-     * Get all the SubInfoRecord(s) in subinfo database
-     * @param context Context provided by caller
-     * @return Array list of all SubInfoRecords in database, include thsoe that were inserted before
+     * Get all the SubInfoRecord(s) in subInfo database
+     * @return List of all SubInfoRecords in database, include those that were inserted before
+     * maybe empty but not null.
+     * @hide
      */
-    public static List<SubInfoRecord> getAllSubInfoList(Context context) {
+    public static List<SubInfoRecord> getAllSubInfoList() {
         if (VDBG) logd("[getAllSubInfoList]+");
 
         List<SubInfoRecord> result = null;
@@ -268,37 +368,41 @@
             // ignore it
         }
 
+        if (result == null) {
+            result = new ArrayList<SubInfoRecord>();
+        }
         return result;
     }
 
     /**
      * Get the SubInfoRecord(s) of the currently inserted SIM(s)
-     * @param context Context provided by caller
-     * @return Array list of currently inserted SubInfoRecord(s)
+     * @return Array list of currently inserted SubInfoRecord(s) maybe empty but not null
+     * @hide - to be unhidden
      */
-    public static List<SubInfoRecord> getActivatedSubInfoList(Context context) {
-        if (VDBG) logd("[getActivatedSubInfoList]+");
-
+    public static List<SubInfoRecord> getActiveSubInfoList() {
         List<SubInfoRecord> result = null;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                result = iSub.getActivatedSubInfoList();
+                result = iSub.getActiveSubInfoList();
             }
         } catch (RemoteException ex) {
             // ignore it
         }
 
+        if (result == null) {
+            result = new ArrayList<SubInfoRecord>();
+        }
         return result;
     }
 
     /**
      * Get the SUB count of all SUB(s) in subinfo database
-     * @param context Context provided by caller
      * @return all SIM count in database, include what was inserted before
+     * @hide
      */
-    public static int getAllSubInfoCount(Context context) {
+    public static int getAllSubInfoCount() {
         if (VDBG) logd("[getAllSubInfoCount]+");
 
         int result = 0;
@@ -316,17 +420,40 @@
     }
 
     /**
+     * Get the count of active SUB(s)
+     * @return active SIM count
+     * @hide
+     */
+    public static int getActiveSubInfoCount() {
+        int result = 0;
+
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                result = iSub.getActiveSubInfoCount();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return result;
+    }
+
+    /**
      * Add a new SubInfoRecord to subinfo database if needed
-     * @param context Context provided by caller
      * @param iccId the IccId of the SIM card
      * @param slotId the slot which the SIM is inserted
      * @return the URL of the newly created row or the updated row
+     * @hide
      */
-    public static Uri addSubInfoRecord(Context context, String iccId, int slotId) {
+    public static Uri addSubInfoRecord(String iccId, int slotId) {
         if (VDBG) logd("[addSubInfoRecord]+ iccId:" + iccId + " slotId:" + slotId);
         if (iccId == null) {
             logd("[addSubInfoRecord]- null iccId");
         }
+        if (!isValidSlotId(slotId)) {
+            logd("[addSubInfoRecord]- invalid slotId");
+        }
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -345,15 +472,15 @@
 
     /**
      * Set SIM color by simInfo index
-     * @param context Context provided by caller
      * @param color the color of the SIM
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
+     * @hide
      */
-    public static int setColor(Context context, int color, long subId) {
+    public static int setColor(int color, long subId) {
         if (VDBG) logd("[setColor]+ color:" + color + " subId:" + subId);
         int size = sSimBackgroundDarkRes.length;
-        if (subId <= 0 || color < 0 || color >= size) {
+        if (!isValidSubId(subId) || color < 0 || color >= size) {
             logd("[setColor]- fail");
             return -1;
         }
@@ -375,26 +502,30 @@
 
     /**
      * Set display name by simInfo index
-     * @param context Context provided by caller
      * @param displayName the display name of SIM card
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
+     * @hide
      */
-    public static int setDisplayName(Context context, String displayName, long subId) {
-        return setDisplayName(context, displayName, subId, -1);
+    public static int setDisplayName(String displayName, long subId) {
+        return setDisplayName(displayName, subId, NAME_SOURCE_UNDEFINDED);
     }
 
     /**
      * Set display name by simInfo index with name source
-     * @param context Context provided by caller
      * @param displayName the display name of SIM card
      * @param subId the unique SubInfoRecord index in database
-     * @param nameSource, 0: DEFAULT_SOURCE, 1: SIM_SOURCE, 2: USER_INPUT
-     * @return the number of records updated
+     * @param nameSource 0: NAME_SOURCE_DEFAULT_SOURCE, 1: NAME_SOURCE_SIM_SOURCE,
+     *                   2: NAME_SOURCE_USER_INPUT, -1 NAME_SOURCE_UNDEFINED
+     * @return the number of records updated or -1 if invalid subId
+     * @hide
      */
-    public static int setDisplayName(Context context, String displayName, long subId, long nameSource) {
-        if (VDBG) logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId + " nameSource:" + nameSource);
-        if (subId <= 0) {
+    public static int setDisplayName(String displayName, long subId, long nameSource) {
+        if (VDBG) {
+            logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId
+                    + " nameSource:" + nameSource);
+        }
+        if (!isValidSubId(subId)) {
             logd("[setDisplayName]- fail");
             return -1;
         }
@@ -416,15 +547,14 @@
 
     /**
      * Set phone number by subId
-     * @param context Context provided by caller
      * @param number the phone number of the SIM
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
+     * @hide
      */
-    public static int setDispalyNumber(Context context, String number, long subId) {
-        if (VDBG) logd("[setDispalyNumber]+ number:" + number + " subId:" + subId);
-        if (number == null || subId <= 0) {
-            logd("[setDispalyNumber]- fail");
+    public static int setDisplayNumber(String number, long subId) {
+        if (number == null || !isValidSubId(subId)) {
+            logd("[setDisplayNumber]- fail");
             return -1;
         }
 
@@ -433,7 +563,7 @@
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                result = iSub.setDispalyNumber(number, subId);
+                result = iSub.setDisplayNumber(number, subId);
             }
         } catch (RemoteException ex) {
             // ignore it
@@ -445,14 +575,14 @@
 
     /**
      * Set number display format. 0: none, 1: the first four digits, 2: the last four digits
-     * @param context Context provided by caller
      * @param format the display format of phone number
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
+     * @hide
      */
-    public static int setDisplayNumberFormat(Context context, int format, long subId) {
+    public static int setDisplayNumberFormat(int format, long subId) {
         if (VDBG) logd("[setDisplayNumberFormat]+ format:" + format + " subId:" + subId);
-        if (format < 0 || subId <= 0) {
+        if (format < 0 || !isValidSubId(subId)) {
             logd("[setDisplayNumberFormat]- fail, return -1");
             return -1;
         }
@@ -474,14 +604,14 @@
 
     /**
      * Set data roaming by simInfo index
-     * @param context Context provided by caller
      * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
+     * @hide
      */
-    public static int setDataRoaming(Context context, int roaming, long subId) {
+    public static int setDataRoaming(int roaming, long subId) {
         if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId);
-        if (roaming < 0 || subId <= 0) {
+        if (roaming < 0 || !isValidSubId(subId)) {
             logd("[setDataRoaming]- fail");
             return -1;
         }
@@ -500,10 +630,18 @@
         return result;
     }
 
+    /**
+     * Get slotId associated with the subscription.
+     * @return slotId as a positive integer or a negative value if an error either
+     * SIM_NOT_INSERTED or INVALID_SLOT_ID.
+     * @hide - to be unhidden
+     */
     public static int getSlotId(long subId) {
-        if (VDBG) logd("[getSlotId]+ subId:" + subId);
+        if (!isValidSubId(subId)) {
+            logd("[getSlotId]- fail");
+        }
 
-        int result = 0;
+        int result = INVALID_SLOT_ID;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -518,8 +656,12 @@
 
     }
 
+    /** @hide */
     public static long[] getSubId(int slotId) {
-        if (VDBG) logd("[getSubId]+ slotId:" + slotId);
+        if (!isValidSlotId(slotId)) {
+            logd("[getSubId]- fail");
+            return null;
+        }
 
         long[] subId = null;
 
@@ -535,10 +677,14 @@
         return subId;
     }
 
+    /** @hide */
     public static int getPhoneId(long subId) {
-        if (VDBG) logd("[getPhoneId]+ subId=" + subId);
+        if (!isValidSubId(subId)) {
+            logd("[getPhoneId]- fail");
+            return INVALID_PHONE_ID;
+        }
 
-        int result = 0;
+        int result = INVALID_PHONE_ID;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -549,7 +695,7 @@
             // ignore it
         }
 
-        if (VDBG) logd("[getPhoneId]- phonId=" + result);
+        if (VDBG) logd("[getPhoneId]- phoneId=" + result);
         return result;
 
     }
@@ -583,23 +729,14 @@
         Rlog.d(LOG_TAG, "[SubManager] " + msg);
     }
 
-    public static long normalizeSubId(long subId) {
-        long retVal = (subId == DEFAULT_SUB_ID) ? getDefaultSubId() : subId;
-        Rlog.d(LOG_TAG, "[SubManager] normalizeSubId subId=" + retVal);
-        return retVal;
-    }
-
-    public static boolean validSubId(long subId) {
-        return (subId != DEFAULT_SUB_ID) && (subId != -1);
-    }
-
     /**
      * @return the "system" defaultSubId on a voice capable device this
      * will be getDefaultVoiceSubId() and on a data only device it will be
      * getDefaultDataSubId().
+     * @hide
      */
     public static long getDefaultSubId() {
-        long subId = 1;
+        long subId = INVALID_SUB_ID;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -614,8 +751,9 @@
         return subId;
     }
 
+    /** @hide */
     public static long getDefaultVoiceSubId() {
-        long subId = 1;
+        long subId = INVALID_SUB_ID;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -626,10 +764,11 @@
             // ignore it
         }
 
-        if (VDBG) logd("getDefaultSubId, sub id = " + subId);
+        if (VDBG) logd("getDefaultVoiceSubId, sub id = " + subId);
         return subId;
     }
 
+    /** @hide */
     public static void setDefaultVoiceSubId(long subId) {
         if (VDBG) logd("setDefaultVoiceSubId sub id = " + subId);
         try {
@@ -638,34 +777,81 @@
                 iSub.setDefaultVoiceSubId(subId);
             }
         } catch (RemoteException ex) {
-         // ignore it
+            // ignore it
         }
     }
 
-    public static long getPreferredSmsSubId() {
-        // FIXME add framework support to get the preferred sub
-        return getDefaultSubId();
+    /** @hide */
+    public static SubInfoRecord getDefaultVoiceSubInfo() {
+        return getSubInfoUsingSubId(getDefaultVoiceSubId());
     }
 
-    public static long getPreferredDataSubId() {
-        // FIXME add framework support to get the preferred sub
-        return getDefaultSubId();
+    /** @hide */
+    public static int getDefaultVoicePhoneId() {
+        return getPhoneId(getDefaultVoiceSubId());
     }
 
-    public static long getDefaultDataSubId() {
+    /**
+     * @return subId of the DefaultSms subscription or the value INVALID_SUB_ID if an error.
+     * @hide - to be unhidden
+     */
+    public static long getDefaultSmsSubId() {
+        long subId = INVALID_SUB_ID;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                return iSub.getDefaultDataSubId();
-            } else {
-                return -1;
+                subId = iSub.getDefaultSmsSubId();
             }
         } catch (RemoteException ex) {
-            return -1;
+            // ignore it
+        }
+
+        if (VDBG) logd("getDefaultSmsSubId, sub id = " + subId);
+        return subId;
+    }
+
+    /** @hide */
+    public static void setDefaultSmsSubId(long subId) {
+        if (VDBG) logd("setDefaultSmsSubId sub id = " + subId);
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                iSub.setDefaultSmsSubId(subId);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
         }
     }
 
+    /** @hide */
+    public static SubInfoRecord getDefaultSmsSubInfo() {
+        return getSubInfoUsingSubId(getDefaultSmsSubId());
+    }
+
+    /** @hide */
+    public static int getDefaultSmsPhoneId() {
+        return getPhoneId(getDefaultSmsSubId());
+    }
+
+    /** @hide */
+    public static long getDefaultDataSubId() {
+        long subId = INVALID_SUB_ID;
+
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                subId = iSub.getDefaultDataSubId();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        if (VDBG) logd("getDefaultDataSubId, sub id = " + subId);
+        return subId;
+    }
+
+    /** @hide */
     public static void setDefaultDataSubId(long subId) {
         if (VDBG) logd("setDataSubscription sub id = " + subId);
         try {
@@ -674,14 +860,22 @@
                 iSub.setDefaultDataSubId(subId);
             }
         } catch (RemoteException ex) {
-         // ignore it
+            // ignore it
         }
     }
 
-    public static void clearSubInfo()
-    {
-        if (VDBG) logd("[clearSubInfo]+");
+    /** @hide */
+    public static SubInfoRecord getDefaultDataSubInfo() {
+        return getSubInfoUsingSubId(getDefaultDataSubId());
+    }
 
+    /** @hide */
+    public static int getDefaultDataPhoneId() {
+        return getPhoneId(getDefaultDataSubId());
+    }
+
+    /** @hide */
+    public static void clearSubInfo() {
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
@@ -694,19 +888,100 @@
         return;
     }
 
+    //FIXME this is vulnerable to race conditions
+    /** @hide */
+    public static boolean allDefaultsSelected() {
+        if (getDefaultDataSubId() == INVALID_SUB_ID) {
+            return false;
+        }
+        if (getDefaultSmsSubId() == INVALID_SUB_ID) {
+            return false;
+        }
+        if (getDefaultVoiceSubId() == INVALID_SUB_ID) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * If a default is set to subscription which is not active, this will reset that default back to
+     * INVALID_SUB_ID.
+     * @hide
+     */
+    public static void clearDefaultsForInactiveSubIds() {
+        if (VDBG) logd("clearDefaultsForInactiveSubIds");
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                iSub.clearDefaultsForInactiveSubIds();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
+     * @return true if a valid subId else false
+     * @hide - to be unhidden
+     */
+    public static boolean isValidSubId(long subId) {
+        return subId > INVALID_SUB_ID ;
+    }
+
+    /** @hide */
+    public static boolean isValidSlotId(int slotId) {
+        return slotId > INVALID_SLOT_ID && slotId < TelephonyManager.getDefault().getSimCount();
+    }
+
+    /** @hide */
+    public static boolean isValidPhoneId(int phoneId) {
+        return phoneId > INVALID_PHONE_ID
+                && phoneId < TelephonyManager.getDefault().getPhoneCount();
+    }
+
+    /** @hide */
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
-        long [] subId = SubscriptionManager.getSubId(phoneId);
-        if ((subId != null) && (subId.length >= 1)) {
-            putPhoneIdAndSubIdExtra(intent, phoneId, subId[0]);
+        long[] subIds = SubscriptionManager.getSubId(phoneId);
+        if (subIds != null && subIds.length > 0) {
+            putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]);
         } else {
             logd("putPhoneIdAndSubIdExtra: no valid subs");
         }
     }
 
+    /** @hide */
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, long subId) {
         if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
-        intent.putExtra(PhoneConstants.SLOT_KEY, phoneId); //FIXME: RENAME TO PHONE_ID_KEY ??
         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+        intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
+        //FIXME this is using phoneId and slotId interchangeably
+        //Eventually, this should be removed as it is not the slot id
+        intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
+    }
+
+    /**
+     * @return the list of subId's that are active,
+     *         is never null but the length maybe 0.
+     * @hide
+     */
+    public static long[] getActiveSubIdList() {
+        long[] subId = null;
+
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                subId = iSub.getActiveSubIdList();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        if (subId == null) {
+            subId = new long[0];
+        }
+
+        return subId;
+
     }
 }
 
diff --git a/telephony/java/com/android/internal/telephony/IMms.aidl b/telephony/java/com/android/internal/telephony/IMms.aidl
index cbcef25..4337012 100644
--- a/telephony/java/com/android/internal/telephony/IMms.aidl
+++ b/telephony/java/com/android/internal/telephony/IMms.aidl
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.content.ContentValues;
 import android.net.Uri;
+import android.os.Bundle;
 
 /**
  * Service interface to handle MMS API requests
@@ -29,7 +30,8 @@
      *
      * @param subId the SIM id
      * @param callingPkg the package name of the calling app
-     * @param pdu the MMS message encoded in standard MMS PDU format
+     * @param contentUri the content uri from which to read MMS message encoded in standard MMS
+     *  PDU format
      * @param locationUrl the optional location url for where this message should be sent to
      * @param configOverrides the carrier-specific messaging configuration values to override for
      *  sending the message. See {@link android.telephony.MessagingConfigurationManager} for the
@@ -37,8 +39,8 @@
      * @param sentIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is successfully sent, or failed
      */
-    void sendMessage(long subId, String callingPkg, in byte[] pdu, String locationUrl,
-            in ContentValues configOverrides, in PendingIntent sentIntent);
+    void sendMessage(long subId, String callingPkg, in Uri contentUri,
+            String locationUrl, in Bundle configOverrides, in PendingIntent sentIntent);
 
     /**
      * Download an MMS message using known location and transaction id
@@ -47,6 +49,7 @@
      * @param callingPkg the package name of the calling app
      * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained
      *  from the MMS WAP push notification
+     * @param contentUri a contentUri to which the downloaded MMS message will be written
      * @param configOverrides the carrier-specific messaging configuration values to override for
      *  downloading the message. See {@link android.telephony.MessagingConfigurationManager} for the
      *  value names and types.
@@ -54,7 +57,8 @@
      *  broadcast when the message is downloaded, or the download is failed
      */
     void downloadMessage(long subId, String callingPkg, String locationUrl,
-            in ContentValues configOverrides, in PendingIntent downloadedIntent);
+            in Uri contentUri, in Bundle configOverrides,
+            in PendingIntent downloadedIntent);
 
     /**
      * Update the status of a pending (send-by-IP) MMS message handled by the carrier app.
@@ -78,33 +82,11 @@
     void updateMmsDownloadStatus(int messageRef, in byte[] pdu);
 
     /**
-     * Get carrier-dependent configuration value as boolean. For example, if multipart SMS
-     * is supported.
+     * Get carrier-dependent configuration values.
      *
      * @param subId the SIM id
-     * @param name the configuration name
-     * @param defaultValue the default value if fail to find the name
      */
-    boolean getCarrierConfigBoolean(long subId, String name, boolean defaultValue);
-
-    /**
-     * Get carrier-dependent configuration value as int. For example, the MMS message size limit.
-     *
-     * @param subId the SIM id
-     * @param name the configuration name
-     * @param defaultValue the default value if fail to find the name
-     */
-    int getCarrierConfigInt(long subId, String name, int defaultValue);
-
-    /**
-     * Get carrier-dependent configuration value as String. For example, extra HTTP headers for
-     * MMS request.
-     *
-     * @param subId the SIM id
-     * @param name the configuration name
-     * @param defaultValue the default value if fail to find the name
-     */
-    String getCarrierConfigString(long subId, String name, String defaultValue);
+    Bundle getCarrierConfigValues(long subId);
 
     /**
      * Import a text message into system's SMS store
@@ -125,14 +107,14 @@
       * Import a multimedia message into system's MMS store
       *
       * @param callingPkg the package name of the calling app
-      * @param pdu the PDU of the message to import
+      * @param contentUri the content uri from which to read PDU of the message to import
       * @param messageId the optional message id
       * @param timestampSecs the message timestamp in seconds
       * @param seen if the message is seen
       * @param read if the message is read
       * @return the message URI, null if failed
       */
-    Uri importMultimediaMessage(String callingPkg, in byte[] pdu, String messageId,
+    Uri importMultimediaMessage(String callingPkg, in Uri contentUri, String messageId,
             long timestampSecs, boolean seen, boolean read);
 
     /**
@@ -189,10 +171,10 @@
      * Add a multimedia message draft to system MMS store
      *
      * @param callingPkg the package name of the calling app
-     * @param pdu the PDU data of the draft MMS
+     * @param contentUri the content Uri from which to read PDU data of the draft MMS
      * @return the URI of the stored draft message
      */
-    Uri addMultimediaMessageDraft(String callingPkg, in byte[] pdu);
+    Uri addMultimediaMessageDraft(String callingPkg, in Uri contentUri);
 
     /**
      * Send a system stored MMS message
@@ -210,7 +192,7 @@
      *  broadcast when the message is successfully sent, or failed
      */
     void sendStoredMessage(long subId, String callingPkg, in Uri messageUri,
-            in ContentValues configOverrides, in PendingIntent sentIntent);
+            in Bundle configOverrides, in PendingIntent sentIntent);
 
     /**
      * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6021ccf..46d0660 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -1,18 +1,18 @@
 /*
-* Copyright (C) 2011-2014 MediaTek Inc.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ * 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.telephony;
 
@@ -22,7 +22,6 @@
 interface ISub {
     /**
      * Get the SubInfoRecord according to an index
-     * @param context Context provided by caller
      * @param subId The unique SubInfoRecord index in database
      * @return SubInfoRecord, maybe null
      */
@@ -30,7 +29,6 @@
 
     /**
      * Get the SubInfoRecord according to an IccId
-     * @param context Context provided by caller
      * @param iccId the IccId of SIM card
      * @return SubInfoRecord, maybe null
      */
@@ -38,7 +36,6 @@
 
     /**
      * Get the SubInfoRecord according to slotId
-     * @param context Context provided by caller
      * @param slotId the slot which the SIM is inserted
      * @return SubInfoRecord, maybe null
      */
@@ -46,28 +43,30 @@
 
     /**
      * Get all the SubInfoRecord(s) in subinfo database
-     * @param context Context provided by caller
      * @return Array list of all SubInfoRecords in database, include thsoe that were inserted before
      */
     List<SubInfoRecord> getAllSubInfoList();
 
     /**
      * Get the SubInfoRecord(s) of the currently inserted SIM(s)
-     * @param context Context provided by caller
      * @return Array list of currently inserted SubInfoRecord(s)
      */
-    List<SubInfoRecord> getActivatedSubInfoList();
+    List<SubInfoRecord> getActiveSubInfoList();
 
     /**
      * Get the SUB count of all SUB(s) in subinfo database
-     * @param context Context provided by caller
      * @return all SIM count in database, include what was inserted before
      */
     int getAllSubInfoCount();
 
     /**
+     * Get the count of active SUB(s)
+     * @return active SIM count
+     */
+    int getActiveSubInfoCount();
+
+    /**
      * Add a new SubInfoRecord to subinfo database if needed
-     * @param context Context provided by caller
      * @param iccId the IccId of the SIM card
      * @param slotId the slot which the SIM is inserted
      * @return the URL of the newly created row or the updated row
@@ -76,7 +75,6 @@
 
     /**
      * Set SIM color by simInfo index
-     * @param context Context provided by caller
      * @param color the color of the SIM
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
@@ -85,7 +83,6 @@
 
     /**
      * Set display name by simInfo index
-     * @param context Context provided by caller
      * @param displayName the display name of SIM card
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
@@ -94,7 +91,6 @@
 
     /**
      * Set display name by simInfo index with name source
-     * @param context Context provided by caller
      * @param displayName the display name of SIM card
      * @param subId the unique SubInfoRecord index in database
      * @param nameSource, 0: DEFAULT_SOURCE, 1: SIM_SOURCE, 2: USER_INPUT
@@ -104,16 +100,14 @@
 
     /**
      * Set phone number by subId
-     * @param context Context provided by caller
      * @param number the phone number of the SIM
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
      */
-    int setDispalyNumber(String number, long subId);
+    int setDisplayNumber(String number, long subId);
 
     /**
      * Set number display format. 0: none, 1: the first four digits, 2: the last four digits
-     * @param context Context provided by caller
      * @param format the display format of phone number
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
@@ -122,7 +116,6 @@
 
     /**
      * Set data roaming by simInfo index
-     * @param context Context provided by caller
      * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming
      * @param subId the unique SubInfoRecord index in database
      * @return the number of records updated
@@ -150,4 +143,12 @@
     long getDefaultVoiceSubId();
 
     void setDefaultVoiceSubId(long subId);
+
+    long getDefaultSmsSubId();
+
+    void setDefaultSmsSubId(long subId);
+
+    void clearDefaultsForInactiveSubIds();
+
+    long[] getActiveSubIdList();
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index b4b1ea5..62b5596 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -136,14 +136,6 @@
     /** APN type for IA Emergency PDN */
     public static final String APN_TYPE_EMERGENCY = "emergency";
 
-    // FIXME: This looks to be used as default phoneId, rename
-    // or use SubscriptionManager.DEFAULT_SUB_ID
-    public static final int DEFAULT_SUBSCRIPTION = 0;
-
-    // FIXME: This looks to be used as invalid phoneId, rename
-    // or use SubscriptionManager.INVALID_SUB_ID
-    public static final int INVALID_SUBSCRIPTION = -1;
-
     public static final int RIL_CARD_MAX_APPS    = 8;
 
     public static final int DEFAULT_CARD_INDEX   = 0;
@@ -154,10 +146,14 @@
 
     public static final int MAX_PHONE_COUNT_TRI_SIM = 3;
 
-    public static final String SUBSCRIPTION_KEY  = "subscription";
+    public static final String PHONE_KEY = "phone";
 
     public static final String SLOT_KEY  = "slot";
 
+    // FIXME: This is used to pass a subId via intents, we need to look at its usage, which is
+    // FIXME: extensive, and see if this should be an array of all active subId's or ...?
+    public static final String SUBSCRIPTION_KEY  = "subscription";
+
     public static final String SUB_SETTING  = "subSettings";
 
     public static final int SUB1 = 0;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 85ceefd..e7aca90 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -391,4 +391,14 @@
      */
     public static final String ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED
             = "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED";
+
+    /**
+     * Broadcast Action: The default sms subscription has changed.  This has the following
+     * extra values:</p>
+     * <ul>
+     *   <li><em>subscription</em> - A int, the current sms default subscription.</li>
+     * </ul>
+     */
+    public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED
+            = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
 }
diff --git a/test-runner/src/android/test/ProviderTestCase.java b/test-runner/src/android/test/ProviderTestCase.java
index 1b323cf..4108f34 100644
--- a/test-runner/src/android/test/ProviderTestCase.java
+++ b/test-runner/src/android/test/ProviderTestCase.java
@@ -67,9 +67,8 @@
                 filenamePrefix);
         mProviderContext = new IsolatedContext(mResolver, targetContextWrapper);
 
-        mProvider = mProviderClass.newInstance();
-        mProvider.attachInfoForTesting(mProviderContext, null);
-        assertNotNull(mProvider);
+        mProvider = ProviderTestCase2.createProviderForTest(
+                mProviderContext, mProviderClass, mProviderAuthority);
         mResolver.addProvider(mProviderAuthority, getProvider());
     }
 
@@ -107,8 +106,7 @@
                 resolver, targetContextWrapper);
         DatabaseUtils.createDbFromSqlStatements(context, databaseName, databaseVersion, sql);
 
-        T provider = providerClass.newInstance();
-        provider.attachInfoForTesting(context, null);
+        T provider = ProviderTestCase2.createProviderForTest(context, providerClass, authority);
         resolver.addProvider(authority, provider);
 
         return resolver;
diff --git a/test-runner/src/android/test/ProviderTestCase2.java b/test-runner/src/android/test/ProviderTestCase2.java
index dcd089d..1fa633e 100644
--- a/test-runner/src/android/test/ProviderTestCase2.java
+++ b/test-runner/src/android/test/ProviderTestCase2.java
@@ -19,6 +19,7 @@
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.ProviderInfo;
 import android.content.res.Resources;
 import android.test.mock.MockContext;
 import android.test.mock.MockContentResolver;
@@ -138,14 +139,24 @@
                 getContext(), // The context that file methods are delegated to
                 filenamePrefix);
         mProviderContext = new IsolatedContext(mResolver, targetContextWrapper);
-
-        mProvider = mProviderClass.newInstance();
-        mProvider.attachInfoForTesting(mProviderContext, null);
-        assertNotNull(mProvider);
+        mProvider = createProviderForTest(mProviderContext, mProviderClass, mProviderAuthority);
         mResolver.addProvider(mProviderAuthority, getProvider());
     }
 
     /**
+     * Creates and sets up a new instance of the provider.
+     */
+    static <T extends ContentProvider> T createProviderForTest(
+            Context context, Class<T> providerClass, String authority)
+            throws IllegalAccessException, InstantiationException {
+        T instance = providerClass.newInstance();
+        ProviderInfo providerInfo = new ProviderInfo();
+        providerInfo.authority = authority;
+        instance.attachInfoForTesting(context, providerInfo);
+        return instance;
+    }
+
+    /**
      * Tears down the environment for the test fixture.
      * <p>
      * Calls {@link android.content.ContentProvider#shutdown()} on the
@@ -218,8 +229,7 @@
         Context context = new IsolatedContext(resolver, targetContextWrapper);
         DatabaseUtils.createDbFromSqlStatements(context, databaseName, databaseVersion, sql);
 
-        T provider = providerClass.newInstance();
-        provider.attachInfoForTesting(context, null);
+        T provider = createProviderForTest(context, providerClass, authority);
         resolver.addProvider(authority, provider);
 
         return resolver;
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index cd7d178..5a4e0eb 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -46,7 +46,7 @@
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
-import android.graphics.Bitmap;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.UserHandle;
@@ -403,6 +403,29 @@
     }
 
     @Override
+    public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user,
+            Rect badgeLocation,
+            int badgeDensity) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** @hide */
+    @Override
+    public Drawable getUserBadgeForDensity(UserHandle user, int density) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) {
         throw new UnsupportedOperationException();
     }
diff --git a/tests/UsageStatsTest/Android.mk b/tests/UsageStatsTest/Android.mk
index 69fefeb..5f7467a 100644
--- a/tests/UsageStatsTest/Android.mk
+++ b/tests/UsageStatsTest/Android.mk
@@ -6,6 +6,8 @@
 # Only compile source java files in this apk.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+
 LOCAL_PACKAGE_NAME := UsageStatsTest
 
 include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsTest/res/layout/config_row_item.xml b/tests/UsageStatsTest/res/layout/config_row_item.xml
new file mode 100644
index 0000000..547de04
--- /dev/null
+++ b/tests/UsageStatsTest/res/layout/config_row_item.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingLeft="16dp"
+    android:paddingRight="16dp"/>
diff --git a/tests/UsageStatsTest/res/layout/row_item.xml b/tests/UsageStatsTest/res/layout/row_item.xml
index da50163..4f2bfe4 100644
--- a/tests/UsageStatsTest/res/layout/row_item.xml
+++ b/tests/UsageStatsTest/res/layout/row_item.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:paddingLeft="16dp"
@@ -8,13 +9,10 @@
     <TextView android:id="@android:id/text1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
-        android:layout_centerVertical="true"
+        android:layout_weight="1"
         android:textStyle="bold"/>
 
     <TextView android:id="@android:id/text2"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentRight="true"
-        android:layout_alignBaseline="@android:id/text1"/>
-</RelativeLayout>
+        android:layout_height="wrap_content"/>
+</LinearLayout>
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
index 5f62ad8..31e7c38 100644
--- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
+import android.support.v4.util.CircularArray;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -35,11 +36,14 @@
     private UsageStatsManager mUsageStatsManager;
     private Adapter mAdapter;
     private Handler mHandler = new Handler();
+    private long mLastTime;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
+        mLastTime = System.currentTimeMillis() - USAGE_STATS_PERIOD;
+
         mAdapter = new Adapter();
         setListAdapter(mAdapter);
     }
@@ -59,24 +63,31 @@
     @Override
     public void run() {
         long now = System.currentTimeMillis();
-        long beginTime = now - USAGE_STATS_PERIOD;
-        UsageEvents events = mUsageStatsManager.queryEvents(beginTime, now);
-        mAdapter.update(events);
+        UsageEvents events = mUsageStatsManager.queryEvents(mLastTime, now);
+        long lastEventTime = mAdapter.update(events);
+        if (lastEventTime >= 0) {
+            mLastTime = lastEventTime + 1;
+        }
         mHandler.postDelayed(this, 1000 * 5);
     }
 
     private class Adapter extends BaseAdapter {
+        private static final int MAX_EVENTS = 50;
+        private final CircularArray<UsageEvents.Event> mEvents = new CircularArray<>(MAX_EVENTS);
 
-        private final ArrayList<UsageEvents.Event> mEvents = new ArrayList<>();
-
-        public void update(UsageEvents results) {
-            mEvents.clear();
+        public long update(UsageEvents results) {
+            long lastTimeStamp = -1;
             while (results.hasNextEvent()) {
                 UsageEvents.Event event = new UsageEvents.Event();
                 results.getNextEvent(event);
-                mEvents.add(event);
+                lastTimeStamp = event.getTimeStamp();
+                if (mEvents.size() == MAX_EVENTS) {
+                    mEvents.popLast();
+                }
+                mEvents.addFirst(event);
             }
             notifyDataSetChanged();
+            return lastTimeStamp;
         }
 
         @Override
@@ -85,7 +96,7 @@
         }
 
         @Override
-        public Object getItem(int position) {
+        public UsageEvents.Event getItem(int position) {
             return mEvents.get(position);
         }
 
@@ -95,41 +106,72 @@
         }
 
         @Override
+        public int getItemViewType(int position) {
+            final int eventType = getItem(position).getEventType();
+            if (eventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
+                return 1;
+            }
+            return 0;
+        }
+
+        @Override
         public View getView(int position, View convertView, ViewGroup parent) {
+            final UsageEvents.Event event = getItem(position);
+
             final ViewHolder holder;
             if (convertView == null) {
-                convertView = LayoutInflater.from(UsageLogActivity.this)
-                        .inflate(R.layout.row_item, parent, false);
                 holder = new ViewHolder();
-                holder.packageName = (TextView) convertView.findViewById(android.R.id.text1);
-                holder.state = (TextView) convertView.findViewById(android.R.id.text2);
+
+                if (event.getEventType() == UsageEvents.Event.CONFIGURATION_CHANGE) {
+                    convertView = LayoutInflater.from(UsageLogActivity.this)
+                            .inflate(R.layout.config_row_item, parent, false);
+                    holder.config = (TextView) convertView.findViewById(android.R.id.text1);
+                } else {
+                    convertView = LayoutInflater.from(UsageLogActivity.this)
+                            .inflate(R.layout.row_item, parent, false);
+                    holder.packageName = (TextView) convertView.findViewById(android.R.id.text1);
+                    holder.state = (TextView) convertView.findViewById(android.R.id.text2);
+                }
                 convertView.setTag(holder);
             } else {
                 holder = (ViewHolder) convertView.getTag();
             }
 
-            holder.packageName.setText(mEvents.get(position).getPackageName());
-            String state;
-            switch (mEvents.get(position).getEventType()) {
+            if (holder.packageName != null) {
+                holder.packageName.setText(event.getPackageName());
+            }
+
+            if (holder.state != null) {
+                holder.state.setText(eventToString(event.getEventType()));
+            }
+
+            if (holder.config != null &&
+                    event.getEventType() == UsageEvents.Event.CONFIGURATION_CHANGE) {
+                holder.config.setText(event.getConfiguration().toString());
+            }
+            return convertView;
+        }
+
+        private String eventToString(int eventType) {
+            switch (eventType) {
                 case UsageEvents.Event.MOVE_TO_FOREGROUND:
-                    state = "Foreground";
-                    break;
+                    return "Foreground";
 
                 case UsageEvents.Event.MOVE_TO_BACKGROUND:
-                    state = "Background";
-                    break;
+                    return "Background";
+
+                case UsageEvents.Event.CONFIGURATION_CHANGE:
+                    return "Config change";
 
                 default:
-                    state = "Unknown: " + mEvents.get(position).getEventType();
-                    break;
+                    return "Unknown: " + eventType;
             }
-            holder.state.setText(state);
-            return convertView;
         }
     }
 
     static class ViewHolder {
         public TextView packageName;
         public TextView state;
+        public TextView config;
     }
 }
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index 1f01461..4639114 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -92,7 +92,7 @@
                 break;
             case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNENROLLED:
                 Log.i(TAG, "STATE_KEYPHRASE_UNENROLLED");
-                Intent enroll = mHotwordDetector.createIntentToEnroll();
+                Intent enroll = mHotwordDetector.createEnrollIntent();
                 Log.i(TAG, "Need to enroll with " + enroll);
                 break;
             case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED:
diff --git a/tools/layoutlib/.idea/libraries/asm_4_0.xml b/tools/layoutlib/.idea/libraries/asm_4_0.xml
index 578a7bf..7df287f 100644
--- a/tools/layoutlib/.idea/libraries/asm_4_0.xml
+++ b/tools/layoutlib/.idea/libraries/asm_4_0.xml
@@ -1,11 +1,11 @@
 <component name="libraryTable">
   <library name="asm-4.0">
     <CLASSES>
-      <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/asm/asm-4.0.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/asm/asm-4.0.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/asm/src.zip!/" />
+      <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/asm/src.zip!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/framework_jar.xml b/tools/layoutlib/.idea/libraries/framework_jar.xml
index 11f5b89..6695a36 100644
--- a/tools/layoutlib/.idea/libraries/framework_jar.xml
+++ b/tools/layoutlib/.idea/libraries/framework_jar.xml
@@ -1,13 +1,13 @@
 <component name="libraryTable">
   <library name="framework.jar">
     <CLASSES>
-      <root url="jar://$ANDROID_BUILD_TOP$/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="file://$ANDROID_BUILD_TOP$/frameworks/base/core/java" />
-      <root url="file://$ANDROID_BUILD_TOP$/frameworks/base/graphics/java" />
-      <root url="file://$ANDROID_BUILD_TOP$/libcore/luni/src/main/java" />
+      <root url="file://$PROJECT_DIR$/../../core/java" />
+      <root url="file://$PROJECT_DIR$/../../graphics/java" />
+      <root url="file://$PROJECT_DIR$/../../../../libcore/luni/src/main/java" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/guava.xml b/tools/layoutlib/.idea/libraries/guava.xml
index de5607e..d47fc06 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://$ANDROID_BUILD_TOP$/out/host/common/obj/JAVA_LIBRARIES/guavalib_intermediates/javalib.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/guavalib_intermediates/javalib.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="file://$ANDROID_BUILD_TOP$/external/guava/guava/src" />
+      <root url="file://$PROJECT_DIR$/../../../../external/guava/guava/src" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/icu4j.xml b/tools/layoutlib/.idea/libraries/icu4j.xml
index 8d9a318..dbe0bd7 100644
--- a/tools/layoutlib/.idea/libraries/icu4j.xml
+++ b/tools/layoutlib/.idea/libraries/icu4j.xml
@@ -1,7 +1,7 @@
 <component name="libraryTable">
   <library name="icu4j">
     <CLASSES>
-      <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/icu4j/icu4j.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/icu4j/icu4j.jar!/" />
     </CLASSES>
     <JAVADOC>
       <root url="http://icu-project.org/apiref/icu4j50rc/" />
diff --git a/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml b/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml
index 91feaea..2a65050 100644
--- a/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml
+++ b/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml
@@ -1,11 +1,11 @@
 <component name="libraryTable">
   <library name="kxml2-2.3.0">
     <CLASSES>
-      <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/kxml2/kxml2-2.3.0.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/kxml2/kxml2-2.3.0.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="file://$ANDROID_BUILD_TOP$/libcore/xml/src/main/java" />
+      <root url="file://$PROJECT_DIR$/../../../../libcore/xml/src/main/java" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml b/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml
index be928da..5952002 100644
--- a/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml
+++ b/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml
@@ -1,7 +1,7 @@
 <component name="libraryTable">
   <library name="layoutlib_api-prebuilt">
     <CLASSES>
-      <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
diff --git a/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml b/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml
index 338137b..f34f7dd 100644
--- a/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml
+++ b/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml
@@ -1,7 +1,7 @@
 <component name="libraryTable">
   <library name="ninepatch-prebuilt">
     <CLASSES>
-      <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
diff --git a/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml b/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml
index 6479886..b325ad4 100644
--- a/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml
+++ b/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml
@@ -4,7 +4,7 @@
       <root url="file://$PROJECT_DIR$" />
     </ANNOTATIONS>
     <CLASSES>
-      <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar!/" />
+      <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/tools-common/tools-common-prebuilt.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
diff --git a/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml b/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml
index badbbab..f965ba7 100644
--- a/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml
+++ b/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml
@@ -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 -Dplatform.dir=&quot;$ANDROID_BUILD_TOP$/out/host/linux-x86/sdk/sdk/android-sdk_eng.deepanshu_linux-x86/platforms/android-L&quot; -Dtest_res.dir=&quot;$PROJECT_DIR$/bridge/tests/res&quot;" />
+    <option name="VM_PARAMETERS" value="-ea -Dtest_res.dir=&quot;$PROJECT_DIR$/bridge/tests/res&quot;" />
     <option name="PARAMETERS" value="" />
     <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
     <option name="ENV_VARIABLES" />
diff --git a/tools/layoutlib/.idea/runConfigurations/Create.xml b/tools/layoutlib/.idea/runConfigurations/Create.xml
index e62925b..fb0b866 100644
--- a/tools/layoutlib/.idea/runConfigurations/Create.xml
+++ b/tools/layoutlib/.idea/runConfigurations/Create.xml
@@ -4,7 +4,7 @@
     <option name="MAIN_CLASS_NAME" value="com.android.tools.layoutlib.create.Main" />
     <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://$ANDROID_BUILD_TOP$/" />
+    <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="ENABLE_SWING_INSPECTOR" value="false" />
diff --git a/tools/layoutlib/.idea/vcs.xml b/tools/layoutlib/.idea/vcs.xml
index 8114960..9ab281a 100644
--- a/tools/layoutlib/.idea/vcs.xml
+++ b/tools/layoutlib/.idea/vcs.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="VcsDirectoryMappings">
-    <mapping directory="$ANDROID_BUILD_TOP$/frameworks/base" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
   </component>
 </project>
 
diff --git a/tools/layoutlib/bridge/bridge.iml b/tools/layoutlib/bridge/bridge.iml
index 7553b59..0f96916 100644
--- a/tools/layoutlib/bridge/bridge.iml
+++ b/tools/layoutlib/bridge/bridge.iml
@@ -34,11 +34,11 @@
     <orderEntry type="module-library" scope="TEST">
       <library>
         <CLASSES>
-          <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/sdk-common/sdk-common.jar!/" />
+          <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/sdk-common/sdk-common.jar!/" />
         </CLASSES>
         <JAVADOC />
         <SOURCES>
-          <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/sdk-common/sdk-common-sources.jar!/" />
+          <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/sdk-common/sdk-common-sources.jar!/" />
         </SOURCES>
       </library>
     </orderEntry>
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 5b69681..fbe21a8 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -90,9 +90,16 @@
         // fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt
         // first count the array size
         int count = 0;
-        for (ResourceValue data : mResourceData) {
-            if (data != null && !RenderResources.REFERENCE_NULL.equals(data.getValue())) {
-                count++;
+        for (int i = 0; i < mResourceData.length; i++) {
+            ResourceValue data = mResourceData[i];
+            if (data != null) {
+                if (RenderResources.REFERENCE_NULL.equals(data.getValue())) {
+                    // No need to store this resource value. This saves needless checking for
+                    // "@null" every time  an attribute is requested.
+                    mResourceData[i] = null;
+                } else {
+                    count++;
+                }
             }
         }
 
@@ -103,8 +110,7 @@
         // fill the array with the indices.
         int index = 1;
         for (int i = 0 ; i < mResourceData.length ; i++) {
-            if (mResourceData[i] != null
-                    && !RenderResources.REFERENCE_NULL.equals(mResourceData[i].getValue())) {
+            if (mResourceData[i] != null) {
                 mIndices[index++] = i;
             }
         }
@@ -215,10 +221,6 @@
 
         String s = mResourceData[index].getValue();
 
-        if (RenderResources.REFERENCE_NULL.equals(s)) {
-            return defValue;
-        }
-
         if (s == null || s.length() == 0) {
             return defValue;
         }
@@ -231,6 +233,20 @@
 
         // Field is not null and is not an integer.
         // Check for possible constants and try to find them.
+        return (int) resolveEnumAttribute(index, defValue);
+    }
+
+    /**
+     * Searches for the string in the attributes (flag or enums) and returns the integer.
+     * If found, it will return an integer matching the value. However, if the value is not found,
+     * it returns {@code defValue} which may be a float.
+     *
+     * @param index Index of attribute to retrieve.
+     * @param defValue Value to return if the attribute is not found.
+     *
+     * @return Attribute int value, or defValue if not defined.
+     */
+    private float resolveEnumAttribute(int index, float defValue) {
         // Get the map of attribute-constant -> IntegerValue
         Map<String, Integer> map = null;
         if (mIsFramework[index]) {
@@ -249,7 +265,7 @@
             int result = 0;
 
             // split the value in case this is a mix of several flags.
-            String[] keywords = s.split("\\|");
+            String[] keywords = mResourceData[index].getValue().split("\\|");
             for (String keyword : keywords) {
                 Integer i = map.get(keyword.trim());
                 if (i != null) {
@@ -258,7 +274,7 @@
                     Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                             String.format(
                                 "\"%s\" in attribute \"%2$s\" is not a valid value",
-                                keyword, mNames[index]), null /*data*/);
+                                keyword, mNames[index]), null);
                 }
             }
             return result;
@@ -293,7 +309,7 @@
                 Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                         String.format(
                             "\"%s\" in attribute \"%2$s\" cannot be converted to float.",
-                            s, mNames[index]), null /*data*/);
+                            s, mNames[index]), null);
 
                 // we'll return the default value below.
             }
@@ -358,10 +374,6 @@
             return null;
         }
 
-        if (RenderResources.REFERENCE_NULL.equals(value)) {
-            return null;
-        }
-
         // let the framework inflate the ColorStateList from the XML file.
         File f = new File(value);
         if (f.isFile()) {
@@ -377,13 +389,13 @@
                 }
             } catch (XmlPullParserException e) {
                 Bridge.getLog().error(LayoutLog.TAG_BROKEN,
-                        "Failed to configure parser for " + value, e, null /*data*/);
+                        "Failed to configure parser for " + value, e, null);
                 return null;
             } catch (Exception e) {
                 // this is an error and not warning since the file existence is checked before
                 // attempting to parse it.
                 Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
-                        "Failed to parse file " + value, e, null /*data*/);
+                        "Failed to parse file " + value, e, null);
 
                 return null;
             }
@@ -393,7 +405,7 @@
             int color = ResourceHelper.getColor(value);
             return ColorStateList.valueOf(color);
         } catch (NumberFormatException e) {
-            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null /*data*/);
+            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null);
         }
 
         return null;
@@ -443,26 +455,15 @@
 
         if (s == null) {
             return defValue;
-        } else if (s.equals(BridgeConstants.MATCH_PARENT) ||
-                s.equals(BridgeConstants.FILL_PARENT)) {
-            return LayoutParams.MATCH_PARENT;
-        } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
-            return LayoutParams.WRAP_CONTENT;
-        } else if (RenderResources.REFERENCE_NULL.equals(s)) {
-            return defValue;
         }
 
-        if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true /*requireUnit*/)) {
+        if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
             return mValue.getDimension(mBridgeResources.getDisplayMetrics());
         }
 
-        // looks like we were unable to resolve the dimension value
-        Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
-                String.format(
-                    "\"%1$s\" in attribute \"%2$s\" is not a valid format.",
-                    s, mNames[index]), null /*data*/);
-
-        return defValue;
+        // looks like we were unable to resolve the dimension value. Check if it is an attribute
+        // constant.
+        return resolveEnumAttribute(index, defValue);
     }
 
     /**
@@ -518,7 +519,7 @@
                     Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                             String.format(
                                 "\"%1$s\" in attribute \"%2$s\" is not a valid format.",
-                                s, mNames[index]), null /*data*/);
+                                s, mNames[index]), null);
                 }
             }
 
@@ -575,11 +576,9 @@
             return LayoutParams.MATCH_PARENT;
         } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
             return LayoutParams.WRAP_CONTENT;
-        } else if (RenderResources.REFERENCE_NULL.equals(s)) {
-            throw new RuntimeException();
         }
 
-        if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true /*requireUnit*/)) {
+        if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
             float f = mValue.getDimension(mBridgeResources.getDisplayMetrics());
 
             final int res = (int)(f+0.5f);
@@ -621,16 +620,15 @@
             return defValue;
         }
 
-        if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue,
-                false /*requireUnit*/)) {
+        if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue, false)) {
             return mValue.getFraction(base, pbase);
         }
 
         // looks like we were unable to resolve the fraction value
         Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                 String.format(
-                    "\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.",
-                    value, mNames[index]), null /*data*/);
+                        "\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.",
+                        value, mNames[index]), null);
 
         return defValue;
     }
@@ -669,10 +667,6 @@
             return mContext.getDynamicIdByStyle((StyleResourceValue)resValue);
         }
 
-        if (RenderResources.REFERENCE_NULL.equals(resValue.getValue())) {
-            return defValue;
-        }
-
         // if the attribute was a reference to a resource, and not a declaration of an id (@+id),
         // then the xml attribute value was "resolved" which leads us to a ResourceValue with a
         // valid getType() and getName() returning a resource name.
@@ -782,7 +776,7 @@
 
         ResourceValue value = mResourceData[index];
         String stringValue = value.getValue();
-        if (stringValue == null || RenderResources.REFERENCE_NULL.equals(stringValue)) {
+        if (stringValue == null) {
             return null;
         }
 
@@ -812,17 +806,13 @@
 
         String value = mResourceData[index].getValue();
         if (value != null) {
-            if (RenderResources.REFERENCE_NULL.equals(value)) {
-                return null;
-            }
-
             return new CharSequence[] { value };
         }
 
         Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                 String.format(
                     String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
-                    index, mResourceData[index].getName())), null /*data*/);
+                    index, mResourceData[index].getName())), null);
 
         return null;
     }
@@ -862,8 +852,7 @@
 
         String s = mResourceData[index].getValue();
 
-        return ResourceHelper.parseFloatAttribute(mNames[index], s, outValue,
-                false /*requireUnit*/);
+        return ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false);
     }
 
     /**
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index adb0937..99ae7c9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -63,11 +63,11 @@
      * Returns the color value represented by the given string value
      * @param value the color value
      * @return the color as an int
-     * @throw NumberFormatException if the conversion failed.
+     * @throws NumberFormatException if the conversion failed.
      */
     public static int getColor(String value) {
         if (value != null) {
-            if (value.startsWith("#") == false) {
+            if (!value.startsWith("#")) {
                 throw new NumberFormatException(
                         String.format("Color value '%s' must start with #", value));
             }
@@ -113,7 +113,7 @@
 
     public static ColorStateList getColorStateList(ResourceValue resValue, BridgeContext context) {
         String value = resValue.getValue();
-        if (value != null && RenderResources.REFERENCE_NULL.equals(value) == false) {
+        if (value != null && !RenderResources.REFERENCE_NULL.equals(value)) {
             // first check if the value is a file (xml most likely)
             File f = new File(value);
             if (f.isFile()) {
@@ -360,7 +360,7 @@
      */
     public static boolean parseFloatAttribute(String attribute, String value,
             TypedValue outValue, boolean requireUnit) {
-        assert requireUnit == false || attribute != null;
+        assert !requireUnit || attribute != null;
 
         // remove the space before and after
         value = value.trim();
@@ -379,7 +379,7 @@
         }
 
         // check the first character
-        if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.' && buf[0] != '-') {
+        if ((buf[0] < '0' || buf[0] > '9') && buf[0] != '.' && buf[0] != '-' && buf[0] != '+') {
             return false;
         }
 
@@ -411,7 +411,7 @@
 
             if (end.length() == 0) {
                 if (outValue != null) {
-                    if (requireUnit == false) {
+                    if (!requireUnit) {
                         outValue.type = TypedValue.TYPE_FLOAT;
                         outValue.data = Float.floatToIntBits(f);
                     } else {
@@ -489,6 +489,8 @@
 
     private static void applyUnit(UnitEntry unit, TypedValue outValue, float[] outScale) {
         outValue.type = unit.type;
+        // COMPLEX_UNIT_SHIFT is 0 and hence intelliJ complains about it. Suppress the warning.
+        //noinspection PointlessBitwiseExpression
         outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT;
         outScale[0] = unit.scale;
     }
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 31b3e25..a2588a6 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
@@ -104,9 +104,61 @@
             return platformDir;
         }
         // System Property not set. Try to find the directory in the build directory.
-        String out = System.getenv("ANDROID_HOST_OUT");
-        if (out == null || out.isEmpty() || !new File(out).isDirectory()) {
-            // Can't find the out directory.
+        String androidHostOut = System.getenv("ANDROID_HOST_OUT");
+        if (androidHostOut != null) {
+            platformDir = getPlatformDirFromHostOut(new File(androidHostOut));
+            if (platformDir != null) {
+                return platformDir;
+            }
+        }
+        String workingDirString = System.getProperty("user.dir");
+        File workingDir = new File(workingDirString);
+        // Test if workingDir is android checkout root.
+        platformDir = getPlatformDirFromRoot(workingDir);
+        if (platformDir != null) {
+            return platformDir;
+        }
+        // Test if workingDir is  platform/frameworks/base/tools/layoutlib. That is, root should be
+        // workingDir/../../../../  (4 levels up)
+        File currentDir = workingDir;
+        for (int i = 0; i < 4; i++) {
+            if (currentDir != null) {
+                currentDir = currentDir.getParentFile();
+            }
+        }
+        return currentDir == null ? null : getPlatformDirFromRoot(currentDir);
+    }
+
+    private static String getPlatformDirFromRoot(File root) {
+        if (!root.isDirectory()) {
+            return null;
+        }
+        File out = new File(root, "out");
+        if (!out.isDirectory()) {
+            return null;
+        }
+        File host = new File(out, "host");
+        if (!host.isDirectory()) {
+            return null;
+        }
+        File[] hosts = host.listFiles(new FileFilter() {
+            @Override
+            public boolean accept(File path) {
+                return path.isDirectory() && (path.getName().startsWith("linux-") || path.getName()
+                        .startsWith("darwin-"));
+            }
+        });
+        for (File hostOut : hosts) {
+            String platformDir = getPlatformDirFromHostOut(hostOut);
+            if (platformDir != null) {
+                return platformDir;
+            }
+        }
+        return null;
+    }
+
+    private static String getPlatformDirFromHostOut(File out) {
+        if (!out.isDirectory()) {
             return null;
         }
         File sdkDir = new File(out, "sdk" + File.separator + "sdk");
@@ -117,7 +169,7 @@
         File[] possibleSdks = sdkDir.listFiles(new FileFilter() {
             @Override
             public boolean accept(File path) {
-                return path.isDirectory() && path.getAbsolutePath().contains("android-sdk");
+                return path.isDirectory() && path.getName().contains("android-sdk");
             }
         });
         for (File possibleSdk : possibleSdks) {
diff --git a/tools/layoutlib/create/tests/Android.mk b/tools/layoutlib/create/tests/Android.mk
new file mode 100644
index 0000000..0052ec2
--- /dev/null
+++ b/tools/layoutlib/create/tests/Android.mk
@@ -0,0 +1,32 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# Only compile source java files in this lib.
+LOCAL_SRC_FILES := $(call all-java-files-under, com)
+
+LOCAL_JAVA_RESOURCE_DIRS := data mock_data
+
+LOCAL_MODULE := layoutlib-create-tests
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JAVA_LIBRARIES := layoutlib_create junit
+LOCAL_STATIC_JAVA_LIBRARIES := asm-4.0
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+# Build all sub-directories
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 397d700..a752686 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -18,7 +18,6 @@
 
 import android.net.wifi.BatchedScanResult;
 import android.net.wifi.BatchedScanSettings;
-import android.net.wifi.WifiAdapter;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.ScanSettings;
@@ -40,9 +39,9 @@
  */
 interface IWifiManager
 {
-    List<WifiAdapter> getAdaptors();
+    int getSupportedFeatures();
 
-    WifiActivityEnergyInfo reportActivityInfo(in WifiAdapter adapter);
+    WifiActivityEnergyInfo reportActivityInfo();
 
     List<WifiConfiguration> getConfiguredNetworks();
 
diff --git a/wifi/java/android/net/wifi/WifiAdapter.aidl b/wifi/java/android/net/wifi/WifiAdapter.aidl
deleted file mode 100644
index 0bb5dd7..0000000
--- a/wifi/java/android/net/wifi/WifiAdapter.aidl
+++ /dev/null
@@ -1,19 +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.net.wifi;
-
-parcelable WifiAdapter;
diff --git a/wifi/java/android/net/wifi/WifiAdapter.java b/wifi/java/android/net/wifi/WifiAdapter.java
deleted file mode 100644
index 0b12dea..0000000
--- a/wifi/java/android/net/wifi/WifiAdapter.java
+++ /dev/null
@@ -1,257 +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.net.wifi;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * Represents local wifi adapter. Different devices have different kinds of
- * wifi adapters; each with different capabilities. Use this class to find out
- * which capabilites are supported by the wifi adapter on the device.
- */
-public class WifiAdapter implements Parcelable {
-    private static final String TAG = "WifiAdapter";
-
-    /* Keep this list in sync with wifi_hal.h */
-    /** @hide */
-    public static final int WIFI_FEATURE_INFRA            = 0x0001;  // Basic infrastructure mode
-    /** @hide */
-    public static final int WIFI_FEATURE_INFRA_5G         = 0x0002;  // Support for 5 GHz Band
-    /** @hide */
-    public static final int WIFI_FEATURE_PASSPOINT        = 0x0004;  // Support for GAS/ANQP
-    /** @hide */
-    public static final int WIFI_FEATURE_P2P              = 0x0008;  // Wifi-Direct
-    /** @hide */
-    public static final int WIFI_FEATURE_MOBILE_HOTSPOT   = 0x0010;  // Soft AP
-    /** @hide */
-    public static final int WIFI_FEATURE_SCANNER          = 0x0020;  // WifiScanner APIs
-    /** @hide */
-    public static final int WIFI_FEATURE_NAN              = 0x0040;  // Neighbor Awareness Networking
-    /** @hide */
-    public static final int WIFI_FEATURE_D2D_RTT          = 0x0080;  // Device-to-device RTT
-    /** @hide */
-    public static final int WIFI_FEATURE_D2AP_RTT         = 0x0100;  // Device-to-AP RTT
-    /** @hide */
-    public static final int WIFI_FEATURE_BATCH_SCAN       = 0x0200;  // Batched Scan (deprecated)
-    /** @hide */
-    public static final int WIFI_FEATURE_PNO              = 0x0400;  // Preferred network offload
-    /** @hide */
-    public static final int WIFI_FEATURE_ADDITIONAL_STA   = 0x0800;  // Support for two STAs
-    /** @hide */
-    public static final int WIFI_FEATURE_TDLS             = 0x1000;  // Tunnel directed link setup
-    /** @hide */
-    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
-
-    private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30;
-    /** @hide */
-    public static final int ACTIVITY_ENERGY_INFO_CACHED = 0;
-    /** @hide */
-    public static final int ACTIVITY_ENERGY_INFO_REFRESHED = 1;
-
-    private String name;
-    private int    supportedFeatures;
-
-    // Make the API consistent with BlueTooth Adaptor, allowing WifiService to be accessed
-    // Directly from the adapter
-    /** @hide */
-    public IWifiManager mService = null;
-
-    /** @hide */
-    public WifiAdapter(String name, int supportedFeatures) {
-        this.name = name;
-        this.supportedFeatures = supportedFeatures;
-    }
-
-    /**
-     * @return name of the adapter
-     */
-    public String getName() {
-        return name;
-    }
-
-    private int getSupportedFeatures() {
-        return supportedFeatures;
-    }
-
-    private boolean isFeatureSupported(int feature) {
-        return (supportedFeatures & feature) == feature;
-    }
-
-    /**
-     * @return true if this adapter supports 5 GHz band
-     */
-    public boolean is5GHzBandSupported() {
-        return isFeatureSupported(WIFI_FEATURE_INFRA_5G);
-    }
-
-    /**
-     * @return true if this adapter supports passpoint
-     */
-    public boolean isPasspointSupported() {
-        return isFeatureSupported(WIFI_FEATURE_PASSPOINT);
-    }
-
-    /**
-     * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct)
-     */
-    public boolean isP2pSupported() {
-        return isFeatureSupported(WIFI_FEATURE_P2P);
-    }
-
-    /**
-     * @return true if this adapter supports portable Wi-Fi hotspot
-     */
-    public boolean isPortableHotspotSupported() {
-        return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT);
-    }
-
-    /**
-     * @return true if this adapter supports WifiScanner APIs
-     */
-    public boolean isWifiScannerSupported() {
-        return isFeatureSupported(WIFI_FEATURE_SCANNER);
-    }
-
-    /**
-     * @return true if this adapter supports Neighbour Awareness Network APIs
-     * @hide
-     */
-    public boolean isNanSupported() {
-        return isFeatureSupported(WIFI_FEATURE_NAN);
-    }
-
-    /**
-     * @return true if this adapter supports Device-to-device RTT
-     */
-    public boolean isDeviceToDeviceRttSupported() {
-        return isFeatureSupported(WIFI_FEATURE_D2D_RTT);
-    }
-
-    /**
-     * @return true if this adapter supports Device-to-AP RTT
-     */
-    public boolean isDeviceToApRttSupported() {
-        return isFeatureSupported(WIFI_FEATURE_D2AP_RTT);
-    }
-
-    /**
-     * @return true if this adapter supports offloaded connectivity scan
-     */
-    public boolean isPreferredNetworkOffloadSupported() {
-        return isFeatureSupported(WIFI_FEATURE_PNO);
-    }
-
-    /**
-     * @return true if this adapter supports multiple simultaneous connections
-     * @hide
-     */
-    public boolean isAdditionalStaSupported() {
-        return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA);
-    }
-
-    /**
-     * @return true if this adapter supports Tunnel Directed Link Setup
-     */
-    public boolean isTdlsSupported() {
-        return isFeatureSupported(WIFI_FEATURE_TDLS);
-    }
-
-    /**
-     * @return true if this adapter supports Off Channel Tunnel Directed Link Setup
-     */
-    public boolean isOffChannelTdlsSupported() {
-        return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL);
-    }
-
-    /**
-     * @return true if this adapter supports advanced power/performance counters
-     */
-    public boolean isEnhancedPowerReportingSupported() {
-        return isFeatureSupported(WIFI_FEATURE_EPR);
-    }
-
-
-    /**
-     * Return the record of {@link WifiActivityEnergyInfo} object that
-     * has the activity and energy info. This can be used to ascertain what
-     * the controller has been up to, since the last sample.
-     * @param updateType Type of info, cached vs refreshed.
-     *
-     * @return a record with {@link WifiActivityEnergyInfo} or null if
-     * report is unavailable or unsupported
-     * @hide
-     */
-    public WifiActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
-        if (mService == null) return null;
-        try {
-            WifiActivityEnergyInfo record;
-            if (!isEnhancedPowerReportingSupported()) {
-                return null;
-            }
-            synchronized(this) {
-                record = mService.reportActivityInfo(this);
-                if (record.isValid()) {
-                    return record;
-                } else {
-                    return null;
-                }
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "getControllerActivityEnergyInfo: " + e);
-        }
-        return null;
-    }
-
-    /* Parcelable implementation */
-    /**
-     * Implement the Parcelable interface
-     * {@hide}
-     */
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * Implement the Parcelable interface
-     * {@hide}
-     */
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(name);
-        dest.writeInt(supportedFeatures);
-    }
-
-    /**
-     * Implement the Parcelable interface
-     * {@hide}
-     */
-    public static final Creator<WifiAdapter> CREATOR =
-            new Creator<WifiAdapter>() {
-                public WifiAdapter createFromParcel(Parcel in) {
-                    WifiAdapter adaptor = new WifiAdapter(in.readString(), in.readInt());
-                    return adaptor;
-                }
-
-                public WifiAdapter[] newArray(int size) {
-                    return new WifiAdapter[size];
-                }
-            };
-}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4a4da22..1393bce 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -576,22 +576,6 @@
     }
 
     /**
-     * Retrieve all wifi adapters available on this device
-     * @return list of adapters
-     */
-    public List<WifiAdapter> getAdapters() {
-        try {
-            List<WifiAdapter> adapterList = mService.getAdaptors();
-            for (WifiAdapter a : adapterList) {
-                a.mService = mService;
-            }
-            return adapterList;
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /**
      * Return a list of all the networks configured in the supplicant.
      * Not all fields of WifiConfiguration are returned. Only the following
      * fields are filled in:
@@ -824,6 +808,182 @@
         }
     }
 
+    /* Keep this list in sync with wifi_hal.h */
+    /** @hide */
+    public static final int WIFI_FEATURE_INFRA            = 0x0001;  // Basic infrastructure mode
+    /** @hide */
+    public static final int WIFI_FEATURE_INFRA_5G         = 0x0002;  // Support for 5 GHz Band
+    /** @hide */
+    public static final int WIFI_FEATURE_PASSPOINT        = 0x0004;  // Support for GAS/ANQP
+    /** @hide */
+    public static final int WIFI_FEATURE_P2P              = 0x0008;  // Wifi-Direct
+    /** @hide */
+    public static final int WIFI_FEATURE_MOBILE_HOTSPOT   = 0x0010;  // Soft AP
+    /** @hide */
+    public static final int WIFI_FEATURE_SCANNER          = 0x0020;  // WifiScanner APIs
+    /** @hide */
+    public static final int WIFI_FEATURE_NAN              = 0x0040;  // Neighbor Awareness Networking
+    /** @hide */
+    public static final int WIFI_FEATURE_D2D_RTT          = 0x0080;  // Device-to-device RTT
+    /** @hide */
+    public static final int WIFI_FEATURE_D2AP_RTT         = 0x0100;  // Device-to-AP RTT
+    /** @hide */
+    public static final int WIFI_FEATURE_BATCH_SCAN       = 0x0200;  // Batched Scan (deprecated)
+    /** @hide */
+    public static final int WIFI_FEATURE_PNO              = 0x0400;  // Preferred network offload
+    /** @hide */
+    public static final int WIFI_FEATURE_ADDITIONAL_STA   = 0x0800;  // Support for two STAs
+    /** @hide */
+    public static final int WIFI_FEATURE_TDLS             = 0x1000;  // Tunnel directed link setup
+    /** @hide */
+    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
+
+    private int getSupportedFeatures() {
+        try {
+            return mService.getSupportedFeatures();
+        } catch (RemoteException e) {
+            return 0;
+        }
+    }
+
+    private boolean isFeatureSupported(int feature) {
+        return (getSupportedFeatures() & feature) == feature;
+    }
+    /**
+     * @return true if this adapter supports 5 GHz band
+     */
+    public boolean is5GHzBandSupported() {
+        return isFeatureSupported(WIFI_FEATURE_INFRA_5G);
+    }
+
+    /**
+     * @return true if this adapter supports passpoint
+     * @hide
+     */
+    public boolean isPasspointSupported() {
+        return isFeatureSupported(WIFI_FEATURE_PASSPOINT);
+    }
+
+    /**
+     * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct)
+     */
+    public boolean isP2pSupported() {
+        return isFeatureSupported(WIFI_FEATURE_P2P);
+    }
+
+    /**
+     * @return true if this adapter supports portable Wi-Fi hotspot
+     * @hide
+     */
+    @SystemApi
+    public boolean isPortableHotspotSupported() {
+        return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT);
+    }
+
+    /**
+     * @return true if this adapter supports WifiScanner APIs
+     * @hide
+     */
+    @SystemApi
+    public boolean isWifiScannerSupported() {
+        return isFeatureSupported(WIFI_FEATURE_SCANNER);
+    }
+
+    /**
+     * @return true if this adapter supports Neighbour Awareness Network APIs
+     * @hide
+     */
+    public boolean isNanSupported() {
+        return isFeatureSupported(WIFI_FEATURE_NAN);
+    }
+
+    /**
+     * @return true if this adapter supports Device-to-device RTT
+     * @hide
+     */
+    @SystemApi
+    public boolean isDeviceToDeviceRttSupported() {
+        return isFeatureSupported(WIFI_FEATURE_D2D_RTT);
+    }
+
+    /**
+     * @return true if this adapter supports Device-to-AP RTT
+     */
+    @SystemApi
+    public boolean isDeviceToApRttSupported() {
+        return isFeatureSupported(WIFI_FEATURE_D2AP_RTT);
+    }
+
+    /**
+     * @return true if this adapter supports offloaded connectivity scan
+     */
+    public boolean isPreferredNetworkOffloadSupported() {
+        return isFeatureSupported(WIFI_FEATURE_PNO);
+    }
+
+    /**
+     * @return true if this adapter supports multiple simultaneous connections
+     * @hide
+     */
+    public boolean isAdditionalStaSupported() {
+        return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA);
+    }
+
+    /**
+     * @return true if this adapter supports Tunnel Directed Link Setup
+     */
+    public boolean isTdlsSupported() {
+        return isFeatureSupported(WIFI_FEATURE_TDLS);
+    }
+
+    /**
+     * @return true if this adapter supports Off Channel Tunnel Directed Link Setup
+     * @hide
+     */
+    public boolean isOffChannelTdlsSupported() {
+        return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL);
+    }
+
+    /**
+     * @return true if this adapter supports advanced power/performance counters
+     */
+    public boolean isEnhancedPowerReportingSupported() {
+        return isFeatureSupported(WIFI_FEATURE_EPR);
+    }
+
+    /**
+     * Return the record of {@link WifiActivityEnergyInfo} object that
+     * has the activity and energy info. This can be used to ascertain what
+     * the controller has been up to, since the last sample.
+     * @param updateType Type of info, cached vs refreshed.
+     *
+     * @return a record with {@link WifiActivityEnergyInfo} or null if
+     * report is unavailable or unsupported
+     * @hide
+     */
+    public WifiActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
+        if (mService == null) return null;
+        try {
+            WifiActivityEnergyInfo record;
+            if (!isEnhancedPowerReportingSupported()) {
+                return null;
+            }
+            synchronized(this) {
+                record = mService.reportActivityInfo();
+                if (record.isValid()) {
+                    return record;
+                } else {
+                    return null;
+                }
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "getControllerActivityEnergyInfo: " + e);
+        }
+        return null;
+    }
+
     /**
      * Request a scan for access points. Returns immediately. The availability
      * of the results is made known later by means of an asynchronous event sent
@@ -840,6 +1000,7 @@
     }
 
     /** @hide */
+    @SystemApi
     public boolean startScan(WorkSource workSource) {
         try {
             mService.startScan(null, workSource);
@@ -913,6 +1074,7 @@
      * @return false if not supported.
      * @hide
      */
+    @SystemApi
     public boolean isBatchedScanSupported() {
         try {
             return mService.isBatchedScanSupported();
@@ -939,6 +1101,7 @@
      * {@link BATCHED_SCAN_RESULTS_AVAILABLE_ACTION} is received.
      * @hide
      */
+    @SystemApi
     public List<BatchedScanResult> getBatchedScanResults() {
         try {
             return mService.getBatchedScanResults(mContext.getOpPackageName());
@@ -1457,12 +1620,14 @@
     /**
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the operation failed due to an internal error.
+     * @hide
      */
     public static final int ERROR                       = 0;
 
     /**
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the operation is already in progress
+     * @hide
      */
     public static final int IN_PROGRESS                 = 1;
 
@@ -1470,6 +1635,7 @@
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the operation failed because the framework is busy and
      * unable to service the request
+     * @hide
      */
     public static final int BUSY                        = 2;
 
@@ -1488,18 +1654,21 @@
     /**
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the operation failed due to invalid inputs
+     * @hide
      */
     public static final int INVALID_ARGS                = 8;
 
     /**
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the operation failed due to user permissions.
-     *
      * @hide
      */
     public static final int NOT_AUTHORIZED              = 9;
 
-    /** Interface for callback invocation on an application action */
+    /**
+     * Interface for callback invocation on an application action
+     * @hide
+     */
     public interface ActionListener {
         /** The operation succeeded */
         public void onSuccess();
@@ -1512,19 +1681,21 @@
     }
 
     /** Interface for callback invocation on a start WPS action */
-    public interface WpsListener {
+    public static abstract class WpsCallback {
         /** WPS start succeeded */
-        public void onStartSuccess(String pin);
+        public abstract void onStarted(String pin);
 
         /** WPS operation completed succesfully */
-        public void onCompletion();
+        public abstract void onSucceeded();
 
         /**
          * WPS operation failed
          * @param reason The reason for failure could be one of
-         * {@link #IN_PROGRESS}, {@link #WPS_OVERLAP_ERROR},{@link #ERROR} or {@link #BUSY}
+         * {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR},
+         * {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE}
+         * and some generic errors.
          */
-        public void onFailure(int reason);
+        public abstract void onFailed(int reason);
     }
 
     /** Interface for callback invocation on a TX packet count poll action {@hide} */
@@ -1576,7 +1747,6 @@
                 case WifiManager.CONNECT_NETWORK_FAILED:
                 case WifiManager.FORGET_NETWORK_FAILED:
                 case WifiManager.SAVE_NETWORK_FAILED:
-                case WifiManager.CANCEL_WPS_FAILED:
                 case WifiManager.DISABLE_NETWORK_FAILED:
                     if (listener != null) {
                         ((ActionListener) listener).onFailure(message.arg1);
@@ -1586,7 +1756,6 @@
                 case WifiManager.CONNECT_NETWORK_SUCCEEDED:
                 case WifiManager.FORGET_NETWORK_SUCCEEDED:
                 case WifiManager.SAVE_NETWORK_SUCCEEDED:
-                case WifiManager.CANCEL_WPS_SUCCEDED:
                 case WifiManager.DISABLE_NETWORK_SUCCEEDED:
                     if (listener != null) {
                         ((ActionListener) listener).onSuccess();
@@ -1595,7 +1764,7 @@
                 case WifiManager.START_WPS_SUCCEEDED:
                     if (listener != null) {
                         WpsResult result = (WpsResult) message.obj;
-                        ((WpsListener) listener).onStartSuccess(result.pin);
+                        ((WpsCallback) listener).onStarted(result.pin);
                         //Listener needs to stay until completion or failure
                         synchronized(sListenerMapLock) {
                             sListenerMap.put(message.arg2, listener);
@@ -1604,12 +1773,22 @@
                     break;
                 case WifiManager.WPS_COMPLETED:
                     if (listener != null) {
-                        ((WpsListener) listener).onCompletion();
+                        ((WpsCallback) listener).onSucceeded();
                     }
                     break;
                 case WifiManager.WPS_FAILED:
                     if (listener != null) {
-                        ((WpsListener) listener).onFailure(message.arg1);
+                        ((WpsCallback) listener).onFailed(message.arg1);
+                    }
+                    break;
+                case WifiManager.CANCEL_WPS_SUCCEDED:
+                    if (listener != null) {
+                        ((WpsCallback) listener).onSucceeded();
+                    }
+                    break;
+                case WifiManager.CANCEL_WPS_FAILED:
+                    if (listener != null) {
+                        ((WpsCallback) listener).onFailed(message.arg1);
                     }
                     break;
                 case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
@@ -1794,7 +1973,7 @@
      * @throws IllegalStateException if the WifiManager instance needs to be
      * initialized again
      */
-    public void startWps(WpsInfo config, WpsListener listener) {
+    public void startWps(WpsInfo config, WpsCallback listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
         validateChannel();
         sAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config);
@@ -1807,7 +1986,7 @@
      * @throws IllegalStateException if the WifiManager instance needs to be
      * initialized again
      */
-    public void cancelWps(ActionListener listener) {
+    public void cancelWps(WpsCallback listener) {
         validateChannel();
         sAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener));
     }
@@ -2352,4 +2531,7 @@
             return 0;
         }
     }
+
+
+
 }